Reputation: 678
I'm building a platform that let's user create Projects. Each Project may have different Roles to be covered, and each Role may have different Requirements that the user applying to it has to meet (a Requirement is a pair of Technology and Level objects).
As of now, I have something like this:
<%= simple_form_for([ @project, @role ], remote: true) do |f| %>
<%= simple_fields_for :requirement do |ff| %>
<%= ff.input :technology_id, collection: Technology.all, label:false, prompt: "Tecnología" %>
<%= ff.input :level_id, collection: Level.all, label:false, prompt: "Nivel" %>
<% end %>
<%= f.input :name, label:false, placeholder: "Nombre del rol" %>
<%= f.input :description, label:false, placeholder: "Descripción" %>
<%= f.submit "Add role", class: "btn btn-primary" %>
<% end %>
However, that approach is not convenient because it will only let me create 1 Requirement (Tech and Level pair) for that Role.
How could I let the user create many different Requirements for that Role at once? I was thinking of building an array of hashes and passing it to the controller so I could then iterate over it. Something like:
requirements = [{technology: "Ruby", level: "Junior"}, {technology: "Rails", level: "Junior"}..]
However, I don't know if that would be the way to do it, and if so if that can be done with simple_form. Any insight would be appreciated.
Upvotes: 0
Views: 28
Reputation: 102026
You don't need to do any silly shenanigans here. Just need to change the association to a one-to-many:
class Role < ApplicationRecord
has_many :requirements
accepts_nested_attributes_for :requirements
end
class Requirement < ApplicationRecord
belongs_to :role
belongs_to :level
belongs_to :technology
end
<%= simple_form_for([ @project, @role ], remote: true) do |f| %>
<%= simple_fields_for :requirements do |ff| %>
<%= ff.input :technology_id, collection: Technology.all, label:false, prompt: "Tecnología" %>
<%= ff.input :level_id, collection: Level.all, label:false, prompt: "Nivel" %>
<% end %>
...
<% end %>
You then need to seed the association in the controller in order for the inputs to show up:
def new
@role = Role.new do |r|
5.times { r.requirements.new }
end
end
You can whitelist an array of nested attributes by passing an array of symbols corresponding to the attributes you want to permit:
def role_params
params.require(:role)
.permit(
:name, :description,
requirements_attributes: [
:id, :_destroy, :technology_id, :level_id
]
)
end
You don't need to loop through anything. accepts_nested_attributes_for :requirements
creates a requirements_attributes=
setter that takes care of it all for you.
Upvotes: 1