1 year ago
#363502

Sumak
Create multiple associated records in a single form
I'd like a User to be able to create an Event and associated Invitations. An Invitation is a join table between User and Event (with an enum for its state, default to pending
).
Eligible users are those who are member of the same team.
Here are my models:
class User
has_many :invitations, dependent: :destroy
has_many appointments, through: :invitations, source: :event, foreign_key: :event_id
end
class Invitation
belongs_to :event
belongs_to :user
end
class Event
has_many :invitations, dependent: :destroy
has_many :attendees, through: :invitations, source: :user, foreign_key: :user_id
accepts_nested_attributes_for :invitations
end
On the controller setting the instance variables for the form I've:
def new
@current_team = get_current_team
@attendees = @current_team.users.select(:id, :pseudonym)
@new_event = Event.new
@new_event.invitations.build
end
Parameters are white listed, though I suspect I made a mistake here:
def event_params
:title,
:start_date,
# ...
invitations_attributes: [user_id: []]
end
And a form, from which a User can select attendees through a collection_check_boxes
:
<%= form_with model: Event.new do |form| %>
<%= form.fields_for :invitations, Event.new.invitations do |invitation_form| %>
<%= invitation_form.collection_check_boxes :user_id, @attendees, :id, :pseudonym, { include_hidden: false } do |user_check_box| %>
<li>
<%= user_check_box.check_box %>
<%= user_check_box.label %>
</li>
<% end %>
<% end %>
<% end %>
Which generates a collection of <li>
containing <input>
like:
<li>
<input type="checkbox" value="1" name="event[invitations_attributes][0][user_id][]" id="event_invitations_attributes_0_user_id_1">
<label for="event_invitations_attributes_0_user_id_1">Hong Wintheiser III</label>
</li>
However the params are not really convenients:
#<ActionController::Parameters {
"event" => #<ActionController::Parameters {
"title" => "Event title",
"invitations_attributes" => { "0" => { "user_id" => [ "1", "2", "3" ] } }
} permitted: false >,
} permitted: false >
In the end, my parameters does not allow the creation of a new Event ("Invitations user must exist"
).
One way I can think about is to delete
the invitations_attributes
from params
, save it in a variable, create
the new Event (validation will succeed), and then iterate each invitations_attributes['0'][:user_id]
to create associated Invitations.
Though it looks wrong to me, I believe there's a cleaner pattern to achieve this operation.
Question
How do you create a set of associated records from a `has_many through:` relationship inside a single form ?Edit:
The EventController#create
method:
def create
@event.new(event_params)
respond_to do |format|
if @event.save
# ...
end
end
end
Nothing special here, as I think I'm doing wrong before the creation.
Solution:
Our great savior @max answered this question 6 years ago.
Rails fields_for checkbox to create new record
TLDR:
<%= form_with model: @new_event do |f| %>
<%= f.collection_check_boxes :attendee_ids, @attendees, :id, :pseudonym %>
<% end %>
def event_params
# ...
attendee_ids: []
end
And Invitation
are created automagically
ruby-on-rails
forms
nested-attributes
0 Answers
Your Answer