2017-07-08 134 views
0

這是什麼問題? 是的,我可以做一個if else語句,但我想用case語句做這件事。爲什麼我的ruby case語句不起作用?

在我的控制器

query_limit = case current_user 
       when nil 
        return 5 
       when is_admin? 
        return 200 
       when has_role?('registered') 
        return 20 
       else 
        return 5 
       end 


NoMethodError (undefined method `is_admin?' for #<V1::MyController:123123123>): 

puts query_limit#總是ELSE當我這樣做:

query_limit = case current_user 
        when nil 
         return 5 
        when current_user.is_admin? 
         return 200 
        when current_user.has_role?('registered') 
         return 20 
        else 
         return 5 
        end 

型號用戶

class User 
    def is_admin? 
    self.has_role?('administrator') 
    end 

    def has_role?(the_role) 
    self.roles.any? {|role| role.slug == the_role} 
    end 
end 

回答

-1

按照Ruby文檔:

Case語句包括一個可選的條件,這是在位置的情況下的爭論,以及當條款時零或更多。第一個when子句匹配條件(或者評估爲布爾真值,如果條件爲空)「勝出」,並且其代碼段被執行。

如果指定current_user視情況條件,則第一when表達式匹配current_user將被執行。 current_user.is_admin?返回一個布爾值,該值將永遠不等於current_user,所以你的第二個例子將始終以else分支:

case current_user 
    when nil # current_user != nil, skip condition 
    return 5 
    when current_user.is_admin? # current_user != current_user.is_admin?, skip condition 
    return 200 
    when current_user.has_role?('registered') # and so on 
    return 20 
    else 
    return 5 
end 

你的第一個例子被打破,因爲沒有定義本地is_admin?方法。在這種情況下,case不知道在current_user上致電is_admin?

要修復您的代碼,您可以移除案例條件。在這種情況下,計算結果爲truthy值第一when條款將被選擇:

case # no current_user here! 
    when current_user.nil? # current_user.nil? is false, skip condition 
    return 5 
    when current_user.is_admin? # current_user.is_admin? is truthy, run this one! 
    return 200 
    when current_user.has_role?('registered') 
    return 20 
    else 
    return 5 
end 
+1

'當nil'沒有爲'case'任何說法? –

+0

哎呀,我的壞。固定。 –

+1

現在它已修復,您的代碼與我的答案完全相同。 –

4

的方式case作品是它不調用無論您想在when中輸入什麼方法條款。相反,它使用when子句中的===,通過case作爲參數。

換句話說:

case user 
when admin? then 42 
end 

是不是

42 if user.admin? 

42 if admin? === user 

而當你沒有在控制器的admin?方法,你會得到一個NoMethodErrorelsif代替 -


簡單if就重寫。

1

你可以這樣,這基本上是寫一個變相if/elsif

query_limit = case 
       when current_user.nil? 
        return 5 
       when current_user.is_admin? 
        return 200 
       when current_user.has_role?('registered') 
        return 20 
       else 
        return 5 
       end 
1

case語句的工作方式(使用===)比較反對when語句的值給定值。所以case current_user; when current_user.is_admin?檢查current_user是否等於current_user.is_admin?,這顯然不會。

基本上

case x 
    when y 
    case1 
    when z 
    case2 
    ... 
end 

相當於

if y === x 
    case1 
elsif z === x 
    case2 
... 
end 

如果結構不適合你的使用情況,您應該使用case

PS:return從當前方法返回,所以這不是你想要的。

PPS:您也可以使用case而不用表達式作爲編寫任意if-elsif鏈的不同方式。所以,你可以做你想做的是這樣的:

query_limit = case 
    when current_user == nil 
    5 
    when current_user.is_admin? 
    200 
    ... 
end 

不過,當然,你也可以只用一個簡單的IF-ELSIF這一點。這只是一個偏好問題。

3

ndn在他的回答中已經解釋了爲什麼您的示例中的case語句不起作用。

您可以切換到if/elsif塊或稍長的when current_user.admin?語法。或者,你可以定義一些方法返回lambda表達式:

def is_admin? 
    ->(user) { user.is_admin? } 
end 

def has_role?(role) 
    ->(user) { user.has_role?(role) } 
end 

有了這些,你可以這樣寫:

query_limit = case current_user 
       when nil then 5 
       when is_admin? then 200 
       when has_role?('registered') then 20 
       else 5 
       end