繁体   English   中英

验证失败时如何不回滚ActiveRecord事务

[英]How to not rollback a ActiveRecord transaction in case of failed validation

所以我在Rails应用程序上有一个模型,其中有一个名称字段。 在数据库中,此字段具有针对它的唯一约束集。 在模型级别,我还在做uniqueness: { case_sensitive: false }, on: :create检查。

我的想法是,在完成ActiveRecord验证之后,如果唯一性检查失败,那么我想为同一表中所有准备就绪的现有记录增加一个计数器。 所以我现在要做的是:

after_validation :term_exists

    private
    def term_exists
        if self.errors.added? :name, :taken
            Term.where('LOWER(name) = LOWER(?)', self[:name]).update_all('popularity_counter = popularity_counter + 1')
        end
    end

这将很棒,但是当我对其进行测试时,计数器永远不会增加。 我想这是因为一旦验证失败,该事务中的所有内容都会回滚。

但是,解决这种问题的正确方法是什么? 强烈建议不要在控制器中保留此类逻辑。

如果使用MySQL,则可以改用INSERT ... ON DUPLICATE KEY UPDATE ... (请参阅docs )。 为此,您必须为name列添加唯一索引。 在这种情况下,您不需要任何唯一性验证。

还有一个很有前途的宝石,称为upsert (这是“更新而不是插入”的常用缩写),但它尚不支持更新其他列(例如,计数器)而不是更新插入的值。 不过,您可以观看此问题

我要说的是,您需要创建自定义的before_validation方法,可以在其中检查名称是否唯一,如果不是,则更新计数器,然后使验证失败。

在这种情况下,您可以删除Rails的uniqueness: { case_sensitive: false }, on: :create因为它显然不能满足您的要求。

我认为这是我想到的最干净的方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM