3
votes

I'm using RoR with simple_form and cocoon to handle this structure : Node has_many :addresses

Each Address has a boolean :main field which will flag one of each Node address as the main one (actually the one used for SNMP monitoring).

I've a nested form to manage these addresses but I can't find a clean way to select the main one.

Logically, I should use a radio buttons group, each address being one radio group option, but, in a nested form, each radio button will belong to one single address and have a different name, meaning they're in different groups.

I could link the radio button input to a virtual attribute in Node, and set selected address':main field to true in a callback, but how will I link each button to its address (I could use address ID as button value, but newly added addresses have no ID yet).

Here's a simplified version of what my Node form should look like (parentheses represent radio buttons, brackets for text inputs) :

Name : [MyNode1         ]

| Address    | Main |
|------------|------|
| [10.0.0.1] | (*)  |
| [10.0.0.2] | ( )  |
| [10.0.0.3] | ( )  |

My only other solution would be a JS feeded selectbox (options updated when I change something in addresses list) but it's definitely less clean and logical than a simple radio group...

Edit An "acceptable" workaround would be to group radio buttons on something else than name attribute (example : data-group attribute). Does someone know any good JS/jQuery plug-in that could do this ?

1
This topic on ruby-forum talks about the same issue but the solution doesn't handle newly added nested objects (no ID) : ruby-forum.com/topic/2330622 - Gauthier Delacroix
were you able to find a solution to this problem ? - Nanda

1 Answers

0
votes

I had a similar problem, with a Title that had many Role objects (a HMT glue model, which said which Person had done what to that title -- author, editor, translator, whatever). Each title had a primary person, usually the author, but sometimes an editor or curator, as in an encyclopedia. Try as I might, I could not get Rails to use a radio button in a newly created nested model, as you have seen. Here's what I ended up doing:

In the nested Role partial:

<p>
<%= f.collection_select :name, person_roles, :to_s, :titleize, {:prompt => "Role"}, {:class => 'combo'} %>
&nbsp;
<%= f.collection_select :person_id, Person.order(:sort_name), :id, :reverse_name, :prompt => "Person" %>
<%- if ! f.object.new_record? -%>
&nbsp;
<%= radio_button_tag 'title[role_id]', f.object.id, (@title.role_id == f.object.id) %>
<%= label_tag :role_id, "Primary", :for => "title_role_id_#{f.object.id}" %>
<%- end -%>
<%- if ! f.object.new_record? -%>
&nbsp;
<%= f.link_to_remove "Delete", :class => 'delete' %>
<%- end -%>

In the Title model:

has_many :roles, :dependent => :destroy
has_many :people, :through => :roles
belongs_to :role #the primary person, like the author or editor

accepts_nested_attributes_for :roles, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true

after_create :set_primary

def set_primary
  self.update_attributes( :role_id => self.roles.first.id ) if self.roles && self.roles.first
end

So the radio buttons don't even appear unless the nested models have been saved. Adding a new nested model will give you a form partial missing the radio button and delete link (since neither would work until that nested child had been saved).