Atributos anidados parámetros no permitidos


Tengo un objeto Bill, que tiene muchos objetos Due. El objeto Due también pertenece a un Person. Quiero un formulario que pueda crear el Bill y sus hijos Dues todo en una página. Estoy intentando crear un formulario usando atributos anidados, similares a los de este Railscast.

Se indica el código pertinente abajo:

Debido.rb

class Due < ActiveRecord::Base
    belongs_to :person
    belongs_to :bill
end

Bill.rb

class Bill < ActiveRecord::Base
    has_many :dues, :dependent => :destroy 
    accepts_nested_attributes_for :dues, :allow_destroy => true
end

Bills_controller.rb

  # GET /bills/new
  def new
      @bill = Bill.new
      3.times { @bill.dues.build }
  end

Facturas / _form.HTML.erb

  <%= form_for(@bill) do |f| %>
    <div class="field">
        <%= f.label :company %><br />
        <%= f.text_field :company %>
    </div>
    <div class="field">
        <%= f.label :month %><br />
        <%= f.text_field :month %>
    </div>
    <div class="field">
        <%= f.label :year %><br />
        <%= f.number_field :year %>
    </div>
    <div class="actions">
        <%= f.submit %>
    </div>
    <%= f.fields_for :dues do |builder| %>
        <%= render 'due_fields', :f => builder %>
    <% end %>
  <% end %>

Bills / _due_fields.HTML.erb

<div>
    <%= f.label :amount, "Amount" %>        
    <%= f.text_field :amount %>
    <br>
    <%= f.label :person_id, "Renter" %>
    <%= f.text_field :person_id %>
</div>

ACTUALIZACIÓN a bills_controller.rb Esto funciona!

def bill_params 
  params
  .require(:bill)
  .permit(:company, :month, :year, dues_attributes: [:amount, :person_id]) 
end

Los campos apropiados se muestran en la página (aunque sin un menú desplegable para Person todavía) y el envío es exitoso. Sin embargo, ninguna de las cuotas de los niños se guardan para la base de datos, y se lanza un error en el registro del servidor:

Unpermitted parameters: dues_attributes

Justo antes del error, el registro muestra esto:

Started POST "/bills" for 127.0.0.1 at 2013-04-10 00:16:37 -0700
Processing by BillsController#create as HTML<br>
Parameters: {"utf8"=>"✓", 
"authenticity_token"=>"ipxBOLOjx68fwvfmsMG3FecV/q/hPqUHsluBCPN2BeU=",
 "bill"=>{"company"=>"Comcast", "month"=>"April ", 
"year"=>"2013", "dues_attributes"=>{
"0"=>{"amount"=>"30", "person_id"=>"1"}, 
"1"=>{"amount"=>"30", "person_id"=>"2"},
 "2"=>{"amount"=>"30", "person_id"=>"3"}}}, "commit"=>"Create Bill"}

¿Ha habido algún cambio en Rails 4?

Author: sawa, 2013-04-10

6 answers

Parece que hay un cambio en el manejo de la protección de atributos y ahora debe incluir parámetros en la lista blanca en el controlador (en lugar de attr_accessible en el modelo) porque la antigua gema opcional strong_parameters se convirtió en parte del núcleo de Rails.

Esto debería ser algo como esto:

class PeopleController < ActionController::Base
  def create
    Person.create(person_params)
  end

private
  def person_params
    params.require(:person).permit(:name, :age)
  end
end

Así que params.require(:model).permit(:fields) se usaría

Y para atributos anidados algo como

params.require(:person).permit(:name, :age, pets_attributes: [:id, :name, :category])

Se pueden encontrar más detalles en los documentos de la API de Ruby edge y strong_parameters en github o aquí

 168
Author: thorsten müller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-25 07:39:56

De los documentos

To whitelist an entire hash of parameters, the permit! method can be used

params.require(:log_entry).permit!

Los atributos anidados tienen la forma de un hash. En mi aplicación, tengo una pregunta.el modelo rb acepta atributos anidados para una respuesta.modelo rb (donde el usuario crea opciones de respuesta para una pregunta que crea). En questions_controller, hago esto

  def question_params

      params.require(:question).permit!

  end

Todo en el hash de la pregunta está permitido, incluyendo los atributos de respuesta anidados. Esto también funciona si los atributos anidados tienen la forma de una matriz.

Dicho esto, me pregunto si hay una preocupación de seguridad con este enfoque porque básicamente permite cualquier cosa que esté dentro del hash sin especificar exactamente qué es, lo que parece contrario al propósito de los parámetros fuertes.

 20
Author: Leahcim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-24 02:50:47

O simplemente puede usar

def question_params

  params.require(:question).permit(team_ids: [])

end
 18
Author: Amit Agarwal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-31 14:20:04

En realidad, hay una forma de enumerar todos los parámetros anidados.

params.require(:widget).permit(:name, :description).tap do |whitelisted|
  whitelisted[:position] = params[:widget][:position]
  whitelisted[:properties] = params[:widget][:properties]
end

Este método tiene ventaja sobre otras soluciones. Permite permitir parámetros anidados profundamente.

Mientras que otras soluciones como:

params.require(:person).permit(:name, :age, pets_attributes: [:id, :name, :category])

No lo hagas.


Fuente:

Https://github.com/rails/rails/issues/9454#issuecomment-14167664

 11
Author: nothing-special-here,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-25 20:56:30

Hoy me encontré con este mismo problema, mientras trabajaba en rails 4, pude hacerlo funcionar estructurando mis fields_for como:

<%= f.select :tag_ids, Tag.all.collect {|t| [t.name, t.id]}, {}, :multiple => true %>

Entonces en mi controlador tengo mis fuertes parámetros como:

private
def post_params
    params.require(:post).permit(:id, :title, :content, :publish, tag_ids: [])
end

¡Todo funciona!

 3
Author: Kingsley Ijomah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-19 21:14:59

Si utiliza un campo JSONB, debe convertirlo a JSON con .to_json (ROR)

 1
Author: Wouter Schoofs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-16 16:34:27