代码之家  ›  专栏  ›  技术社区  ›  James A. Rosen

如何在activerecord事务中获取save(无感叹号)语义?

  •  3
  • James A. Rosen  · 技术社区  · 15 年前

    我有两个模型: Person Address 我想在交易中创建。也就是说,我想尝试创建 如果成功,创建相关的 地址 . 我想用 save 语义(返回 true false )而不是 save! 语义(提出 ActiveRecord::StatementInvalid 或不)。

    这不起作用,因为 user.save 不会触发事务回滚:

    class Person
      def save_with_address(address_options = {})
        transaction do
          self.save
          address = Address.build(address_options)
          address.person = self
          address.save
        end
      end
    end
    

    (更改 self.save 打电话给某人 if self.save 其他的街区也没用,因为 即使 地址 一个失败了。

    但这不起作用,因为它提高了 activerecord::语句无效 例外情况 transaction 阻止而不触发 ActiveRecord::Rollback :

    class Person
      def save_with_address(address_options = {})
        transaction do
          save!
          address = Address.build(address_options)
          address.person = self
          address.save!
        end
      end
    end
    

    这个 Rails documentation 特别警告不要抓到 activerecord::语句无效 里面 交易 块。

    我想我的第一个问题是:为什么这个事务块不…两次保存都要处理?

    2 回复  |  直到 15 年前
        1
  •  5
  •   Harish Shetty    15 年前

    这个怎么样?

    class Person
      def save_with_address(address_options = {})
        tx_error = false
        transaction do
          begin
            self.save!
            address = Address.build(address_options)
            address.person = self
            address.save!
          rescue Exception => e
            # add relevant error message to self using errors.add_to_base
            raise ActiveRecord::Rollback 
            tx_error = true 
          end
        end
        return true unless tx_error
    
        # now roll back the Person TX.
        raise ActiveRecord::Rollback
        return false
      end
    end
    

    我不喜欢TX的实现方式。但这是你解决问题的方法。

        2
  •  0
  •   François Beausoleil    15 年前

    告诉activerecord帮你做这个。帮你解决了一大堆问题:

    class Person < ActiveRecord::Base
      belongs_to :address, :autosave => true
    end
    

    好在人的错误会包含地址的验证错误,格式正确。

    AutosaveAssocation 模块了解更多信息。