'How to maintain the ordering for nested attributes when using accepts_nested_attributes_for in a Rails application
Here is the parent model:
class TypeWell < ActiveRecord::Base
...
has_many :type_well_phases, :dependent => :destroy
accepts_nested_attributes_for :type_well_phases, :reject_if => lambda { |a| a[:phase_id].blank? }, :allow_destroy => true
...
end
Here is the nested model:
class TypeWellPhase < ActiveRecord::Base
belongs_to :type_well
belongs_to :phase
end
Here is the Phase model:
class Phase < ActiveRecord::Base
...
has_many :type_well_phases
...
end
I add nested records in child table (TypeWellPhases) by copying ALL records from my phases (Phase model) table in the parent model's controller as shown below:
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
I do this because I want to maintain a specific order by the children fields that are added. The part of the code Phase.order("id") is for that since the phases table has these records in a specific order.
After this I use the simple_form_for and simple_fields_for helpers as shown below in my form partial:
= 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
Everything works as desired; most of the times. However, sometimes the ordering of Child rows in the form gets messed up after it has been saved. The order is important in this application that is why I explicitly do this ordering in the private method in the controller.
I am using the "cocoon" gem for adding removing child records. I am not sure as to why this order gets messed up sometimes.
Sorry for such a long post, but I wanted to provide all the pertinent details up front.
Appreciate any pointers.
Bharat
Solution 1:[1]
If you are using Rails 2.3.14 or older you have to use:
f.fields_for :orders, f.object.orders.all(:order => :name) do |order_fields|
Solution 2:[2]
I use this way:
class League < ActiveRecord::Base
has_many :rounds, -> { sort_by_number }, dependent: :destroy
end
class League::Round < ActiveRecord::Base
belongs_to :league
scope :sort_by_number, -> { order('league_rounds.number ASC') }
end
In the view
= form_for league do |f|
= f.fields_for :rounds do |round_form|
# Here rounds are sorted by sort_by_number
This approach allows the use of any scope defined in the model. This approach allows the creation of several differently sorted associations.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Ailison Carvalho |
| Solution 2 | Aivils Štoss |
