CanCan 独立角色模型

发布于 2024-11-15 13:20:15 字数 661 浏览 4 评论 0原文

我一直在遵循有关独立角色模型实现的指南< a href="https://github.com/ryanb/cancan" rel="nofollow">CanCan。当用户尝试注册时,在创建分配时会引发此错误。

User(#21477600) 预期,得到 Symbol(#5785720)

以下 before_save 函数

class User < ActiveRecord::Base
.
.
.
 def create_profile
    profile = Profile.new :user_id => :id
  end

  def create_role
     Assignment.new :user => :id, :role => Role.find_by_role("user").id
  end
end

我正在使用 Devise 生成的 User 以及我想要的 默认用户的角色为“user”,但我显然做错了什么。这应该如何实施?

I've been following this guide on the Separate Role Model implementation in CanCan. When a User, tries to sign up this error is thrown when creating the Assignment.

User(#21477600) expected, got Symbol(#5785720)

I'm using a Devise generated User with the following before_save functions

class User < ActiveRecord::Base
.
.
.
 def create_profile
    profile = Profile.new :user_id => :id
  end

  def create_role
     Assignment.new :user => :id, :role => Role.find_by_role("user").id
  end
end

I want to default the user's role to "user", but I'm obviously doing something wrong. How should this be implemented?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

蘸点软妹酱 2024-11-22 13:20:15

不确定您是否看过这个,但 Ryan Bates 制作了一份精彩的文档,内容涉及:

单独的角色模型编辑

这是我目前正在使用的。我相信您的“分配”与我的“用户角色”相同。

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

: [role_name],我本质上是创建一个 UserRole,它有一个 user_id 和一个 role_id。

Not sure if you've seen this or not, but Ryan Bates has produced a wonderful document regarding:

Separate Role Models

EDIT:

Here's what I am currently using. I believe your 'Assignment' is the same as my '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

Then in my ability.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

Then I can easily assign roles, like in my seed file by doing something like:

# Create Users
...

# Roles
admin = Role.create!(:name => "admin")
standard = Role.create!(:name => "standard")

# UserRoles :Admin
user1.roles << admin
user2.roles << standard

So by calling user.roles << [role_name], I am essentially creating a UserRole, which has a user_id and a role_id.

可可 2024-11-22 13:20:15

可能有一些更有效的方法来实现这一点,但如果没有确切的模型关联,我无法判断。

无论如何,我认为这应该有效:

def create_role
  Assignment.new :user => self, :role => Role.find_by_role("user")
end

由于您指定 :user 而不是 :user_id,因此您应该传递 self. :role 也是如此。如果您指定了 :role_id 那么您应该在 find_by_role 之后输入 .id,但由于您只指定 :role 然后删除 .id

There might be some more effective ways to accomplish this, but I cant tell without the exact model associations.

Anyway, I think this should work:

def create_role
  Assignment.new :user => self, :role => Role.find_by_role("user")
end

Since you specify :user and not :user_id, you should pass self. The same thing for :role. If you had specified :role_id then you should have entered .id after find_by_role but since you only specify :role then remove .id

苹果你个爱泡泡 2024-11-22 13:20:15

看起来您正在将符号传递给需要对象的哈希条件。

丹尼曼的回答应该有效。你也可以这样做

Assignment.new( :user_id=>self.id, :role_id => Role.find_by_role('user').id )

(但在我看来,丹尼的更好)

最后一个建议——为什么不说角色的名字是“名字”,而不是“角色”。那么你就会这样做,Role.find_by_name('user')。这对于后来的程序员来说会更容易遵循。

It looks like you're passing symbols to hash conditions that are expecting objects.

DanneManne's answer should work. You could alternatively do

Assignment.new( :user_id=>self.id, :role_id => Role.find_by_role('user').id )

(but Danne's is better, imo)

One last suggestion -- why not say the name of the role is "name", not "role". So then you'd be doing, Role.find_by_name('user'). That would be easier for a subsequent programmer to follow.

櫻之舞 2024-11-22 13:20:15

首先,您不应该使用保存回调,因为它会在创建和创建时触发。更新。

其次,如果您在模型之间建立这样的关联:

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.profileuser.build_profileuser.create_profile 等方便的方法。构建& create 将自动在个人资料上设置user_id。您可以在回调中使用它们,而无需定义任何方法。

请注意,在保存用户之前,它没有 id。因此,您需要使用 before_create :build_profileafter_create :create_profile。第一个将在内存中创建配置文件,该配置文件将在用户保存后自动保存,第二个非常简单。

也有类似的分配方法:user.assignments.build user.assignments.create。所以 User 的最终代码看起来像这样

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

Firstly, you should not use save callback because it will be fired on both create & update.

Secondly, if you set up associations between models like that:

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

You will have convenient methods like user.profile, user.build_profile and user.create_profile. Build & create will set up user_id on profile automatically. You can use them in your callbacks without having to define any methods.

Note that before user is saved it does not have an id. So you need to use either before_create :build_profile either after_create :create_profile. The first one will create profile in memory that will be autosaved after user is saved, the second one is pretty straightforward.

There will be similar methods for assignments too: user.assignments.build user.assignments.create. So the final code for User will look something like this

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文