29

C'è un modo in strong parameters per consentire tutti gli attributi di un modello nested_attributes? Ecco un codice di esempio.consentono tutti gli attributi per gli attributi nidificati

class Lever < ActiveRecord::Base 
has_one :lever_benefit 
accepts_nested_attributes_for :lever_benefit 
end 

class LeverBenefit < ActiveRecord::Base 
    # == Schema Information 
    # id   :integer   not null, primary key 
    # lever_id :integer 
    # explanation :text 
end 

Per i parametri di leva forte sto scrivendo attualmente questo

def lever 
params.require(:lever).permit(:name,:lever_benefit_attributes => [:lever_id, :explanation]) 
end 

Esiste un modo per attributi nidificati posso scrivere per consentire a tutti gli attributi senza dare esplicitamente gli attributi nome come lever_id e explanation?

Nota: Si prega di non confondersi con questa domanda con permit! o permit(:all) questo è per permettendo a tutti per gli attributi nidificati

+0

provare a leggere questa risposta può essere questo è utile. > http://stackoverflow.com/questions/14483963/rails-4-0-strong-parameters-nested-attributes-with-a-key-that-points-to-a-hash –

+0

grazie, ma ho visto questo . Se noti che sta facendo la stessa cosa del filtraggio selettivo degli attributi ('assets_attributes:: filename') che sta passando il nome del file. Voglio consentire tutti i parametri per gli attributi nidificati – AnkitG

risposta

10

Il punto centrale di parametri forti è nel suo nome: rendere i vostri parametri di input forte.
Consentire a tutti i parametri sarebbe una pessima idea, in quanto permetterebbe a chiunque di inserire valori che non si vogliono necessariamente aggiornare dai propri utenti.

Nell'esempio fornito, si citano i due parametri attualmente necessari:
[:lever_id, :explanation].

Se sono consentiti tutti i parametri, è possibile che qualcuno modifichi qualsiasi altro valore.
created_at o lever_id per esempio.

Questo sarebbe sicuramente un problema di sicurezza ed è per questo che non dovresti farlo.
Specificare esplicitamente tutti gli attributi potrebbe sembrare noioso quando lo si fa.
Ma questo è necessario per mantenere la vostra applicazione sicura.

Modifica: per persone che effettuano downvoting. Questa potrebbe non essere la risposta che stai cercando, ma è la risposta che ti serve.
La whitelist di tutti gli attributi nidificati è un enorme difetto di sicurezza che i params forti stanno cercando di proteggerti con e lo stai rimuovendo.
Date un'occhiata a quello che portano a costruire strong_params, e come non lo si utilizza può essere un male per voi: https://gist.github.com/peternixey/1978249

+1

grazie, la tua risposta è un punto valido che può essere un problema di sicurezza. Andrò con menzione esplicita degli attributi. – AnkitG

+17

Se l'hash che si stava ricevendo è memorizzato in una colonna JSON serializzata, non ci sono problemi di sicurezza per le chiavi. (Oltre alle preoccupazioni esistenti di un input troppo grande). Ho questo caso d'uso e vorrei permettere qualsiasi chiave arbitraria in un hash. –

+2

Esistono altri modi per proteggere gli attributi. Gli oggetti di comando che lanciano parametri non ammessi, ad esempio, sono un approccio molto migliore, IMHO. – karmajunkie

46

L'unica situazione che ho incontrato dove permettendo chiavi arbitrarie in hash un nidificato params sembra ragionevole per me è quando si scrive a una colonna serializzata. Sono riuscito a gestire la cosa in questo modo:

class Post 
    serialize :options, JSON 
end 

class PostsController < ApplicationController 
    ... 

    def post_params 
    all_options = params.require(:post)[:options].try(:permit!) 
    params.require(:post).permit(:title).merge(:options => all_options) 
    end 
end 

try fa in modo che non richiedono i regali di una chiave di :options.

+0

Grazie mille, risparmi un sacco di tempo :) –

+1

Questa è la risposta corretta! ti meriti una casella di controllo verde! –

+2

Perché 'params.require (: post) .fetch (: options, nil)' invece di 'params.require (: post) [: options]'? –

5

provare

params.require(:lever).permit(:name, leave_benefit_attributes: LeaveBenefit.attribute_names.collect { |att| att.to_sym }) 
10

prima cosa, assicurarsi che si vuole veramente per consentire a tutti i valori in un hash nidificato. Leggi attraverso Damien MATHIEU's answer per capire la potenziale apertura dei buchi di sicurezza ...

Se è ancora necessario/si desidera consentire tutti i valori in un hash (esistono casi d'uso perfettamente validi per questo, ad esempio la memorizzazione di metadati non strutturati forniti dall'utente per un record), è possibile ottenerlo utilizzando i seguenti bit di codice :

def lever_params 
    nested_keys = params.require(:lever).fetch(:lever_benefit_attributes, {}).keys 
    params.require(:lever).permit(:name,:lever_benefit_attributes => nested_keys) 
end 

Nota: Questo è molto simile a tf.'s answer ma un po 'più elegante dal momento che non sarà possibile ottenere alcun Unpermitted parameters: lever_benefit_attributes avvertimenti/errori.

15

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

params.require(:lever).permit(:name).tap do |whitelisted| 
    whitelisted[:lever_benefit_attributes ] = params[:lever][:lever_benefit_attributes ] 
end 

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

Mentre altre soluzioni come:

nested_keys = params.require(:lever).fetch(:lever_benefit_attributes, {}).keys 
params.require(:lever).permit(:name,:lever_benefit_attributes => nested_keys) 

non lo fanno.


Fonte:

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

+2

Questo non funzionerà con parametri profondamente annidati in Rails 5. Vedi perché qui: http://eileencodes.com/posts/actioncontroller-parameters-now-returns-an-object-instead-of-a-hash/ – rmcsharry