我正在构建一个Rails 3
应用程序,我需要根据用户在网站上注册的路径为他们提供特定的角色。我正在使用Devise和Cancan。
例如,路径
new-fundraiser
(或/users/new/fundraiser
)
需要在用户创建和时设置user.fundraiser = true
new-charity-user
(或/users/new/charity
)
需要在用户创建时设置user.charity_owner = true
。
使用Devise和Cancan实现这一目标的最简单/最佳实践方法是什么?
最初的问题表明@Houen已经在某种程度上定制了Devise。这里有一个稍微调整过的答案,适用于开箱即用的Devise设置和CanCan设置的多对多用户角色。
首先,在您的路线中,添加:
devise_scope :user do
match "/users/sign_up/:initial_role" => 'devise/registrations#new', :as => 'new_user_with_role'
end
然后你可以参考这条路线,比如:
<%= link_to 'here', new_user_with_role_path(:initial_role => 'human') %>
然后,在您的用户模型中添加
attr_accessible :initial_role
def initial_role=(role_name)
@initial_role = role_name
role = Role.find_by_name(role_name)
self.roles << role
end
def initial_role
@initial_role
end
最后在views/design/registrations/new.html.erb中添加
<%= f.hidden_field :initial_role, :value => params[:initial_role] %>
我会设置一个路由,比如:
match "/users/new/:role", :to => 'users#new'
在您的用户模型中,我会添加一个访问者:
class User < ActiveRecord::Base
def role=(role_name)
@role = role_name
case role_name
when 'charity'
self.charity_owner = true
when 'fundraiser'
self.fundraiser = true
else
# raise some exception
end
end
def role
@role
end
end
然后在用户#new.html.erb表单中添加一个隐藏字段:
<%= form.hidden_field :role, :value => params[:role] %>
那么您就根本不需要更改控制器代码。
使用开箱即用的Devise和CanCan,我根据Rails Casts#189"嵌入式关联"设置了我的用户"角色"。然而,我无法得到@calianne的答案来处理我的设置,因为假设了不同的角色方法。如果有人有类似的问题,这里有一个不那么优雅/稳健的方法,它借鉴了@cailinanne的答案。它的一个优点是不需要修改用户模型。
使用@cailinanne提供的"devise_scope"路由和"link_to"代码。跳过对用户模型的更改。最后在views/design/registrations/new.html.erb:中使用以下代码
<% if params[:initial_role] == "admin" %>
<%= hidden_field_tag "user[roles][]", :admin %>
<% elsif params[:initial_role] == "moderator" %>
<%= hidden_field_tag "user[roles][]", :moderator %>
<% elsif params[:initial_role] == "author" %>
<%= hidden_field_tag "user[roles][]", :author %>
<% end %>
此代码替换了RailsCast代码中提供的check_box_tag代码。
这肯定需要更多的工作。我会在某个时刻将if-elsif-elsif逻辑移动到控制器中,并根据User.ROLES引用它,这样在添加/删除角色时它就不会中断。但是,如果您采用Rails Casts的"角色"方法,这将帮助您完成最初的角色分配。