为什么我的ruby案例陈述不起作用?

Jan*_*Jan 0 ruby ruby-on-rails case switch-statement

这有什么问题?是的,我可以做一个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>):
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

模型用户

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
Run Code Online (Sandbox Code Playgroud)

Mát*_*osi 7

根据 Ruby 文档:

Case 语句包含一个可选条件,它位于 case 的参数位置,以及零个或多个 when 子句。第一个匹配条件的 when 子句(或评估为布尔真值,如果条件为空)“获胜”,并且它的代码节被执行。

如果指定current_user为 case 条件,则将执行第一个when匹配的表达式current_usercurrent_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
Run Code Online (Sandbox Code Playgroud)

您的第一个示例已损坏,因为没有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
Run Code Online (Sandbox Code Playgroud)


ndn*_*kov 5

方法case是它不会调用你想要放在when子句中的任何方法.相反,它使用将-ed thingy作为参数传递===when子句case.

换一种说法:

case user
when admin? then 42
end
Run Code Online (Sandbox Code Playgroud)

是不是

42 if user.admin?
Run Code Online (Sandbox Code Playgroud)

42 if admin? === user
Run Code Online (Sandbox Code Playgroud)

因为你admin?在控制器中没有方法,所以你得到了一个NoMethodError.


只需简单地重写它if- elsif而不是.


spi*_*ann 5

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
Run Code Online (Sandbox Code Playgroud)

使用这些方法,您可以编写:

query_limit = case current_user
              when nil then 5
              when is_admin? then 200
              when has_role?('registered') then 20
              else 5
              end
Run Code Online (Sandbox Code Playgroud)