首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将if/else转换为case/when in ruby

将if/else转换为case/when in ruby
EN

Stack Overflow用户
提问于 2016-03-21 17:15:51
回答 3查看 101关注 0票数 0

我遵循莱恩·贝茨的RC#386授权。Ryan的原始代码如下:

代码语言:javascript
复制
module Permissions
  def self.permission_for(user)
    if user.nil?
      GuestPermission.new
    elsif user.is_admin?
      AdminPermission.new(user)
    else
      MemberPermission.new(user)
    end
  end
end

就像预期的那样。

我需要允许的不仅仅是三个授权方案。我需要添加额外的授权角色,如EditorModeratorSenior Editor等。我试图通过将其更改为case-statement来实现这一点。我的代码是:

代码语言:javascript
复制
module Permissions
  def self.permission_for(user)
    case user#.role  #TODO: This will eventually be refactored into a role checker...
    when user.is_admin?
       AdminPermission.new(user)
    when user.current_user
       MemberPermission.new(user)
    else
       GuestPermission.new
    end
  end
end

但是,我收到了一个NoMethod错误

代码语言:javascript
复制
when user.is_admin?

有什么想法吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-03-21 19:41:55

如果您问我case/when块的−,主要的优势是case中的条件将精确地运行一次和一次。

所以在这种情况下:

代码语言:javascript
复制
case some_relatively_expensive_operation()
  when :foo
    # ...
  when :bar
    # ...
end

some_relatively_expensive_operation只运行一次,而在本例中:

代码语言:javascript
复制
if some_relatively_expensive_operation() == :foo
  # ...
elsif some_relatively_expensive_operation() == :bar
  # ...
end

some_relatively_expensive_operation()将运行一次(如果是:foo)或两次(如果是其他东西)。

这不仅关系到性能,而且还使条件以后更容易更改,因为您只需要这样做一次,而不管您有多少if/elsif块,都不需要这样做。

显然,如果您想测试不同的−(这就是当前代码所做的)的多个条件,那么这个结构根本无法工作。是的,你可以用一个lambda来解决这个问题,另一个答案就是这样做,但这完全忽略了这个结构的意义,就像用锤子钉钉子一样。

因此,您需要做的是向对象user添加一个方法,该方法返回一个带有角色的值。我对您的User模型没有洞察力,但这可能很简单:

代码语言:javascript
复制
class User

  # [..]

  def role
    if is_admin?
      :admin
    else
      :member
    end
  end
end

我们仍然需要检查特殊来宾权限情况,这可以在主case之前完成。

代码语言:javascript
复制
def self.permission_for(user)
  # No current user - return Guest permissions
  return GuestPermission.new unless user.current_user

  case user.role
    when :admin
      AdminPermission.new(user)
    when :member
      MemberPermission.new(user)
   end
end

或者,您可以修改User.role以返回:guest。你喜欢什么都行。

现在,您会注意到,这些行实际上看起来非常相似。为什么在这里使用case/when块?我们就不能从user.role构造类名吗?不,我们可以!

代码语言:javascript
复制
  # Get instance to the class
  klass = Object.const_get "#{user.role.to_s.capitalize}Permission"

  # And create it!
  klass.new user

我们可以做一个两行的方法!

代码语言:javascript
复制
def self.permission_for(user)
  return GuestPermission.new unless user.current_user
  return Object.const_get("#{user.role.to_s.capitalize}Permission").new user
end

如果没有当前用户,User.role甚至返回:guest一行。

票数 2
EN

Stack Overflow用户

发布于 2016-03-21 17:41:10

代码语言:javascript
复制
case user
when ->(u) { u.is_admin? } then AdminPermission.new(user)
when ->(u) { u.current_user } then MemberPermission.new(user)
else GuestPermission.new
end

代码语言:javascript
复制
case 
when user.is_admin? then AdminPermission.new(user)
when user.current_user then MemberPermission.new(user)
else GuestPermission.new
end

前者使用Proc#===,后者是一个完全有效的情况,没有初始条件。

票数 2
EN

Stack Overflow用户

发布于 2016-03-21 17:25:04

Case语句检查每个when子句的相等性,例如

代码语言:javascript
复制
case x
   when 1
      puts "Do something when x === 1."
   when "D"
      puts "Do something when x === D."
   else
      puts "Doing nothing"
end

因此,对于您的示例,您可能希望保持if/ want样式语法或执行如下操作:

代码语言:javascript
复制
case user.role
   when :guest
      #something
   when :admin
      #something
   #etc...
end  

http://ruby-doc.org/docs/keywords/1.9/Object.html#method-i-case

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36137613

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档