unpermitted rails parameter formularios anidados ruby-on-rails ruby-on-rails-4

ruby on rails - rails - Atributos anidados parámetros no permitidos



unpermitted parameter rails 5 (6)

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

El código relevante se detalla a continuación:

due.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 %>

facturas / _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 correctos se muestran en la página (aunque sin un menú desplegable para Person todavía) y el envío se realiza correctamente. Sin embargo, ninguna de las cuotas de los hijos se guarda en la base de datos y se genera 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?


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 forma de hash. En mi aplicación, tengo un modelo Question.rb que acepta atributos anidados para un modelo Answer.rb (donde el usuario crea opciones de respuesta para una pregunta que crea). En el questions_controller, hago esto

def question_params params.require(:question).permit! end

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

Habiendo dicho eso, me pregunto si hay un problema de seguridad con este enfoque porque básicamente permite todo lo que está dentro del hash sin especificar exactamente qué es, lo que parece contrario al propósito de los parámetros potentes.


En realidad, hay una manera de simplemente listar 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 una ventaja sobre otras soluciones. Permite permitir parámetros anidados profundos.

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


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

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

Luego en mi controlador tengo mis params fuertes como:

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

¡Todo funciona!


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 verse más o menos así:

class PeopleController < ActionController::Base def create Person.create(person_params) end private def person_params params.require(:person).permit(:name, :age) end end

Entonces se params.require(:model).permit(:fields)

y para atributos anidados algo así 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 los parámetros strong_ en github o here


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


o simplemente puedes usar

def question_params params.require(:question).permit(team_ids: []) end