Rails 5: 无法从参数中检索散列值
Rails 5: unable to retrieve hash values from parameter
我 运行 遇到了一个奇怪的问题。
undefined method `values' for #<ActionController::Parameters:0x007fb06f6b2728>
是我得到的错误,当我将变量分配给参数哈希并尝试获取它的值时。
attributes = params[:line_item][:line_item_attributes_attributes] || {}
attributes.values
参数看起来像这样一个散列的散列:
{"0"=>{"product_attribute_id"=>"4"}, "1"=>{"product_attribute_id"=>"7"}}
现在,当我在控制台中执行此操作并将其分配给变量属性时,它可以完美运行。所以我正在努力了解什么在这里不起作用 - 以及如何让它起作用。
我认为发生的事情如下:
在控制台中,您正在使用一个名为 attributes
的简单散列。作为散列,控制台中的 attributes
参数有 a valid instance method 调用 values
。
在您的 rails 应用程序中,参数哈希不再是简单的哈希。它是 ActionController::Parameters
class 的实例。作为 class 的实例,它没有名为 values
的实例方法,但它确实有 an instance method called to_h
& to_unsafe_h
,这将实现您的目标.在您的参数上调用 to_h
之后,您可以调用 values
方法。
使用参数散列上的 to_h
方法查看 this. Very weird since ActionController::Parameters
is a subclass of Hash, you can convert it directly 散列。
但是 to_h
仅适用于列入白名单的参数,因此您可以执行以下操作:
permitted = params.require(:line_item).permit(: line_item_attributes_attributes)
attributes = permitted.to_h || {}
attributes.values
但是如果您不想加入白名单,那么您只需要使用 to_unsafe_h
方法。
更新
我对这个问题很好奇,所以我开始研究,现在你澄清你正在使用 Rails 5,这就是这个问题的原因,正如@tillmo 在稳定版本中所说Rails和4.x一样,ActionController::Parameters
是Hash的子类,所以确实应该响应values
方法,however in Rails5 ActionController::Parameters
现在 return 是对象而不是哈希
注意:这不会像params[:id]
那样影响访问参数哈希中的键。您可以查看实施此更改的Pull Request。
要访问对象中的参数,您可以将 to_h
添加到参数中:
params.to_h
如果我们查看 ActionController::Parameters
中的 to_h
方法,我们可以看到它在将参数转换为散列之前检查是否允许参数。
# 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
例如:
def do_something_with_params
params.slice(:param_1, :param_2)
end
哪个 return:
{ :param_1 => "a", :param_2 => "2" }
但现在 return 一个 ActionController::Parameters
对象。
在此调用 to_h
将 return 一个空散列,因为 param_1 和 param_2 是不允许的。
要从 ActionController::Parameters
访问参数,您需要先允许参数,然后在对象
上调用 to_h
def do_something_with_params
params.permit([:param_1, :param_2]).to_h
end
上面的代码会 return 一个包含您刚刚允许的参数的散列,但是如果您不想允许这些参数并想跳过该步骤,还有另一种使用 to_unsafe_hash
方法的方法:
def do_something_with_params
params.to_unsafe_h.slice(:param_1, :param_2)
end
有一种方法可以始终允许来自 application.rb 的配置中的参数,如果您希望始终允许某些参数,您可以设置一个配置选项。注意:这将 return 带有字符串键的散列,而不是符号键。
#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)
现在您可以访问以下参数:
def do_something_with_params
params.slice("param_1", "param_2").to_h
end
请注意,现在键是字符串而不是符号。
希望这有助于您了解问题的根源。
来源:eileen.codes
明智的话:如果您使用 sorted gem 中的 link_to_sorted
,它会破坏 Rails 5.
中的视图
因为Rails 5,参数是class 'ActionController::Parameters'
如果你这样做 params.to_h 你会得到以下错误。
*** ActionController::UnfilteredParameters Exception: unable to convert
unpermitted parameters to hash
您可以通过如下操作来允许所有参数并得到哈希格式:
parameters = params.permit(params.keys).to_h
“但要小心使用它!您允许所有可能包含可能损害您代码的未知参数的参数。”
我 运行 遇到了一个奇怪的问题。
undefined method `values' for #<ActionController::Parameters:0x007fb06f6b2728>
是我得到的错误,当我将变量分配给参数哈希并尝试获取它的值时。
attributes = params[:line_item][:line_item_attributes_attributes] || {}
attributes.values
参数看起来像这样一个散列的散列:
{"0"=>{"product_attribute_id"=>"4"}, "1"=>{"product_attribute_id"=>"7"}}
现在,当我在控制台中执行此操作并将其分配给变量属性时,它可以完美运行。所以我正在努力了解什么在这里不起作用 - 以及如何让它起作用。
我认为发生的事情如下:
在控制台中,您正在使用一个名为 attributes
的简单散列。作为散列,控制台中的 attributes
参数有 a valid instance method 调用 values
。
在您的 rails 应用程序中,参数哈希不再是简单的哈希。它是 ActionController::Parameters
class 的实例。作为 class 的实例,它没有名为 values
的实例方法,但它确实有 an instance method called to_h
& to_unsafe_h
,这将实现您的目标.在您的参数上调用 to_h
之后,您可以调用 values
方法。
使用参数散列上的 to_h
方法查看 this. Very weird since ActionController::Parameters
is a subclass of Hash, you can convert it directly 散列。
但是 to_h
仅适用于列入白名单的参数,因此您可以执行以下操作:
permitted = params.require(:line_item).permit(: line_item_attributes_attributes)
attributes = permitted.to_h || {}
attributes.values
但是如果您不想加入白名单,那么您只需要使用 to_unsafe_h
方法。
更新
我对这个问题很好奇,所以我开始研究,现在你澄清你正在使用 Rails 5,这就是这个问题的原因,正如@tillmo 在稳定版本中所说Rails和4.x一样,ActionController::Parameters
是Hash的子类,所以确实应该响应values
方法,however in Rails5 ActionController::Parameters
现在 return 是对象而不是哈希
注意:这不会像params[:id]
那样影响访问参数哈希中的键。您可以查看实施此更改的Pull Request。
要访问对象中的参数,您可以将 to_h
添加到参数中:
params.to_h
如果我们查看 ActionController::Parameters
中的 to_h
方法,我们可以看到它在将参数转换为散列之前检查是否允许参数。
# 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
例如:
def do_something_with_params
params.slice(:param_1, :param_2)
end
哪个 return:
{ :param_1 => "a", :param_2 => "2" }
但现在 return 一个 ActionController::Parameters
对象。
在此调用 to_h
将 return 一个空散列,因为 param_1 和 param_2 是不允许的。
要从 ActionController::Parameters
访问参数,您需要先允许参数,然后在对象
to_h
def do_something_with_params
params.permit([:param_1, :param_2]).to_h
end
上面的代码会 return 一个包含您刚刚允许的参数的散列,但是如果您不想允许这些参数并想跳过该步骤,还有另一种使用 to_unsafe_hash
方法的方法:
def do_something_with_params
params.to_unsafe_h.slice(:param_1, :param_2)
end
有一种方法可以始终允许来自 application.rb 的配置中的参数,如果您希望始终允许某些参数,您可以设置一个配置选项。注意:这将 return 带有字符串键的散列,而不是符号键。
#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)
现在您可以访问以下参数:
def do_something_with_params
params.slice("param_1", "param_2").to_h
end
请注意,现在键是字符串而不是符号。
希望这有助于您了解问题的根源。
来源:eileen.codes
明智的话:如果您使用 sorted gem 中的 link_to_sorted
,它会破坏 Rails 5.
因为Rails 5,参数是class 'ActionController::Parameters'
如果你这样做 params.to_h 你会得到以下错误。
*** ActionController::UnfilteredParameters Exception: unable to convert
unpermitted parameters to hash
您可以通过如下操作来允许所有参数并得到哈希格式:
parameters = params.permit(params.keys).to_h
“但要小心使用它!您允许所有可能包含可能损害您代码的未知参数的参数。”