Rails after_save 回调未触发

Posted

技术标签:

【中文标题】Rails after_save 回调未触发【英文标题】:Rails after_save callback not firing 【发布时间】:2014-12-23 23:15:52 【问题描述】:

我有下面的代码可以很好地删除记录,但是在尝试使用 after_save 回调将记录插入表中时,什么都不做。

本质上,我正在做的是创建一系列高级关系,这些关系应该在campaign_category_metro_bids 表中创建或删除关系。如果我在 phpMyAdmin 中运行就没有问题。但是在rails中点击并激活只允许调用第二个回调,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

我怎样才能让它工作?

【问题讨论】:

【参考方案1】:

问题是在after_save 上,将在数据库上创建记录的事务尚未提交,因此记录还没有真正存在。你必须使用after_commit

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

【讨论】:

我试过了,没用。我在通过 SQL 调用创建的表上使用回调,而不是活动记录 你能在保存/提交回调后得到任何在那个模型中运行吗?如果这是通过在广告系列中添加 Metro 来隐式创建的,反之亦然,那么这就是问题所在,我们可以探索解决方案 我将整个过程移到了一个正在使用活动记录创建的模型中,并且它完全按照应有的方式运行。没问题 这些型号和has_and_belongs_to_many有关系吗?如果是这样,那么您可以尝试使用has_many :through guides.rubyonrails.org/…

以上是关于Rails after_save 回调未触发的主要内容,如果未能解决你的问题,请参考以下文章

具有虚拟属性的 after_save 回调 Rails 3

Rails ActiveRecord 在 after_save 回调中使用最近保存的记录 ID [关闭]

Rails - 如何从after_save回调中查看旧模型值和新模型值?

Rails after_save 错误

插入后的 Rails 回调

数据库触发器与 Rails ActiveRecord 回调的优缺点?