0

我工作的發動機自動創建關聯,其中任何模型都可以有允許的has_many協會的允許:通過許多現有關聯

class Permit < ActiveRecord::Base 
    belongs_to :permissible, polymorphic: true 
end 

module Permissible 
    def self.included(base) 
    base.class_eval do 
    has_many :permits, as: :permissible 
    end 
end 

class Group < ActiveRecord::Base 
    include Permissible 
end 

class GroupAllocation < ActiveRecord::Base 
    belongs_to :person 
    belongs_to :group 
end 

class Person < ActiveRecord::Base 
    include Permissible 
    has_many :group_allocations 
    has_many :groups, through: :group_allocations 
end 

class User < ActiveRecord::Base 
    belongs_to :person 
end 

因此,集團的has_many:許可證和人的has_many:許可證。我想要做的是在用戶上動態創建關聯,使用許可證關聯作爲源,並通過相同的方式將其他模型上的關聯關聯到用戶。這可以手動完成(在軌3.1+)有:

class Person 
    has_many :group_permits, through: :person, source: :permits 
end 

class User 
    has_many :person_permits, through: :person, source: :permits, class_name: Permit 
    has_many :person_group_permits, through: :person, source: :group_permits, class_name: Permit 
end 

然而,在實踐中,允許將包括在許多車型,所以我想寫上的用戶(在另一個模塊實際上是一個類的方法,但不需要混淆更多的東西),它可以遍歷User.reflect_on_all_associations並創建一個新的關聯數組,這可能是每個關聯都很深的關聯。

尋找關於如何在rails 3.2.8中乾淨利落的輸入。

回答

0

這裏是我是如何做到的(實現代碼問題中已給出的細節略有不同):

模塊Authorisable 高清self.included(基地) base.class_eval做 base.extend ClassMethods 結束 結束

module ClassMethods 
    class PermissionAssociationBuilder 
    def build_permissions_associations(klass) 
     chains = build_chains_from(klass) 
     chains.select! {|c| c.last.klass.included_modules.include? DistributedAuthorisation::Permissible} 
     permissions_associations = [] 
     chains.each do |chain| 
     source_name = :permissions 
     chain.reverse.each do |r| 
      assoc_name = :"#{r.name}_#{source_name}" 
      r.active_record.has_many assoc_name, through: r.name.to_sym, source: source_name, class_name: DistributedAuthorisation::Permission 
      source_name = assoc_name 
     end 
     permissions_associations << source_name 
     end 
     return permissions_associations 
    end 

    private 

    def build_chains_from(klass) 
     chains = reflections_to_follow(klass).map {|r| [r]} 
     chains.each do |chain| 
     models = chain.map {|r| r.klass}.unshift klass 
     reflections_to_follow(models.last).each do |r| 
      chains << (chain.clone << r) unless models.include? r.klass 
     end 
     end 
    end 

    def reflections_to_follow(klass) 
     refs = klass.reflect_on_all_associations 
     refs.reject {|r| r.options[:polymorphic] or r.is_a? ActiveRecord::Reflection::ThroughReflection} 
    end 
    end 

    def permissions_associations 
    @permissions_associations ||= PermissionAssociationBuilder.new.build_permissions_associations(self) 
    end 
end 

可能不是最有效的方法,但它增加了與Klass.permissions_associations後我的鎖鏈,並存儲它們的符號類的實例變量。

我很樂意聽到關於如何改進它的建議。