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后我的锁链,并存储它们的符号类的实例变量。

我很乐意听到关于如何改进它的建议。