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

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

现在,当我在控制台中执行此操作并将其分配给变量属性时,它会完美地工作.因此,我正在努力理解什么在这里不起作用,以及如何使它起作用.

推荐答案

看看this.非常奇怪,因为ActionController::Parameters是Hash的一个子类,所以可以使用params Hash上的to_h方法将其directly转换为Hash.

但是,to_h只适用于白名单参数,因此您可以执行以下操作:

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

但是如果你不想将其列入白名单,那么你只需要使用to_unsafe_h方法.

Update

我对这个问题很好奇,所以我开始研究,现在你澄清了你正在使用Rails 5,这就是这个问题的原因,正如@tillmo在Rails 4的稳定版本中所说的.x、 ActionController::Parameters是Hash的一个子类,因此它确实应该响应values方法however in Rails 5 100 now returns an Object instead of a Hash

Note:这不会影响访问参数散列中的键,比如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

这将返回:

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

但现在它将返回ActionController::Parameters个对象.

在这个问题上调用to_h将返回一个空哈希,因为不允许使用param_1和param_2.

要从ActionController::Parameters访问params,需要先允许params,然后对对象调用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

应用程序总是有一个许可证.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

Ruby-on-rails相关问答推荐

为Rails服务器推荐的交付类型

Web控制台不会出现在例外页面Rails 7.1.1上

ActiveRecord::声明在类别中无效#new

Rails 7 共享刺激控制器功能

计算总价(商品数量*商品价格)

如何为 Rails SimpleForm Select 框设置默认 Select 值

在 Windows 上使用 Ruby 进行开发

控制器规格与请求规格?

渲染:动作和渲染:模板之间的区别

在 PostgreSQL 中强制字符串的最大长度

Ruby on Rails 基本概念总结

在 Rails 生产中禁用assets资源 缩小

ActiveRecord 查找现有表索引

如何在 RSpec 中包含 Rails 助手

你如何覆盖 form_for 助手中的类名?

Rails,Docker:主机不存在:默认

我应该在 Heroku Cedar 上使用薄的还是独角兽

如何从 ApplicationHelper 调用 ApplicationController 方法

简单的 rails rake 任务拒绝运行并出现错误不知道如何构建任务,为什么?

设置EDITOR或BUNDLER_EDITOR环境变量