web-dev-qa-db-fra.com

Rails 5: impossible de récupérer les valeurs de hachage du paramètre

Je rencontre un problème étrange.

undefined method `values' for #<ActionController::Parameters:0x007fb06f6b2728>

est l'erreur que je reçois lorsque j'attribue une variable à un paramètre hash et que j'essaie d'obtenir ses valeurs. 

attributes = params[:line_item][:line_item_attributes_attributes] || {}
attributes.values

le paramètre ressemble à ceci un hachage de hachages:

{"0"=>{"product_attribute_id"=>"4"}, "1"=>{"product_attribute_id"=>"7"}}

maintenant, lorsque je fais cela dans la console et que je l’attribue à une variable, cela fonctionne parfaitement. J'ai donc du mal à comprendre ce qui ne fonctionne pas ici et comment le faire fonctionner.

24

jetez un oeil à this . Très bizarre puisque ActionController::Parameters est une sous-classe de Hash, vous pouvez le convertir directement en un hachage en utilisant la méthode to_h sur le hachage params.

Cependant, seul to_h fonctionnera avec les paramètres de la liste blanche, vous pouvez donc faire quelque chose comme:

permitted = params.require(:line_item).permit(: line_item_attributes_attributes)
attributes = permitted.to_h || {}
attributes.values

Mais si vous préférez ne pas ajouter de liste blanche, il vous suffit d'utiliser la méthode to_unsafe_h.

Mettre à jour

J'étais très curieux à propos de ce problème, alors j'ai commencé mes recherches et, maintenant que vous avez bien précisé que vous utilisez Rails 5, c'est la cause de ce problème, comme @tillmo l'a dit dans les versions stables de Rails comme 4.x, ActionController::Parameters est un. sous-classe de Hash, il devrait donc bien répondre à la méthode values, cependant dans Rails 5 ActionController::Parameters renvoie désormais un objet au lieu d'un hachage

Note: cela n’affecte pas l’accès aux clés dans le hachage params comme params[:id]. Vous pouvez voir le Pull Request qui a implémenté cette modification.

Pour accéder aux paramètres de l'objet, vous pouvez ajouter to_h aux paramètres:

params.to_h

Si nous examinons la méthode to_h dans ActionController::Parameters, nous pouvons voir qu'elle vérifie si les paramètres sont autorisés avant de les convertir en hachage.

# actionpack/lib/action_controller/metal/strong_parameters.rb
def to_h
  if permitted?
    @parameters.to_h
  else
    slice(*self.class.always_permitted_parameters).permit!.to_h
  end
end

par exemple exemple

def do_something_with_params
  params.slice(:param_1, :param_2)
end

Ce qui reviendrait:

{ :param_1 => "a", :param_2 => "2" }

Mais maintenant, cela retournera un objet ActionController::Parameters.

Si vous appelez to_h, vous obtiendrez un hachage vide car param_1 et param_2 ne sont pas autorisés.

Pour avoir accès aux paramètres à partir de ActionController::Parameters, vous devez d'abord autoriser les paramètres, puis appeler to_h sur l'objet.

def do_something_with_params
  params.permit([:param_1, :param_2]).to_h
end

La procédure ci-dessus renverrait un hachage avec les paramètres que vous venez d'autoriser, mais si vous ne souhaitez pas autoriser les paramètres et souhaitez ignorer cette étape, il existe un autre moyen d'utiliser la méthode to_unsafe_hash:

def do_something_with_params
  params.to_unsafe_h.slice(:param_1, :param_2)
end

Il existe un moyen de toujours autoriser les paramètres depuis une configuration de application.rb. Si vous souhaitez toujours autoriser certains paramètres, vous pouvez définir une option de configuration. Remarque: ceci renverra le hachage avec des clés de chaîne, pas des clés de symbole.

#controller and action are parameters that are always permitter by default, but you need to add it in this config.
config.always_permitted_parameters = %w( controller action param_1 param_2)

Maintenant, vous pouvez accéder aux paramètres comme:

def do_something_with_params
  params.slice("param_1", "param_2").to_h
end

Notez que maintenant les clés sont des chaînes et non des symboles.

J'espère que cela vous aidera à comprendre la racine de votre problème.

Source: eileen.codes

41
SsouLlesS

Depuis dans Rails 5, les paramètres sont de la classe 'ActionController :: Parameters'

Si vous faites params.to_h vous obtiendrez l'erreur suivante.

*** ActionController::UnfilteredParameters Exception: unable to convert 
unpermitted parameters to hash

Vous pouvez faire comme suit pour obtenir les paramètres au format Hash:

parameters = params.permit(params.keys).to_h

Mais méfiez-vous de l'utiliser! Vous autorisez tous les paramètres pouvant inclure des paramètres inconnus pouvant nuire à votre code.

6
Abhi

Je pense que ce qui se passe est la suivante: 

Dans une console, vous utilisez un hachage simple appelé attributes. En tant que hash, le paramètre attributes de la console a une méthode d'instance valide appelée values

Dans votre application Rails, le hachage params n'est plus un simple hachage. C'est une instance de la classe ActionController::Parameters. En tant qu'instance de cette classe, elle ne possède pas de méthode d'instance appelée values, mais elle possède une méthode d'instance appeléeto_h & to_unsafe_h, qui permettrait d'atteindre vos objectifs. Après avoir appelé to_h dans vos paramètres, vous pouvez appeler la méthode values.

1
BigRon

Mot à la sagesse: si vous utilisez link_to_sorted à partir de la gemme sortis , cela coupe les vues dans Rails 5.

0
cd-rum