我正在尝试创建一个Web应用程序,用户可以在其中选择一个可以选择多个小部件的仪表板。我有以下多对多:
class CreateWidgets < ActiveRecord::Migration
def change
create_table :widgets do |t|
t.string :name
t.timestamps null: false
end
create_table :users_widgets, id: false do |t|
t.belongs_to :user, index: true
t.belongs_to :widget, index: true
end
end
end
使用设计宝石定义的用户模型。那么我怎样才能最有效地设置一些参数,这些参数允许我定义用户只能看到他们“订阅”的小部件的能力。
CanCan权限在此处定义:
class Ability
include CanCan::Ability
def initialize(user)
can :read, Widget, :user_id => user.id
end
end
显然,这不起作用,因为没有参数可以跟踪哪个用户创建了窗口小部件。那么如何设置Widget / User模型?可能会向用户模型添加权利列表?它可能是一大堆bool属性,每种类型的小部件都有一个,但显然,这可能会有点混乱,我应该如何以安全意识的方式解决这个问题?
我的模特现在读到:
class User < ActiveRecord::Base
has_many :subscriptions
has_many :widgets, through: :subscriptions
end
class Widget < ActiveRecord::Base
has_many :subscriptions
has_many :users, through: :subscriptions
end
class Subscription < ActiveRecord::Base
belongs_to :user
belongs_to :widget
# make sure you add a unique DB index as well.
validates_uniqueness_of :user_id, scope: :widget_id
end
和我的model/ability.rb
文件显示为:
class Ability
include CanCan::Ability
def initialize(user)
can :read, Widget do |widget|
widget.subscriptions.where(user: user).any?
end
end
end
但它仍然不起作用,我预计这是由于有关唯一数据库索引注释的说明,但我不确定要为此添加什么?
答案 0 :(得分:3)
首先需要在User和Widget之间创建many to many join model。
class User < ActiveRecord::Base
has_many :subscriptions
has_many :widgets, through: :subscriptions
end
class Widget < ActiveRecord::Base
has_many :subscriptions
has_many :users, through: :subscriptions
end
class Subscription < ActiveRecord::Base
belongs_to :user
belongs_to :widget
# make sure you add a unique DB index as well.
validates_uniqueness_of :user_id, scope: :widget_id
end
然后,您可以通过将块传递给can
:
can :read, Widget do |widget|
widget.subscriptions.where(user: user).any?
end