Attributi nidificati Parametri non ammessi

Ho un object Bill , che ha molti oggetti Due . L’object Due appartiene anche a una Person . Voglio un modulo in grado di creare il Bill e i suoi figli Dues in un’unica pagina. Sto cercando di creare un modulo usando attributi nidificati, simili a quelli di questo Railscast .

Il codice rilevante è elencato di seguito:

due.rb

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

bill.rb

 class Bill  :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 

Conto / _form.html.erb

   



builder %>

Conto / _due_fields.html.erb

 

AGGIORNA a bills_controller.rb Funziona!

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

I campi corretti vengono visualizzati sulla pagina (anche se non è ancora disponibile un menu a discesa per la Person ) e l’invio è riuscito. Tuttavia, nessuna delle quote figlio viene salvata nel database e viene generato un errore nel registro del server:

 Unpermitted parameters: dues_attributes 

Poco prima dell’errore, il registro mostra questo:

 Started POST "/bills" for 127.0.0.1 at 2013-04-10 00:16:37 -0700 Processing by BillsController#create as HTML
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"}

C’è stato qualche cambiamento in Rails 4?

Sembra che ci sia un cambiamento nella gestione della protezione degli attributi e ora è necessario inserire i parametri nella whitelist nel controller (invece di attr_accessible nel modello) perché l’ex gem opzionale strong_parameters è diventato parte di Rails Core.

Questo dovrebbe assomigliare a questo:

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

Quindi params.require(:model).permit(:fields) verrebbe utilizzato

e per attributi annidati qualcosa di simile

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

Alcuni ulteriori dettagli possono essere trovati nei documenti API di bordo Ruby e nei parametri strong su github o qui

Dai documenti

 To whitelist an entire hash of parameters, the permit! method can be used params.require(:log_entry).permit! 

Gli attributi annidati sono sotto forma di hash. Nella mia app, ho un modello Question.rb che accetta attributi nidificati per un modello Answer.rb (dove l’utente crea le opzioni di risposta per una domanda che crea). Nel question_controller, lo faccio

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

Tutto ciò che è nella hash della domanda è permesso, compresi gli attributi di risposta annidati. Questo funziona anche se gli attributi nidificati sono sotto forma di array.

Detto questo, mi chiedo se c’è un problema di sicurezza con questo approccio perché sostanzialmente permette tutto ciò che è all’interno dell’hash senza specificare esattamente di cosa si tratta, il che sembra contrario allo scopo di parametri forti.

o puoi semplicemente usare

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

In realtà esiste un modo per elencare semplicemente tutti i parametri nidificati.

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

Questo metodo ha vantaggio rispetto ad altre soluzioni. Permette di permettere i parametri deep-nested.

Mentre altre soluzioni come:

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

Non farlo.


Fonte:

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

Oggi mi sono imbattuto in questo stesso problema, mentre lavoravo su Rails 4, sono riuscito a farlo funzionare strutturando i miei fields_for come:

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

Poi nel mio controller ho i miei parametri forti come:

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

Tutto funziona!

Se si utilizza un campo JSONB, è necessario convertirlo in JSON con .to_json (ROR)