web-dev-qa-db-ger.com

Rails 5: Hashwerte können nicht vom Parameter abgerufen werden

Ich bin auf ein seltsames Thema gestoßen.

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

ist der Fehler, den ich bekomme, wenn ich einem param-Hash eine Variable zuweise und versuche, dessen Werte zu ermitteln. 

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

der Parameter sieht folgendermaßen aus: Ein Hash von Hashes:

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

wenn ich das jetzt in der Konsole mache und dies einem Variablenattribut zuweise mache, funktioniert es einwandfrei. Ich habe also Schwierigkeiten zu verstehen, was hier nicht funktioniert - und wie es funktioniert.

einen Blick auf this werfen. Sehr seltsam, da ActionController::Parameters eine Unterklasse von Hash ist. Sie können ihn direkt in einen Hash konvertieren, indem Sie die to_h-Methode des Params-Hashes verwenden.

to_h funktioniert jedoch nur mit Whitelist-Parametern, sodass Sie Folgendes tun können:

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

Wenn Sie stattdessen jedoch keine Whitelist verwenden möchten, müssen Sie lediglich die to_unsafe_h-Methode verwenden.

Aktualisieren

Ich war sehr neugierig auf dieses Problem, also fing ich an zu recherchieren, und jetzt, da Sie klargestellt haben, dass Sie Rails 5 verwenden, ist dies die Ursache dieses Problems, wie @tillmo in stabilen Releases von Rails wie 4.x sagte: ActionController::Parameters ist ein Unterklasse von Hash, also sollte es in der Tat auf die values-Methode reagieren, jedoch in Rails 5 ActionController::Parameters gibt jetzt ein Objekt statt eines Hash zurück

Note: Dies hat keinen Einfluss auf den Zugriff auf die Schlüssel im Parameter-Hash wie params[:id]. Sie können die Pull-Anforderung sehen, die diese Änderung implementiert hat.

Um auf die Parameter im Objekt zuzugreifen, können Sie den Parametern to_h hinzufügen:

params.to_h

Wenn wir die to_h-Methode in ActionController::Parameters betrachten, können wir sehen, ob die Parameter zulässig sind, bevor sie in einen Hash konvertiert werden.

# 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

zum Beispiel

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

Was würde zurückkehren:

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

Aber jetzt wird ein ActionController::Parameters Objekt zurückgegeben.

Wenn Sie to_h aufrufen, wird ein leerer Hash zurückgegeben, da param_1 und param_2 nicht zulässig sind.

Um von ActionController::Parameters auf die Parameter zugreifen zu können, müssen Sie zuerst die Parameter zulassen und dann to_h für das Objekt aufrufen

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

Das Obige würde einen Hash mit den gerade erlaubten Parametern zurückgeben, aber wenn Sie die Parameter nicht zulassen und diesen Schritt überspringen möchten, gibt es eine andere Möglichkeit, die to_unsafe_hash-Methode zu verwenden:

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

Es gibt eine Möglichkeit, die Parameter immer aus einer Konfiguration von application.rb zuzulassen. Wenn Sie bestimmte Parameter immer zulassen möchten, können Sie eine Konfigurationsoption festlegen. Hinweis: Dadurch wird der Hash mit String-Schlüsseln und nicht mit Symbolschlüsseln zurückgegeben.

#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)

Jetzt können Sie auf die Parameter zugreifen wie:

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

Beachten Sie, dass die Schlüssel jetzt Zeichenfolgen und keine Symbole sind.

Ich hoffe, dies hilft Ihnen, die Wurzel Ihres Problems zu verstehen.

Quelle: eileen.codes

41
SsouLlesS

Da in Rails 5 Parameter der Klasse 'ActionController :: Parameters' gehören

Wenn Sie params.to_h ausführen, wird der folgende Fehler angezeigt.

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

Sie können folgendermaßen vorgehen, um die Parameter als Hash-Format zu erhalten:

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

Aber hüte dich vor dieser Verwendung! Sie erlauben alle Parameter, die unbekannte Parameter enthalten können, die Ihren Code beschädigen können.

6
Abhi

Ich denke, was passiert, ist folgendes: 

In einer Konsole arbeiten Sie mit einem einfachen Hash namens attributes. Als Hash hat der Parameter attributes in der Konsole eine gültige Instanzmethode , die als values bezeichnet wird. 

In Ihrer Rails-App ist der Params-Hash kein einfacher Hash mehr. Es ist eine Instanz der ActionController::Parameters-Klasse. Als Instanz dieser Klasse verfügt sie nicht über eine Instanzmethode mit dem Namen values, jedoch über eine Instanzmethode mit dem Namento_h & to_unsafe_h, die Ihre Ziele erreichen würde. Nachdem Sie to_h für Ihre Parameter aufgerufen haben, können Sie die values-Methode aufrufen.

1
BigRon

Um es klarzustellen: Wenn Sie link_to_sorted aus dem sortiert gem verwenden, unterbricht es die Ansichten in Rails 5.

0
cd-rum