2016-02-29 33 views
0

我正在尝试创建一个Web应用程序,其中用户有一个仪表板,可以在其中选择多个小部件。我有以下多对多:如何通过CanCan管理Rails中的复杂用户功能

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 

用devise gem定义的用户模型。那么我怎样才能最有效地设置一些参数,让我能够定义用户只能看到他们“订阅”的小部件的能力。

惨惨的权限定义如下:

class Ability 
    include CanCan::Ability 

    def initialize(user) 
    can :read, Widget, :user_id => user.id 
    end 
end 

显然,这是不行的,因为没有参数,跟踪哪些用户创建的小部件。那么,我将如何设置Widget /用户模型?可能将权利列表添加到用户模型?它可能是bool属性的全部负载,每种类型的widget都有一个属性,但显然这可能会有点混乱,我应该如何以安全意识的方式解决这个问题?

更新:

我的型号现在阅读:

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 

但它仍然无法正常工作,我希望这是由于请注意独特的数据库索引说明,但我不确定要为此添加什么内容?

回答

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 
+0

谢谢!你是什​​么意思一个独特的数据库索引? –

+0

我发布了我的迁移文件,据推测我向他们添加了一些东西? –

+0

唯一的数据库索引只是确保您的“订阅”表中没有重复项。你可以用'add_index(:subscriptions,[:user_id,:widget_id],unique:true)'添加一个。 https://robots.thoughtbot.com/the-perils-of-uniqueness-validations – max