Rails 4 - Paramètres forts - Objets imbriqués


144

J'ai une question assez simple. Mais je n'ai pas encore trouvé de solution.

Voici donc la chaîne JSON que j'envoie au serveur:

{
  "name" : "abc",
  "groundtruth" : {
    "type" : "Point",
    "coordinates" : [ 2.4, 6 ]
  }
}

En utilisant la nouvelle méthode de permis, j'ai:

params.require(:measurement).permit(:name, :groundtruth)

Cela ne génère aucune erreur, mais l'entrée de base de données créée contient nullau lieu de la valeur groundtruth.

Si je viens de définir:

params.require(:measurement).permit!

Tout est enregistré comme prévu, mais bien sûr, cela tue la sécurité fournie par des paramètres forts.

J'ai trouvé des solutions, comment autoriser les tableaux, mais pas un seul exemple utilisant des objets imbriqués. Cela doit être possible d'une manière ou d'une autre, car cela devrait être un cas d'utilisation assez courant. Alors, comment ça marche?



1
@vinodadhikary C'était correct… Je pense que l'OP est confus. Aussi étrange que cela puisse paraître lorsque vous souhaitez autoriser les attributs imbriqués, vous spécifiez les attributs de l'objet imbriqué dans le tableau. D'un autre côté, si vous voulez imbriquer plusieurs objets, vous l'enveloppez dans un hachage ... voir api.rubyonrails.org/classes/ActionController / ... et github.com/rails/rails/blob/master/actionpack/lib/…
j03w

@ j03w, Merci pour le lien vers la source. C'est clair maintenant. Vous devriez ajouter une réponse ici pour cette constatation car je pense que cela aidera beaucoup d'autres personnes.
vee

Réponses:


181

Aussi étrange que cela puisse paraître lorsque vous souhaitez autoriser des attributs imbriqués, vous spécifiez les attributs d'objet imbriqué dans un tableau. Dans votre cas, ce serait

Mettre à jour comme suggéré par @RafaelOliveira

params.require(:measurement)
      .permit(:name, :groundtruth => [:type, :coordinates => []])

D'un autre côté, si vous voulez imbriquer plusieurs objets, vous l'enveloppez dans un hachage ... comme ça

params.require(:foo).permit(:bar, {:baz => [:x, :y]})


Rails a en fait une assez bonne documentation à ce sujet: http://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-permit

Pour plus de précisions, vous pouvez regarder l'implémentation de permitet strong_parameterslui - même: https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/strong_parameters.rb#L246-L247


5
les deux cas sont les mêmes dans cette réponse, en fait, c'est juste que les accolades sont facultatives autour de {: groundtruth => [...]}; C'est un hachage mais l'interpréteur est capable de déterminer où le hachage commence et se termine sans accolades explicites.
speakingcode

Les tableaux d'attributs imbriqués n'autorisent pas les attributs imbriqués. Les attributs imbriqués et attr_accessor sont répertoriés dans mon application en tant que "Paramètres non autorisés". Toujours à la recherche d'une solution sûre.
Katarzyna

Dans le cas de plusieurs objets imbriqués, vous devez également autoriser l'ID pour que cela fonctionne. Plus d'infos ici: stackoverflow.com/questions/18308714/…
Fabrice Carrega

1
Cela n'autorise qu'un seul ensemble d'attributs imbriqués. Cela ne fonctionnera pas dans le cas d'un à plusieurs.
AKWF

23

J'ai trouvé cette suggestion utile dans mon cas:

  def product_params
    params.require(:product).permit(:name).tap do |whitelisted|
      whitelisted[:data] = params[:product][:data]
    end
  end

Consultez ce lien du commentaire de Xavier sur github.

Cette approche met en liste blanche l'ensemble de l'objet params [: mesure] [: groundtruth].

Utilisation des attributs de questions d'origine:

  def product_params
    params.require(:measurement).permit(:name, :groundtruth).tap do |whitelisted|
      whitelisted[:groundtruth] = params[:measurement][:groundtruth]
    end
  end

4
Juste une note latérale, cela apparaîtra toujours dans le journal comme des paramètres non autorisés, mais le modèle les acceptera quand même.
Weston Ganger

5
Je ne suis pas sûr de Rails 4, mais dans mon projet Rails 5, je dois appeler permit!pour être mis sur la liste blanche, sinon il est resté non autorisé après l'avoir tapé. Dans ce cas, ce seraitparams[:measurement][:groundtruth].permit!
nayiaw

@nayiaw j'obtiens également le message non autorisé mais l'ajout permit!soulève ce NoMethodError (undefined method permis d' erreur ! ' for # <Array: 0x007f80cb71ea00>): `
wuliwong

La permit!méthode @wuliwong n'est pas disponible dans Array. Vous devrez avoir accès à l'instance de classe respective pour y avoir accès permit!(cela fait un moment que j'ai oublié le nom de la classe mais c'est quelque chose comme ActionController::Parametersbasé sur cette page ).
nayiaw

8

Autoriser un objet imbriqué:

params.permit( {:school => [:id , :name]}, 
               {:student => [:id, 
                            :name, 
                            :address, 
                            :city]},
                {:records => [:marks, :subject]})

0

Si c'est Rails 5, à cause de la nouvelle notation de hachage: params.permit(:name, groundtruth: [:type, coordinates:[]])fonctionnera bien.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.