1

所以我想做的是根据current_user.

这就是我所拥有的:

  path = case current_user.roles.where(:name => "vendor")
    when :vendor
      dashboard_path
    when :guest
      home_path
    else
      home_path
  end

  redirect_to path     

我正在使用cancan,并且据我所知,找出用户角色的唯一方法是执行current_user.has_role? :admincurrent_user.roles.where(:name => role_name).

鉴于这些限制(或告诉我另一种方式来确定用户的角色),我如何让这个案例陈述起作用?

编辑 1

假设我正在检查多个角色,而不仅仅是我这里的 2 个 - 可能是 4 个或 5 个。

编辑 2

需要明确的是,这是我目前的设置。

我正在使用 Devise、CanCan 和 Rolify。Rolify 允许用户拥有多个角色,但我的应用程序不会有那个用例。一个用户将只有一个角色。它们可以是vendor, buyer, guest, superadmin.

如果他们是 a vendor,他们只能看到dashboard_path属于他们的那个。他们看不到vendor storefront属于其他任何人的任何其他人。他们也不应该能够看到其他供应商的产品。因此,一旦他们登录,他们不root_path应该是其他所有角色的角色。dashboard_pathhome_pathroot_path

如果他们是guest,他们可以看到除价格之外的所有内容 - 我已经有了这个逻辑。我是这样实现的:

if user.has_role? :guest
    can :read, [Product, Vendor, Banner]
    cannot :view_prices, Product
end

然后在我看来,我只是做了这样的事情:

<% if can? :view_prices, Product %>
    <div class="price pull-right">
      <%= number_to_currency(@product.price) %> ea
    </div>      
<% else %>
   <span class="no-price pull-right"><%= link_to "Log In To See Price", login_path %></span>
<% end %>

所以,基本上......我的真正目标是尝试root_path根据用户的角色来改变。我基本上是在尝试实现这个问题的答案。

4

2 回答 2

6

最终答案 (对于早期的答案,见下文)

如果您的用户只能拥有一个角色,我会说您当前的实现并不完全合适。但是,如果您确实需要保留此实现,则可以执行以下操作:

class User < ActiveRecord::Base
  # this will return the name of the first (so the only one) 
  # role that your user has, or nil. 
  def role_name
    roles.first.try( :name ) 
  end
end  

所以现在您的案例陈述将起作用:

path = case current_user.role_name
         when 'vendor' ; dashboard_path
         when 'guest'  ; home_path
         when 'foo'    ; bar_path
         else home_path
       end

我仍然鼓励您将案例语句包装在帮助程序中,以实现可重用性和更易于维护。

较早的答案

我不确定我是否理解您的问题,但我认为您在这里不需要案例陈述:

redirect_to (current_user.has_role? :vendor ? dashboard_path : home_path)

另一种方法是将部分责任推给用户类(或演示者):

class User < ActiveRecord::Base
  def home_page
    # here some logic to return a symbol like :home or :dashboard,
    # depending on your roles implementation. Your User could even use
    # a state machine to do this, or have multiple decorators.
  end
end

然后有一个帮手

 def home_path_for( user )
   case user.home_page
     when :home      ; home_path
     when :dashboard ; dashboard_path
     when :foo       ; bar_path
     else home_path
   end
 end

第一次编辑

如果您的用户一次可以拥有多个角色,我会说 case 语句不合适。case是一个分支语句,当您在一组可能的结果中只有一个且只有一个输入一个且只有一个结果时,它是合适的。

因此,您必须将角色列表减少到中间状态,例如:

 DASHBOARD_ROLES = [:vendor, :admin]
 CLIENT_ROLES    = [:client, :prospect]
 BASIC_ROLES     = [:logged_visitor]

 if (DASHBOARD_ROLES & user_roles).any?
   :admin_dashboard
 else if (CLIENT_ROLES & user_roles).any?
   :client_dashboard
 # additionnal, different logic is possible
 else if (BASIC_ROLES & user_roles).any? && user_logged_in? && user_roles.first != :prospect
   :logged_dashboard
 else
   :home
 end

这是一种完全不同的逻辑。

于 2013-03-15T08:24:20.387 回答
1

首先,如果可能的话,您可能需要解决用户具有多个角色的情况。

假设一个用户有一个角色(尽管如果需要我们可以添加更多条件)你能考虑一个哈希吗?

就像是 -

path = {:vendor => dashboard_path, :guest => home_path} [current_user.active_role] || default_path

我做了一些假设——

  1. current_user.active_role可能是用户的当前角色,您可以根据该角色重定向答案。
  2. default_path是不言自明的。
于 2013-03-15T08:23:50.670 回答