如何使用 ActiveModel 在一次交易中保存 2 个模型?

How to save 2 models in one transaction using ActiveModel?

我有一个小 class 可以与 4 个模型一起使用。我想以“正确”的方式做事。基本上,我想创建 2 个 Address 模型,1 个 Shipment(w/2 address_ids,和属于 Shipment.

1 Parcel

在这一点上,我很困惑。我需要克服这一点,进入下一个重要的里程碑。这看起来有前途吗,还是您建议在控制器中保存 2 条记录,然后使用 after_create 或类似的东西?谢谢。

class Quote
  include ActiveModel::Model
  attr_accessor address_to: {
                  :name, :company, :street1, :street2, :street3, :city, :state, 
                  :zip, :country, :phone, :email},
                address_from: {
                  :name, :company, :street1, :street2, :street3, :city, :state, 
                  :zip, :country, :phone, :email
                }
  def save
    return false if invalid?

    ActiveRecord::Base.transaction do
      user = User.find_by(id: user_id)
      user.addresses.create!([{address_from, address_to}]) # how to do this?

    end
  end
end

如果您通过标签 :belongs_to:has_many 使用模型关联, 例如,您可以使用 accepts_nested_attributes_for :another_child_model。如果您在控制器上允许这些参数,它将自动创建或定义此关联。

Rails guide for nested attributes

注意在控制器上允许这些属性。

class YourController < ApplicationController
   ...
   def your_params
      params.require(:entity).permit(:etc, :etc, child_model_attributes: [:id, :name, :etc, :etc])
   end
   ...
end
  1. 切勿在模型上使用回调。难以测试模型,不可预测的行为。
  2. 你可以使用 accept_nested_attributes.
  3. 如果您有自定义逻辑,您可以使用服务对象模式并将所有逻辑放在那里。 但是如果你想像你那样做然后尝试使用 user.addresses.create!([address_from, address_to])

如果您使用的是 Rails 6 或更高版本 - 有一种名为 insert_all 的方法可以在一条 INSERT 语句中将多条记录插入数据库。

在 apidock 上查看:insert_all

示例:

Book.insert_all([
  { id: 1, title: "Rework", author: "David" },
  { id: 1, title: "Eloquent Ruby", author: "Russ" }
])

(来自文档的示例)