41

我遇到了一个奇怪的问题。

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"}}

现在,当我在控制台中执行此操作并将其分配给变量属性时,它可以完美地工作。所以我很难理解什么在这里不起作用——以及如何让它起作用。

4

4 回答 4

81

看看这个。非常奇怪,因为ActionController::Parameters它是 Hash 的子类,您可以使用params 哈希上的方法将其直接转换为哈希。to_h

但是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方法,但是在 Rails 5 中ActionController::Parameters现在返回一个 Object 而不是 Hash

注意:这不会影响访问 params 哈希中的键,例如params[:id]. 您可以查看实现此更改的拉取请求。

要访问对象中的参数,您可以添加to_h参数:

params.to_h

如果我们查看中的to_h方法,ActionController::Parameters我们可以看到它在将参数转换为哈希之前检查参数是否被允许。

# 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

哪个会返回:

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

但现在这将返回一个ActionController::Parameters对象。

调用to_h它会返回一个空哈希,因为 param_1 和 param_2 是不允许的。

要从 访问参数ActionController::Parameters,您需要首先允许参数,然后调用to_h对象

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

以上将返回带有您刚刚允许的参数的哈希,但如果您不想允许参数并希望跳过该步骤,则还有另一种使用to_unsafe_hash方法:

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

有一种方法总是允许来自 application.rb 的配置中的参数,如果你想总是允许某些参数,你可以设置一个配置选项。注意:这将返回带有字符串键的哈希,而不是符号键。

#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

于 2016-01-22T16:16:54.350 回答
14

Since Rails 5, params are of class 'ActionController::Parameters'

If you do params.to_h you will get the following error.

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

You can do as follows to permit all the params and get as Hash format:

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

"But beware of using this! You are permitting all the params which may include unknown params that can harm your code."

于 2017-08-24T11:28:28.897 回答
1

我认为正在发生的事情如下:

在控制台中,您正在使用一个名为attributes. 作为哈希,attributes控制台中的参数有一个有效的实例方法,称为values.

在您的 rails 应用程序中,params 哈希不再是简单的哈希。它是ActionController::Parameters类的一个实例。作为该类的一个实例,它没有一个名为 的实例方法values,但它确实有一个名为 to_h&的实例方法to_unsafe_h,它可以实现您的目标。调用to_h参数后,您可以调用该values方法。

于 2016-01-22T16:12:04.490 回答
0

明智的说法:如果您link_to_sorted排序的gem 中使用它会破坏 Rails 5 中的视图。

于 2017-08-11T19:46:34.973 回答