2014-01-27 31 views
5

我有一个在ruby 2.1上运行的rails 4应用程序。我有一个User模型,看起来像Ruby 2关键字参数和ActionController ::参数

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

正如你可以在搜索方法见我试图使用new关键字红宝石的参数配备2

的问题是,当我把这个代码从我的控制器中的所有值被转储到query

PARAMS

{"action"=>"search", "controller"=>"users", query: "foobar" } 

请注意,这是一个ActionController的::参数对象,而不是因为它看起来

UsersController

def search 
    @users = User.search(params) 
end 

我觉得一个哈希这是因为params是ActionController::Parameters对象而不是散列。然而,即使在将参数传递给query而不是预期的行为时,甚至会在params上调用to_h。我认为这是因为键现在是字符串而不是符号。

我知道我可以建立一个新的散列w /符号作为键,但这似乎比它的价值更麻烦。想法?建议?

+0

发布内容你'params'将有助于 – bjhaid

+0

@bjhaid更新瓦特/ params' –

回答

0

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

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

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

+0

的'内容我猜这是什么'User.search(params.to_h)'会d o因为OP声称他已经完成了 – bjhaid

+0

@bjhaid这与'to_h'略有不同。这使得键符号,而'to_h'使键字符串(这显然会中断关键字参数)。 –

+0

作为引用[这里](https://github.com/rails/strong_parameters/issues/83#issuecomment-14935519)如果它是一个字符串,它将保持一个字符串。我的代码将第一个字符串转换为符号,这很可能是红宝石正在寻找的。 – snowe

0

在这种特定情况下,我认为你最好通过params对象,并把它当作这样的,而不是巧言令色与红宝石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方法,它将数据结构化,因为你需要它传递给像这样的方法。

7

关键词参数必须与符号哈希传递,而不是字符串:

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)

+0

在rails tracker上打开一个问题:https://github.com/rails/rails/issues/ 14643 – morgoth

+1

在Ruby 2.2中,执行Something.new(“one”:1)将会起作用,所以问题不在于符号与字符串的关系,使用'=>'vs':'似乎有所作用。在你传递这个参数之前将会解决这个问题 –

+1

@WinstonKotzan我认为你误解了2.2的语法,Something.new(“one”:1)''使用符号键而不是字符串键来创建一个哈希值。 。新(“一”=> 1)'在2.2,你会得到同样的错误。所以你确实需要'symbolize_keys'。 – Kelvin

2

我同意Morgoth,但是,与轨〜5你会得到一个弃用警告,因为ActionController :: Parameters不再继承哈希。因此,你可以这样做:

params.to_unsafe_hash.symbolize_keys 

,或者如果你有嵌套PARAMS这是常有的情况下建立API端点时:

params.to_unsafe_hash.deep_symbolize_keys 

您可以添加到ApplicationController中的方法,看起来是这样的:

def unsafe_keyworded_params 
    @_unsafe_keyworded_params ||= params.to_unsafe_hash.deep_symbolized_keys 
end 
相关问题