代码之家  ›  专栏  ›  技术社区  ›  Jan

为什么我的ruby case语句不起作用?

  •  3
  • Jan  · 技术社区  · 9 年前

    这有什么不对? 是的,我可以做一个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

     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
    
    5 回复  |  直到 9 年前
        1
  •  7
  •   Mate Solymosi    9 年前

    根据Ruby文档:

    Case语句包含一个可选条件,该条件位于Case的参数位置,以及零个或多个when子句。第一个匹配条件(如果条件为null,则计算为布尔真值)的when子句获胜,并执行其代码段。

    current_user 作为案例条件,那么第一个 when 匹配的表达式 当前_用户 current_user.is_admin? 返回一个永远不会等于的布尔值 当前_用户 ,因此您的第二个示例将始终采用 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 是管理员吗? 在…上 在这种情况下。

    要修复代码,可以删除case条件。在这种情况下 将选择评估为真实值的子句:

    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
    
        2
  •  5
  •   ndnenkov    9 年前

    这条路 case 工作原理是它不调用任何你想放入的方法 when === 什么时候 案例 -ed thingy作为论点。

    换句话说:

    case user
    when admin? then 42
    end
    

    42 if user.admin?
    

    但是

    42 if admin? === user
    

    因为你没有 admin? 方法,您将得到一个 NoMethodError


    用simple重写 if - elsif 相反

        3
  •  4
  •   spickermann    9 年前

    ndn已经在他的回答中解释了为什么您的示例中的案例陈述不起作用。

    您可以切换到 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
    
        4
  •  1
  •   Eric Duminil    9 年前

    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
    
        5
  •  1
  •   sepp2k    9 年前

    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 .

    return

    PPS:您也可以使用 案例

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