I am trying to implement a HABTM checkbox in a nested form.
Currently, I have 3 models. Subject, lesson and groups. The associations are as follows: Each subject has many lessons. Each lesson has and belongs to many groups.
Right now, I am trying to implement them all on a single creation and edit form. Such that a lesson is nested in the subject and for each lesson there is a list of group check boxes to implement the HABTM relationship.
I am facing trouble implementing the HABTM relationship as there are many lessons per subjects and I am not sure how I could distinguish between the different lessons.
To elaborate further, I am able to get the nested form working but I can't get the HABTM checkboxes to save to the right lessons. The following code sample is my HABTM checkbox implementation.
<% Group.all.each do |group|%>
<%= check_box_tag "subject[lessons_attributes[0]][group_ids][]", group.id, f.object.groups.include?(group) %>
<%= group.group_index %>
<%end%>
Currently, I have saved it to the first lesson using this line "subject[lessons_attributes[0]][group_ids][]".
However, the number of lessons vary and I am not too sure how I could determine the lesson "number", i.e. the bolded 0 in "subject[lessons_attributes[0]][group_ids][]". Such that I could save the groups to the correct lesson.
Any advice would be appreciated.
For those working with Rails 4 and having the same question (as I had)
The Group.all.each
loop in @Viktor Trón's answer is unnecessary:
There's a new FormBuilder method, collection_check_boxes, which has been created just for that!
Your code would be:
<% form_for @subject do |form| %>
....
<% @subject.lessons.each_with_index do |l, i| %>
<%= form.fields_for :lessons, l do |lesson_fields|%>
<%= lesson_fields.collection_check_boxes :group_ids, Group.all, :id, :group_index %>
<% end %>
<% end %>
<% end %>
You then have to add accepts_nested_attributes_for :lessons
to your Subject
model, and in your SubjectsController
, change the subject_params
method to "permit" nested params for lessons:
params.require(:subject).permit(..., lessons_attributes: [:id, group_ids: []])
In your SubjectsController
, the create
or update
actions remain unchanged: @subject = Subject.create(subject_params)
for instance, will create the Subject, the associated lessons and update their HABTM relationships to groups correctly (unless I made a mistake somewhere!).
the best practice is to prebuild (a few) lesson object on the subject (that is the form.object), then you iterate over them to have per-lesson fields. if you use simple_form or formtastic, collection select via checkboxes is easy:
<% form_for @subject do |form| %>
....
<% form.fields_for :lessons do |lesson_form| %>
...
<% lesson_form.input :group_ids, :as => :check_boxes %>
if you wanna use check_box_tag
, you should iterate through lessons with an index and substitute the index in your checkbox name:
<% form_for @subject do |form| %>
....
<% @subject.lessons.each_with_index do |l, i| %>
<% Group.all.each do |group|%>
<%= check_box_tag "subject[lessons_attributes[#{i}]][group_ids][]", group.id, l.groups.include?(group) %>
<%= group.group_index %>
<% end %>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With