Rails strong params - using fields from has_many object
All you need to use _attributes:
params.require(:location).permit(:country, :location, {:ads_attributes => [:remote, :days]})
Rails - Strong Parameters - Nested Objects
As odd as it sound when you want to permit nested attributes you do specify the attributes of nested object within an array. In your case it would be
Update as suggested by @RafaelOliveira
params.require(:measurement)
.permit(:name, :groundtruth => [:type, :coordinates => []])
On the other hand if you want nested of multiple objects then you wrap it inside a hash… like this
params.require(:foo).permit(:bar, {:baz => [:x, :y]})
Rails actually have pretty good documentation on this: http://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-permit
For further clarification, you could look at the implementation of permit
and strong_parameters
itself: https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/strong_parameters.rb#L246-L247
Rails Associations - Strong Parameters Build
First make a few changes in the TeamsController
as below:
class TeamController < ApplicationController
before_action :authenticate_user!
def new
## Set "@team" and build "players"
@team = current_user.build_team
@team.players.build
end
def create
@team = current_user.build_team(team_params)
if @team.save
## Redirect to teams show page
redirect_to @team, notice: 'Team was successfully created.'
else
## In case of any error while saving the record, renders the new page again
render action: 'new'
end
end
private
# I can add the player param as nested i.e. .permit(:name, :players => [:name])
# but then build_team complains about receiving an array.
def team_params
## Permit players_attributes
params.require(:team).permit(:name, players_attributes: [:id, :name])
end
end
After this, update the view as below:
<%# Changed "form_for :team" to "form_for @team" %>
<%= form_for @team do |f| %>
<%= f.label :name %><br />
<%= f.text_field :name %>
<%= f.fields_for :players do |player| %> <%# Changed "|players|" to "|player|" %>
<%= player.label :name %> <%# Changed "player_name" to "name" and "players" to "player" %>
<%= player.text_field :name %> <%# Changed "players" to "player" %>
<% end %>
<div><%= f.submit "Create Team" %></div>
<% end %>
Set an instance variable @team
in new
action and build the players for that @team
.
Use @team
instance variable as an argument for form_for
in your view code.
I have also suggested a few tweaks in the create
action, so you know if the team is saved or not.
And fixed the team_params
method to permit the nested attributes of players
.
UPDATE
Using @team
as an argument to form_for
method is resource-oriented style and much preferred way.
Read this pretty good description about usage of form_for to get a better idea.
You can still implement the required code while using :team
but its not preferred way of doing it.
Example using :team
:
<%= form_for :team do |f| %>
<%# ... %>
<%= f.fields_for :players, f.object.players.build do |player| %> <%# build the players for the team %>
<%# ... %>
<% end %>
<%# ... f.submit "Create Team" %>
<% end %>
fields_for
in your case would iterate over players (@team.players
) belonging to a particular team (@team
). If there are no players then you won't see any fields for players in the form, which is why you build the players so you at least get some blank fields for players to input which is why when using accepts_nested_attributes_for
you need to build the nested attributes. You can build them either at controller level(as shown in above suggested code) or within the form.
Example for "within the form":
<%= form_for @team do |f| %>
<%# ... %>
<%= f.fields_for :players, @team.players.build do |player| %> <%# build the players for @team %>
<%# ... %>
<% end %>
<%# ... f.submit "Create Team" %>
<% end %>
How to permit hash with rails strong params
You haven't mentioned the version of rails you are using but,:elements => []
does not work because elements is a ruby hash and not an array
on rails 5.1+ you can use
params.require(:category).permit(:name, :body, :elements => {})
Strong Params won't save nested has_many
To make sure parameters are nested correctly (and so Rails can understand nested model attributes) you should call f.simple_fields_for(:draft_players)
rather than simple_fields_for(:draft_players)
.
In other words, call simple_fields_for
on the FormBuilder object f
rather than calling the helper directly.
That way Rails can look up and validate the nested association correctly.
How to use Rails 4 strong parameters with has_many :through association?
Keep in mind that the name you give to your strong parameters (employees, employee_ids, etc.) is largely irrelevant because it depends on the name you choose to submit. Strong parameters work no "magic" based upon naming conventions.
The reason https://gist.github.com/leemcalilly/a71981da605187d46d96 is throwing an "Unpermitted parameter" error on 'employee_ids' is because it is expecting an array of scalar values, per https://github.com/rails/strong_parameters#nested-parameters, not just a scalar value.
# If instead of:
... "employee_ids" => "1" ...
# You had:
... "employee_ids" => ["1"]
Then your strong parameters would work, specifically:
... { :employee_ids => [] } ...
Because it is receiving an array of scalar values instead of just a scalar value.
Insert & Update with strong parameters for nested `belongs_to` association
Ok, there are a few things I see:
Nested attributes, as described in the API, "allow you to save attributes on associated records through the parent." This means that
class Enrollment < ActiveRecord::Base
belongs_to :student
accepts_nested_attributes_for :student
endinherently won't work because you're trying to accept nested atributes from the parent. So you need to start by rethinking your Active Record assications.
If we pretend that's all squared away, then more syntactical errors are:
Replace
<%= f.fields_for :student_attributes do |student_builder| %>
with
<%= f.fields_for :students do |student_builder| %>
This can be confusing, but passing
:students
to thefields_for
helper calls the nested student object, whereas:student_attributes
is the hash key from the POST parameters thatfields_for
produces.In your strong parameters, you also need to permit the student
:id
so that your updating action has a reference. Otherwise, it will just create a new student. So change it toprivate
def enrollment_params
params.require(:enrollment).permit(:payment_token, :agreed_to_terms, student_attributes: [:payment_name, :id])
end
I'm not sure if that's everything, but hopefully it's a start. Good luck.
Related Topics
Check If String Is Repetition of an Unknown Substring
Rails: How to Pass Custom Params to a Controller Method
How to Get a Reference to a 'Dynamic' Object Call
Watir and Text Field Inside Iframe
Rails 3 - Has_And_Belongs_To_Many
Ruby on Rails - Error Making New App (Rb:55:In 'Require')
Rails 4 Use Application Helpers Inside Initializers
Why Sinatra Request Takes Em Thread
How to Mimic Browser X509 Client Certificate Verification Without Access to Http Layer
{|_, E| E.Length>1} What Is the Use of Underscore ( _ ) in Ruby
No Route Found in Rspec Test for an Existing Route
Ruby on Rails CSV Upload&Import - File Name Too Long
Net::Ssh with Non Unix/Linux Host
Enter & Ioerror: Byte Oriented Read for Character Buffered Io
What Is the Fully Qualified Name of a Model in Ruby on Rails
Why Must I Explicitly Call Self on Accessor When Using the Array Union Operator |= in Ruby