Обратный вызов Rails after_save не срабатывает

У меня есть приведенный ниже код, который отлично работает для удаления записи, но при попытке вставить записи в таблицу с использованием обратного вызова after_save ничего не происходит.

По сути, я создаю ряд расширенных отношений, которые должны создавать или удалять отношения из таблицы кампания_категория_метро_бидс. Если я запускаю PHPMyAdmin, проблем не возникает. Но щелчок и активация в рельсах позволяет вызывать только второй обратный вызов, after_destroy...

 class CampaignMetro < ActiveRecord::Base

    belongs_to :campaign
    belongs_to :metro

    after_destroy :destroy_category_campaign_metro_bid
    after_save    :create_category_campaign_metro_bid

    def create_category_campaign_metro_bid
        insert = "INSERT INTO campaign_category_metro_bids (campaign_id,category_id, metro_id, created_at, updated_at)
                    SELECT e.campaign_id, e.category_id, e.metro_id, NOW(), NOW()
                    FROM
                    (SELECT c.campaign_id, c.category_id, c.metro_id
                     FROM (SELECT a.campaign_id, a.category_id, b.metro_id
                           FROM campaign_categories a 
                           cross join campaign_metros b 
                           ON a.campaign_id = b.campaign_id) c) e
                    LEFT JOIN campaign_category_metro_bids d
                    ON d.campaign_id = e.campaign_id and
                       d.category_id = e.category_id and
                       d.metro_id    = e.metro_id
                    WHERE d.campaign_id is null and 
                          d.category_id is null and 
                          d.metro_id    is null;"

        ActiveRecord::Base.connection.execute(insert)
    end

    def destroy_category_campaign_metro_bid
        delete="DELETE d.*
                FROM campaign_category_metro_bids d
                LEFT JOIN
                (SELECT c.campaign_id, c.category_id, c.metro_id
                 FROM (SELECT a.campaign_id, a.category_id, b.metro_id
                       FROM campaign_categories a 
                       cross join campaign_metros b 
                       ON a.campaign_id = b.campaign_id) c) e
                ON d.campaign_id = e.campaign_id and
                   d.category_id = e.category_id and
                   d.metro_id    = e.metro_id
                WHERE e.campaign_id is null and 
                      e.category_id is null and 
                      e.metro_id    is null;"

        ActiveRecord::Base.connection.execute(delete)
    end
end

Как я могу заставить это работать?


person Sauron    schedule 23.12.2014    source источник


Ответы (1)


Проблема в том, что after_save транзакция, которая создаст запись в базе данных, еще не была зафиксирована, поэтому записи на самом деле еще нет. Вы должны использовать after_commit.

http://apidock.com/rails/ActiveRecord/Transactions/ClassMethods/after_commit

person rafb3    schedule 23.12.2014
comment
Я пробовал это, это не сработало. Я использую обратные вызовы для таблицы, которая создается с помощью вызовов SQL, а не активной записи. - person Sauron; 24.12.2014
comment
Можете ли вы получить какой-либо обратный вызов после сохранения/фиксации для запуска в этой модели? Если это создается неявным образом путем добавления метро в кампанию или наоборот, тогда это будет проблемой, и мы можем найти решения для этого. - person rafb3; 24.12.2014
comment
Я переместил весь процесс в модель, которая создается с активной записью, и она работает именно так, как должна. Нет проблем - person Sauron; 24.12.2014
comment
Эти модели связаны с has_and_belongs_to_many? Если да, то вы можете попробовать использовать has_many :through guides.rubyonrails.org / - person rafb3; 24.12.2014