在Rails应用程序中使用accepts_nested_attributes_for时,如何维护嵌套属性的顺序

这是父模型:

class TypeWell  :destroy accepts_nested_attributes_for :type_well_phases, :reject_if => lambda { |a| a[:phase_id].blank? }, :allow_destroy => true ... end 

这是嵌套模型:

 class TypeWellPhase < ActiveRecord::Base belongs_to :type_well belongs_to :phase end 

这是阶段模型:

 class Phase < ActiveRecord::Base ... has_many :type_well_phases ... end 

我通过在父模型的控制器中复制我的阶段(阶段模型)表中的所有记录来在子表(TypeWellPhases)中添加嵌套记录,如下所示:

 class TypeWellsController < ResourceController ... def new @new_heading = "New Type Well - Computed" @type_well = TypeWell.new initialize_phase_fields end private def initialize_phase_fields Phase.order("id").all.each do |p| type_well_phase = @type_well.type_well_phases.build type_well_phase.phase_id = p.id type_well_phase.gw_heat_value = p.gw_heat_value end end ... end 

我这样做是因为我想通过添加的子字段维护特定的顺序。 代码Phase.order(“id”)的部分用于此,因为阶段表按特定顺序具有这些记录。

在此之后,我使用simple_form_for和simple_fields_for帮助器,如下面的表单部分所示:

 = simple_form_for @type_well do |f| ... #type_well_phases = f.simple_fields_for :type_well_phases do |type_well_phase| = render "type_well_phase_fields", :f => type_well_phase 

一切都按预期工作; 大部分的时间。 但是,有时表单中Child行的顺序在保存后会搞乱。 顺序在此应用程序中很重要,这就是我在控制器中的私有方法中明确执行此排序的原因。

我使用“cocoon”gem来添加删除子记录。 我不确定为什么这个订单有时搞砸了。

很抱歉这么长的post,但我想提前提供所有相关细节。

感谢任何指针。

巴拉特

我会以更通用的方式解释你。 比如说,您有产品和订单型号:

 = form_for @product do |f| ... = f.fields_for :orders do |order_fields| = order_fields.text_field :name 

如果您希望按名称对订单进行排序,那么只需对它们进行排序:)

代替:

  = f.fields_for :orders do |order_fields| 

放:

  = f.fields_for :orders, f.object.orders.order(:name) do |order_fields| 

如您所见,作为form_for块参数的f变量具有方法object 。 这是你的@product,所以你可以通过.orders获取它的订单,然后通过.orders .order(:name)应用所需的排序(抱歉这个小混乱:订单/订单)。

解决方案的关键是您可以将已排序的订单作为fields_for的第二个参数fields_for

PS您使用simple_form gem不会影响我的解决方案。 如果你向帮助者添加’simple_’,它会起作用。 只是希望我的回答对其他人更有帮助,而不是与任务有关。

如果您使用的是Rails 2.3.14或更早版本,则必须使用:

 f.fields_for :orders, f.object.orders.all(:order => :name) do |order_fields|