Ruby 2关键字参数和ActionController::参数

4bbkushb  于 2023-01-30  发布在  Ruby
关注(0)|答案(5)|浏览(182)

我有一个运行在ruby 2.1上的rails 4应用程序,有一个User模型,类似于

class User < ActiveModel::Base
  def self.search(query: false, active: true, **extra)
    # ...
  end
end

正如您在search方法中所看到的,我尝试使用ruby 2的新关键字参数特性。
问题是,当我从控制器中调用这段代码时,所有的值都会被转储到query中。

参数

{"action"=>"search", "controller"=>"users", query: "foobar" }
  • 请注意,这是一个ActionController::Parameters对象,而不是看上去的哈希 *
    用户控制器
def search
  @users = User.search(params)
end

我觉得这是因为params是一个ActionController::Parameters对象,而不是一个散列。然而,即使在传入params时调用to_h,也会将所有内容转储到query中,而不是预期的行为。我认为这是因为键现在是字符串而不是符号。
我知道我可以建立一个新的散列w/符号作为键,但这似乎是更多的麻烦比它的价值。想法?建议?

kwvwclae

kwvwclae1#

关键字参数必须作为带符号的哈希值传递,而不是字符串:

class Something
  def initialize(one: nil)
  end
end

irb(main):019:0> Something.new("one" => 1)
ArgumentError: wrong number of arguments (1 for 0)

ActionController::Parameters继承自默认为字符串键的ActiveSupport::HashWithIndifferentAccess

a = HashWithIndifferentAccess.new(one: 1)
=> {"one"=>1}

要使其成为符号,可以调用symbolize_keys方法。User.search(params.symbolize_keys)

idv4meu8

idv4meu82#

我同意Morgoth的观点,但是在rails ~5中,你会收到一个弃用警告,因为ActionController::Parameters不再从hash继承。

params.to_unsafe_hash.symbolize_keys

或者如果您有嵌套的参数,这在构建API端点时是常见的情况:

params.to_unsafe_hash.deep_symbolize_keys

您可以向ApplicationController中添加一个如下所示的方法:

def unsafe_keyworded_params
  @_unsafe_keyworded_params ||= params.to_unsafe_hash.deep_symbolized_keys
end
vwhgwdsa

vwhgwdsa3#

你很可能确实需要它们作为符号。试试这个:

def search
  @users = User.search(params.inject({}){|para,(k,v)| para[k.to_sym] = v; para}
end

我知道这不是理想的解决方案,但它是一个班轮。

qyuhtwio

qyuhtwio4#

在这个特定的例子中,我认为最好传递params对象并将其视为params对象,而不是试图巧妙地使用Ruby 2中的新功能。
首先,阅读这篇文章可以更清楚地了解变量的来源,以及它们可能缺失/不正确/诸如此类的原因:

def search(params)
  raise ArgumentError, 'Required arguments are missing' unless params[:query].present?

  # ... do stuff ...
end

在我看来,你试图做的事情只会使问题变得模糊不清,并在试图调试问题时使事情变得混乱:

def self.search(query: false, active: true, **extra)
  # ...
end

# Method explicitly asks for particular arguments, but then you call it like this:
User.search(params)

就我个人而言,我认为这段代码有点臭。
然而......撇开个人观点不谈,我将如何修复它,这将是猴子补丁的ActionController::Parameters类,并添加一个#to_h方法,该方法根据您需要将数据结构化,以传递给这样的方法。

k2fxgqgv

k2fxgqgv5#

使用to_unsafe_hash是不安全的,因为它包含不允许的参数。(请参阅ActionController::Parameters#permit)更好的方法是使用to_hash

params.to_hash.symbolize_keys

或者如果您有嵌套的参数:

params.to_hash.deep_symbolize_keys

参考:https://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-to_hash

相关问题