Rails 嵌套属性被复制
Rails Nested attributes being duplicated
这个问题难倒了我。我整个周末都在看它,但不知道发生了什么。
当我创建一个新的 employee
对象时,我还想在我的 employee
模型中使用 accepts_nested_attributes_for :ee_pay
创建多个新的 ee_pay
记录。
为新员工创建 ee_pay
记录取决于员工所属公司存在的 company_pay
个对象的数量。因此,在下面的情况下,有 2 个 company_pay
对象 -> "Basic" [id:2] 和 "Time + 1/2" [id:3](在 before_action
中返回),我想为有问题的员工
为每个人创建一个 ee_pay
代码如下:-
employees_controller.rb
before_action :set_company_pay_types, only: [:new, :update, :edit]
def new
@ee_pay_types = []
@taxable_pays.each do |pt|
@ee_pay_types << @employee.ee_pay.build(company_pay_id: pt.id)
end
end
private
def set_company_pay_types
@taxable_pays = CompanyPay.where(['company_id = ? AND pay_sub_head_id = ? AND description <> ?', current_company.id, 1, "Salary"]).order(:id)
end
def employee_params
params.require(:employee).permit(....[multiple other fields]..., address_attributes:[:id, :line1, :line2, :line3, :line4, :postcode, :country], ee_pay_attributes:[:id, :employee_id, :company_pay_id, :amount, :rate])
end
views/employees/_form
<div><strong>Hourly Pay Types</strong></div>
<div class="form_spacer"></div>
<div class="row">
<div class="col-md-3">
<div class="form_indent1"><div class="form_label"><strong>Description</strong></div></div>
</div>
<div class="col-md-3">
<div class="form_indent1"><div class="form_label"><strong>Amount</strong></div></div>
</div>
<div class="col-md-2">
<div class="form_indent1"><div class="form_label"><strong>Units</strong></div></div>
</div>
<div class="col-md-4">
<div class="form_indent1"><div class="form_label"><strong>Rate</strong></div></div>
</div>
<div>
<%= debug @ee_pay_types %>
<% @ee_pay_types.each do |ee_pay| %>
<%= f.fields_for :ee_pay do |builder| %>
<%= builder.hidden_field :company_pay_id %>
<div class="col-md-3">
<div class="form_indent1"><div class="form_indent1"><%= ee_pay.company_pay.description %></div></div>
<div class="form_spacer"></div>
</div>
<div class="col-md-3">
<div class="form_indent1"><%= builder.text_field :amount, class: "number_input" %></div>
<div class="form_spacer"></div>
</div>
<div class="col-md-2">
<div class="form_indent1"><%= ee_pay.company_pay.units %></div>
<div class="form_spacer"></div>
</div>
<div class="col-md-4">
<div class="form_indent1"><%= builder.text_field :rate, class: "number_input" %></div>
<div class="form_spacer"></div><br />
</div>
<% end %>
<% end %>
</div>
</div>
Output from employees/new
当我去创建一个新的员工记录时,我得到了 ee_pay
对象的以下输出。事实证明,代码正在按照以下格式复制每个代码:-
*description* *company_pay_id*
Basic 2
Basic 3
Time & 1/2 2
Time & 1/2 3
在我看来 employees_controller
中的这一行 @ee_pay_types << @employee.ee_pay.build(company_pay_id: pt.id)
正在构建两个新的 ee_pay
对象(在上图中的调试中输出)。然后在视图中,它迭代这两个对象并为每个对象创建两个新的 ee_pay
对象。我认为这就是正在发生的事情,但我可能会完全绞尽脑汁。我在这个阶段迷路了,我不知道如何解决它。
希望有人能为我指出正确的解决方法。这可能是我遗漏的很明显的东西。
感谢观看
Edit 1
按要求添加模型
models/ee_pay
class EePay < ActiveRecord::Base
belongs_to :employee
belongs_to :company_pay
end
model/company_pay
class CompanyPay < ActiveRecord::Base
belongs_to :pay_sub_head
belongs_to :company
has_many :ee_pay
end
model/employee
class Employee < ActiveRecord::Base
belongs_to :company
belongs_to :address
accepts_nested_attributes_for :address
has_many :ee_pay
accepts_nested_attributes_for :ee_pay
end
Yann 在评论中建议将 employee_controller
更改为此
@ee_pay_types = []
@taxable_pays.each do |pt|
@employee.ee_pay.build(company_pay_id: pt.id)
end
并删除视图中 @ee_pay_types
的迭代,现在看起来像(我将对 ee_pay
的任何引用更改为 builder
):-
<div>
<%= debug @ee_pay_types %>
<%= f.fields_for :ee_pay do |builder| %>
<%= builder.hidden_field :company_pay_id %>
<div class="col-md-3">
<div class="form_indent1"><div class="form_indent1"><%= builder.company_pay.description %></div></div>
<div class="form_spacer"></div>
</div>
<div class="col-md-3">
<div class="form_indent1"><%= builder.text_field :amount, class: "number_input" %></div>
<div class="form_spacer"></div>
</div>
<div class="col-md-2">
<div class="form_indent1"><%= builder.company_pay.units %></div>
<div class="form_spacer"></div>
</div>
<div class="col-md-4">
<div class="form_indent1"><%= builder.text_field :rate, class: "number_input" %></div>
<div class="form_spacer"></div><br />
</div>
<% end %>
</div>
但这给了我错误:-
undefined method `company_pay' for #<ActionView::Helpers::FormBuilder:0x007f47d5649118>
对我来说,我似乎无法访问正在创建的 ee_pay
的 company_pay
。有人有什么想法吗?
Edit 2 - Solved
按照 Yan Foto 的建议进行编辑后,我可以访问使用 builder.object.company_pay.description
创建的 ee_pay
的 company_pay
。再次感谢颜
您不需要在 fields_for
之前进行迭代,因为它会根据现有关联的数量呈现您的表单。您可以通过将 @taxable_pays
的数量更改为 3 来确认这一点,并查看您如何在表单中获得 9(而不是 6)项。
将您的控制器更改为以下内容:
def new
@ee_pay_types = []
@taxable_pays.each do |pt|
@employee.ee_pay.build(company_pay_id: pt.id)
end
end
并从您的表单中删除 <% @ee_pay_types.each do |ee_pay| %>
,您就可以开始了。
更新
您还想以以下形式访问 CompanyPay
:
builder.object
使您可以访问表单对象(EePay
实例)并调用 builder.object.company_pay.description
为您提供关联的 CompanyPay
.
的描述
这个问题难倒了我。我整个周末都在看它,但不知道发生了什么。
当我创建一个新的 employee
对象时,我还想在我的 employee
模型中使用 accepts_nested_attributes_for :ee_pay
创建多个新的 ee_pay
记录。
为新员工创建 ee_pay
记录取决于员工所属公司存在的 company_pay
个对象的数量。因此,在下面的情况下,有 2 个 company_pay
对象 -> "Basic" [id:2] 和 "Time + 1/2" [id:3](在 before_action
中返回),我想为有问题的员工
ee_pay
代码如下:-
employees_controller.rb
before_action :set_company_pay_types, only: [:new, :update, :edit]
def new
@ee_pay_types = []
@taxable_pays.each do |pt|
@ee_pay_types << @employee.ee_pay.build(company_pay_id: pt.id)
end
end
private
def set_company_pay_types
@taxable_pays = CompanyPay.where(['company_id = ? AND pay_sub_head_id = ? AND description <> ?', current_company.id, 1, "Salary"]).order(:id)
end
def employee_params
params.require(:employee).permit(....[multiple other fields]..., address_attributes:[:id, :line1, :line2, :line3, :line4, :postcode, :country], ee_pay_attributes:[:id, :employee_id, :company_pay_id, :amount, :rate])
end
views/employees/_form
<div><strong>Hourly Pay Types</strong></div>
<div class="form_spacer"></div>
<div class="row">
<div class="col-md-3">
<div class="form_indent1"><div class="form_label"><strong>Description</strong></div></div>
</div>
<div class="col-md-3">
<div class="form_indent1"><div class="form_label"><strong>Amount</strong></div></div>
</div>
<div class="col-md-2">
<div class="form_indent1"><div class="form_label"><strong>Units</strong></div></div>
</div>
<div class="col-md-4">
<div class="form_indent1"><div class="form_label"><strong>Rate</strong></div></div>
</div>
<div>
<%= debug @ee_pay_types %>
<% @ee_pay_types.each do |ee_pay| %>
<%= f.fields_for :ee_pay do |builder| %>
<%= builder.hidden_field :company_pay_id %>
<div class="col-md-3">
<div class="form_indent1"><div class="form_indent1"><%= ee_pay.company_pay.description %></div></div>
<div class="form_spacer"></div>
</div>
<div class="col-md-3">
<div class="form_indent1"><%= builder.text_field :amount, class: "number_input" %></div>
<div class="form_spacer"></div>
</div>
<div class="col-md-2">
<div class="form_indent1"><%= ee_pay.company_pay.units %></div>
<div class="form_spacer"></div>
</div>
<div class="col-md-4">
<div class="form_indent1"><%= builder.text_field :rate, class: "number_input" %></div>
<div class="form_spacer"></div><br />
</div>
<% end %>
<% end %>
</div>
</div>
Output from employees/new
当我去创建一个新的员工记录时,我得到了 ee_pay
对象的以下输出。事实证明,代码正在按照以下格式复制每个代码:-
*description* *company_pay_id*
Basic 2
Basic 3
Time & 1/2 2
Time & 1/2 3
在我看来 employees_controller
中的这一行 @ee_pay_types << @employee.ee_pay.build(company_pay_id: pt.id)
正在构建两个新的 ee_pay
对象(在上图中的调试中输出)。然后在视图中,它迭代这两个对象并为每个对象创建两个新的 ee_pay
对象。我认为这就是正在发生的事情,但我可能会完全绞尽脑汁。我在这个阶段迷路了,我不知道如何解决它。
希望有人能为我指出正确的解决方法。这可能是我遗漏的很明显的东西。
感谢观看
Edit 1
按要求添加模型
models/ee_pay
class EePay < ActiveRecord::Base
belongs_to :employee
belongs_to :company_pay
end
model/company_pay
class CompanyPay < ActiveRecord::Base
belongs_to :pay_sub_head
belongs_to :company
has_many :ee_pay
end
model/employee
class Employee < ActiveRecord::Base
belongs_to :company
belongs_to :address
accepts_nested_attributes_for :address
has_many :ee_pay
accepts_nested_attributes_for :ee_pay
end
Yann 在评论中建议将 employee_controller
更改为此
@ee_pay_types = []
@taxable_pays.each do |pt|
@employee.ee_pay.build(company_pay_id: pt.id)
end
并删除视图中 @ee_pay_types
的迭代,现在看起来像(我将对 ee_pay
的任何引用更改为 builder
):-
<div>
<%= debug @ee_pay_types %>
<%= f.fields_for :ee_pay do |builder| %>
<%= builder.hidden_field :company_pay_id %>
<div class="col-md-3">
<div class="form_indent1"><div class="form_indent1"><%= builder.company_pay.description %></div></div>
<div class="form_spacer"></div>
</div>
<div class="col-md-3">
<div class="form_indent1"><%= builder.text_field :amount, class: "number_input" %></div>
<div class="form_spacer"></div>
</div>
<div class="col-md-2">
<div class="form_indent1"><%= builder.company_pay.units %></div>
<div class="form_spacer"></div>
</div>
<div class="col-md-4">
<div class="form_indent1"><%= builder.text_field :rate, class: "number_input" %></div>
<div class="form_spacer"></div><br />
</div>
<% end %>
</div>
但这给了我错误:-
undefined method `company_pay' for #<ActionView::Helpers::FormBuilder:0x007f47d5649118>
对我来说,我似乎无法访问正在创建的 ee_pay
的 company_pay
。有人有什么想法吗?
Edit 2 - Solved
按照 Yan Foto 的建议进行编辑后,我可以访问使用 builder.object.company_pay.description
创建的 ee_pay
的 company_pay
。再次感谢颜
您不需要在 fields_for
之前进行迭代,因为它会根据现有关联的数量呈现您的表单。您可以通过将 @taxable_pays
的数量更改为 3 来确认这一点,并查看您如何在表单中获得 9(而不是 6)项。
将您的控制器更改为以下内容:
def new
@ee_pay_types = []
@taxable_pays.each do |pt|
@employee.ee_pay.build(company_pay_id: pt.id)
end
end
并从您的表单中删除 <% @ee_pay_types.each do |ee_pay| %>
,您就可以开始了。
更新
您还想以以下形式访问 CompanyPay
:
builder.object
使您可以访问表单对象(EePay
实例)并调用 builder.object.company_pay.description
为您提供关联的 CompanyPay
.