Triple-nested form with Rails form_with and strong parameters
At first, you need to change the form to nest option_values
inside option
, and add account_id
field to option values:
<%= form_with(model: product, local: true) do |f| %>
<%= f.fields_for :options do |options_form| %>
<fieldset class='form-group'>
<%= options_form.hidden_field :account_id, value: current_user.account.id %>
<%= options_form.label :name, 'Option' %>
<%= options_form.text_field :name, class: 'form-control' %>
</fieldset>
<%= options_form.fields_for :option_values do |values_form| %>
<fieldset class='form-group'>
<%= values_form.hidden_field :account_id, value: current_user.account.id %>
<%= values_form.label :name, 'Value' %>
<%= values_form.text_field :name, class: 'form-control' %>
</fieldset>
<% end %>
<% end %>
<% end %>
Also you need to build nested records in the controller. Another option is to build them dynamically via javascript (look at the cocoon gem, for example). To build 3 options with 3 values each:
def new
@account = current_user.account
# it is better to create associated product
@product = @account.products.new
3.times do
option = @product.options.build
3.times { option.option_values.build }
end
end
Rails Multiple Nested Forms
The new form_with
which combines the previous form_for
and form_tag
makes it on the one hand pretty powerful but also sometimes very confusing. What used to be simply form_for @product
, now you have to write
form_with model: @product, local: true do |f|
Your use of scope:
just uses @product
as a prefix and will not actually iterate over or use the @product
to find associations, that is why we do not see the property_attributes
, nor the implicit id
field, even though you correctly have the accepts_nested_attributes
(the _destroy
field would be added by cocoon's link_to_remove_association
--if you would want to go back to the ability to dynamically add/remove nested items).
Rails 2 level nested forms
Your strong parameters permit
call should reflect the actual nesting structure of parameters:
def person_params
params.require(:person).permit(
:first_name, :last_name,
addresses_attributes: [
:id, :kind, :street, :_destroy,
{ nested_addresses_attributes: [:id, :name, :_destroy] } # <= note the hash
]
)
end
How to pass an account_id through a nested form in Rails
Alternatively, you can pass a hidden_field with form and nested_form as given below: -
<%= form_for @product do |form|%>
<%= form.fields_for :options do |builder| %>
<fieldset class='form-group'>
<%= builder.label :name, 'Add option(s)' %>
<%= builder.text_field :name %>
<small id="optionHelp" class="form-text text-muted">
(e.g. "Sizes" or "Color")
</small>
<%=builder.hidden_field :account_id, value: current_user.account.id%>
</fieldset>
<% end %>
<%= form.hidden_field :account_id, value: current_user.account.id%>
<%end%>
Other than this you can set account_id at the controller
def new
#@product = Product.new
@product = current_user.account.products.new
@product.options.build(account_id: current_user.account.id)
end
Rails 6: Nested Form not saving
The Poll
isn't created at the moment the validations in the Question
model are run and so the question's poll_id
is nil
causing the presence validation to fail. You can remove the validation since the belongs_to :poll
association validates that the poll exists (belongs_to
association is required by default from Rails 5).
class Question < ApplicationRecord
belongs_to :poll
validates_presence_of :content
end
Related Topics
I Want to Return a Single Result Using .Find() with Ruby on Rails
Ruby on Rails CSV Upload&Import - File Name Too Long
Ruby: Append Text to the 2Nd Line of a File
Rails: How to Pass Custom Params to a Controller Method
Ruby: Sorting 2 Arrays Using Values from One of Them
Vps Apache Config - Invalid Command 'Passengerdefaultruby' After Adding Latest Passenger Gem
Browser-Based Uploads Using Post
Reply to Thread Google-Api-Ruby-Client
Ruby on Rails View Rendering Db Info on Page
Ruby Net-Ssh Calling Bash Script with Interactive Prompts
Find a Unique Element in a Compound Array
Rails in Rendering Unnecessary Information
Check If a Table Exists in Rails
Fetch VS. [] When Working with Hashes