我一直关注this中关于单独角色模型实施的CanCan指南。当User
尝试注册时,会在创建Assignment
时抛出此错误。
User(#21477600) expected, got Symbol(#5785720)
我正在使用带有以下User
函数的<{1}}生成的Devise
before_save
我想将用户的角色默认为“用户”,但我显然做错了什么。该如何实施?
答案 0 :(得分:9)
不确定您是否看过这个,但Ryan Bates制作了一份精彩的文件:
编辑:
这是我目前正在使用的内容。我相信你的'作业'与我的'UserRole'相同。
user.rb
#--
# Relationship
has_many :user_roles, :dependent => :destroy, :uniq => true
has_many :roles, :through => :user_roles, :uniq => true
#--
# Instance Method
# Determine if the user has a specified role
# You can find this method at: https://github.com/ryanb/cancan/wiki/Separate-Role-Model
# Written by Ryan Bates, I added the downcase though to detect 'Admin' vs 'admin'.
# Example:
# user.has_role? :Admin
# => true
def has_role?(role_sym)
roles.any? { |role| role.name.underscore.to_sym == role_sym.downcase }
end
role.rb
# id :integer(4) not null, primary key
# name :string(255)
#--
# Relationship
has_many :user_roles, :dependent => :destroy, :uniq => true
has_many :users, :through => :user_roles, :uniq => true
user_role.rb
# id :integer(4) not null, primary key
# user_id :integer(4)
# role_id :integer(4)
#--
# Relationship
belongs_to :user
belongs_to :role
然后在我的能力.rb
def initialize(user)
user ||= User.new # in case of a guest
if user.has_role? :Admin # The user is an Administrator
can :manage, :all
else
can :read, :all
end
end
然后我可以通过执行以下操作轻松分配角色,例如在我的种子文件中:
# Create Users
...
# Roles
admin = Role.create!(:name => "admin")
standard = Role.create!(:name => "standard")
# UserRoles :Admin
user1.roles << admin
user2.roles << standard
所以通过调用user.roles&lt;&lt; [role_name],我实际上是在创建一个UserRole,它有一个user_id和一个role_id。
答案 1 :(得分:3)
可能有一些更有效的方法可以实现这一目标,但我不知道没有确切的模型关联。
无论如何,我认为这应该有效:
def create_role
Assignment.new :user => self, :role => Role.find_by_role("user")
end
由于您指定:user而不是:user_id,您应该传递self。同样的事情:角色。如果您指定了:role_id,那么您应该在find_by_role之后输入.id但是因为您只指定:role然后删除.id
答案 2 :(得分:2)
看起来你正在将符号传递给期望对象的哈希条件。
DanneManne的回答应该有效。你也可以做
Assignment.new( :user_id=>self.id, :role_id => Role.find_by_role('user').id )
(但Danne's更好,imo)
最后一个建议 - 为什么不说角色的名字是“名字”,而不是“角色”。所以你要做的就是Role.find_by_name('user')。对于后来的程序员来说,这会更容易。
答案 3 :(得分:2)
首先,你不应该使用save回调,因为它将同时在create&amp;更新
其次,如果你在这样的模型之间建立关联:
class User < ActiveRecord::Base
has_one :profile
has_many :assignments
end
class Profile < ActiveRecord::Base
belongs_to :user
end
class Assignment < ActiveRecord::Base
belongs_to :user
belongs_to :role
end
您将拥有方便的方法,例如user.profile
,user.build_profile
和user.create_profile
。建设与发展创建将自动在个人资料上设置user_id
。您可以在回调中使用它们,而无需定义任何方法。
请注意,在保存用户之前,它没有ID。因此,您需要使用before_create :build_profile
after_create :create_profile
或user.assignments.build
。第一个将在内存中创建配置文件,在用户保存后将自动保存,第二个非常简单。
也会有类似的作业方法:user.assignments.create
class User < ActiveRecord::Base
has_one :profile
has_many :assignments
after_create :create_profile, :create_assignment
def create_assignment
assignments.create :role => Role.find_by_role("user")
end
end
。所以User的最终代码看起来像这样
{{1}}