2014-01-27 38 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 
相關問題