这有什么问题? 是的,我可以做一个if else声明,但我想用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
答案 0 :(得分:5)
case
的工作方式是它不会调用您想要放在when
子句中的任何方法。相反,它在===
子句上使用when
,将case
- ed thingy作为参数传递。
换句话说:
case user
when admin? then 42
end
不
42 if user.admin?
但是
42 if admin? === user
由于您在控制器中没有admin?
方法,因此获得NoMethodError
。
只需用简单的if
- elsif
重写即可。
答案 1 :(得分:4)
ndn在他的回答中解释了为什么你的例子中的case语句不起作用。
您可以切换为if/elsif
块或稍长when current_user.admin?
的语法。或者你可以定义一些返回lambdas的方法:
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
答案 2 :(得分: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
答案 3 :(得分:1)
根据Ruby文档:
Case语句由一个可选条件组成,该条件位于case的参数位置,并且在子句时为零或更多。匹配条件的第一个when子句(或者如果条件为null则求值为布尔值,则为“wins”,并执行其代码节。
如果指定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
无法在is_admin?
上致电current_user
。
要修复代码,您可以删除案例条件。在这种情况下,将选择评估为真值的第一个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
答案 4 :(得分:1)
case语句的工作原理是将给定值与when
语句的值进行比较(使用===
)。因此case current_user; when current_user.is_admin?
会检查current_user
是否等于current_user.is_admin?
,这显然不是。{/ p>
基本上
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。这只是一个偏好问题。