Rails Strong Params - Using Fields from Has_Many Object

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:

  1. 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
    end

    inherently 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:

  2. 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 the fields_for helper calls the nested student object, whereas :student_attributes is the hash key from the POST parameters that fields_for produces.

  3. 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 to

    private
    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



Leave a reply



Submit