我试图以相同的形式创建一个新对象及其相关记录,但希望相关记录使用find_or_create_by
而不是仅创建(因为关联的模型记录可能和大多数时间已经存在)。我花了最近两天的时间挖掘了我能找到的与此主题相关的每篇帖子和文章,试图让它工作但是我的表单只是尝试创建新对象,而不是搜索现有对象。
模型
#order.rb
has_many :order_owners, dependent: :destroy, inverse_of: :order
has_many :owners, through: :order_owners
accepts_nested_attributes_for :order_owners
#owner.rb
has_many :order_owners, dependent: :destroy
has_many :orders, through: :order_owners
validates :name, presence: true, uniqueness: { case_sensitive: false }
#order_owner.rb
belongs_to :owner
belongs_to :order
accepts_nested_attributes_for :owner
表格
orders/new.html.erb
<%= bootstrap_form_for(@orders, layout: :horizontal, label_col: "col-sm-2", control_col: "col-sm-6") do |f| %>
<%= render 'shared/error_messages', object: f.object %>
...
<%= f.fields_for :order_owners do |orderowner| %>
<%= render 'orders/new_order_owners', f: orderowner, render_partial: 'orders/new_order_owners' %>
<% end %>
...
<%= f.form_group do %>
<%= f.submit "Create Order", class: "btn btn-primary" %>
<%= link_to_add_association fa_icon("plus", text: "Add Owner"), f, :order_owners,
class: "btn btn-outline pull-right #{orderBtnDisable(@properties)}", partial: "orders/new_order_owners", id: "newOrderOwnerAdd" %>
<% end %>
<% end %>
orders/new_order_owners
部分
<div class="m-t-md m-b-md border-bottom form-horizontal nested-fields">
<%= link_to_remove_association(fa_icon("remove", text: ""), f, { class: "btn btn-danger btn-outline pull-right" }) %>
<% f.object.build_owner unless f.object.owner %>
<%= f.fields_for :owner do |owner| %>
<%= owner.select :name, options_from_collection_for_select(@owners, "name", "name"),
{ label: "Name:", include_blank: true }, { id: "orderPropOwnerSelect", data: { placeholder: "Select an existing Owner or type a new one.."} } %>
<% end %>
</div>
控制器
orders/new
def new
@order = Order.new
@order.build_property
@order.order_owners.build.build_owner
@properties = Property.find_by_id(params[:property_id])
if @properties
@owners = @properties.owners
else
@owners = []
end
respond_to do |format|
format.html
format.js
end
end
orders/create
def create
@properties = Property.find(params[:order][:property_id])
@order = @properties.orders.create(order_params)
respond_to do |format|
format.html { if @order.save
if params[:order][:owners_attributes]
order_prop_owner_check(@order, @properties)
end
flash[:success] = "Order created successfully!"
redirect_to property_order_path(@properties, @order)
else
@properties
@owner = @properties.owner
render 'new'
end
}
format.js {
if @order.save
flash.now[:success] = "Order Updated Successfully!"
else
flash.now[:danger] = @order.errors.full_messages.join(", ")
end
}
end
end
因此,您可以在new
操作中看到,我实例化新订单,构建其关联属性(订单所属的属性),构建新的order_owner关系,并构建该关系的所有者。然后在提交时,它通过@ properties.orders.create(order_params)创建订单。
我得到的错误是&#34;订单所有者所有者名称已经存在。&#34;很明显它没有按名称查找所有者。 我尝试过:
autosave_associated_records_for_owner
,但似乎它们永远不会被调用,所以我必须做错事。 (我已经尝试了几乎所有我能找到的答案的变体)before_add:
回调has_many :owners, through: :order_owners
和has_many :order_owners
。
has_many :owners
和has_many :owners, through: :order_owners
以及在order_order.rb中扩展belongs_to :owner
我也在表单中尝试过不同的调用关联变体,所以我一定只是误解了一些东西。我也使用Cocoon来管理嵌套表单,但我已经就不相关的问题与作者进行了交谈,Cocoon本质上只是嵌套表单的一个视图助手,因此解决方案必须在模型/控制器中使用。
欢迎任何和所有想法。提前谢谢。
P.S。我在控制器操作中留下了代码,这些操作可能/可能不属于这个确切的帖子,但我想展示整个操作的完整性。如果重要,我在另一个字段中选择属性时手动设置所有者通过AJAX选择。基本上它只是查找属性并将现有所有者添加到所有者选择。
答案 0 :(得分:1)
所有者嵌套在订单中。因此,当您调用order.save时,它会运行所有验证(包括所有者)。如果您想使用find_or_create_by
,则需要在before_save
内进行,因此您可以在验证点击之前对所有者进行修改。
#order.rb
before_save :find_or_create_owner
def find_or_create_owner
self.order_owners.each do |order_owner|
order_owner.owner = Owner.find_or_create_by(name: final_owner.name)
end
end
根据您的形式和业务逻辑,可能需要进一步定制,但这是主要概念。