2 years 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
