Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 充当具有多个模型的树_Ruby On Rails_Ruby On Rails Plugins_Acts As Tree - Fatal编程技术网

Ruby on rails 充当具有多个模型的树

Ruby on rails 充当具有多个模型的树,ruby-on-rails,ruby-on-rails-plugins,acts-as-tree,Ruby On Rails,Ruby On Rails Plugins,Acts As Tree,我有几个模型,我想把它们按层次联系起来。为了简单起见,假设我有三个: class Group < ActiveRecord::Base acts_as_tree has_many :users end class User < ActiveRecord::Base acts_as_tree belongs_to :group has_many :posts end class Post < ActiveRecord::Base acts_as_tre

我有几个模型,我想把它们按层次联系起来。为了简单起见,假设我有三个:

class Group < ActiveRecord::Base
  acts_as_tree
  has_many :users
end

class User < ActiveRecord::Base
  acts_as_tree
  belongs_to :group
  has_many :posts
end

class Post < ActiveRecord::Base
  acts_as_tree
  belongs_to :user
end
类组
在当前的acts_as_树下,每个节点可以单独与其他节点分层关联,前提是它们具有相同的类型。我想删除对类型标识的限制,这样SomePost.parent可以有一个用户或一个Post作为它的父项,SomeUser.parent可以有另一个用户或组作为它的父项


有什么想法吗?

我过去的做法是使用树中的多态容器,映射到特定的单个模型

class Container < ActiveRecord::Base
   acts_as_tree
   belongs_to :containable, :polymorphic => true 
end

class User
  has_one :container :as => :containable
end
类容器true 结束 类用户 has_one:container:as=>:containable 结束
我设法做了一些不同的事情,但这可能不适合您的情况。我正在重构现有代码,不想进行任何严肃的数据库迁移

我想要单独的叶类和节点类。两者都从树类继承

我在
vendor/plugins/acts\u as\u tree/lib/active\u record/acts/tree.rb中的ClassMethods中添加了两个函数:

    # Configuration options are:
    #
    # * <tt>foreign_key</tt> - specifies the column name to use for tracking of the tree (default: +parent_id+)
    # * <tt>order</tt> - makes it possible to sort the children according to this SQL snippet.
    # * <tt>counter_cache</tt> - keeps a count in a +children_count+ column if set to +true+ (default: +false+).
    # * <tt>leaf_class_name</tt> - leaf class subtype of base tree class
    # * <tt>node_class_name</tt> - node class subtype of base tree class
    def acts_as_tree_node(options = {})
      configuration = { :foreign_key => "parent_id", :order => nil, :counter_cache => nil, :node_class_name => 'Node', :leaf_class_name => 'Leaf' }
      configuration.update(options) if options.is_a?(Hash)

      belongs_to :parent, :class_name => configuration[:node_class_name], :foreign_key => configuration[:foreign_key], :counter_cache => configuration[:counter_cache]
      #has_many :children, :foreign_key => configuration[:foreign_key], :order => configuration[:order], :dependent => :destroy

      class_eval <<-EOV
        has_many :child_nodes, :class_name => '#{configuration[:node_class_name]}', :foreign_key => "#{configuration[:foreign_key]}", :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}}, :dependent => :destroy
        has_many :child_leaves, :class_name => '#{configuration[:leaf_class_name]}', :foreign_key => "#{configuration[:foreign_key]}", :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}}, :dependent => :destroy

        include ActiveRecord::Acts::Tree::InstanceMethods

        def self.roots
          find(:all, :conditions => "#{configuration[:foreign_key]} IS NULL", :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}})
        end

        def self.root
          find(:first, :conditions => "#{configuration[:foreign_key]} IS NULL", :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}})
        end
      EOV
    end

    # Configuration options are:
    #
    # * <tt>foreign_key</tt> - specifies the column name to use for tracking of the tree (default: +parent_id+)
    # * <tt>order</tt> - makes it possible to sort the children according to this SQL snippet.
    # * <tt>counter_cache</tt> - keeps a count in a +children_count+ column if set to +true+ (default: +false+).
    # * <tt>node_class_name</tt> - the class name of the node (subclass of the tree base)
    def acts_as_tree_leaf(options = {})
      configuration = { :foreign_key => "parent_id", :order => nil, :counter_cache => nil, :node_class_name => 'Node' }
      configuration.update(options) if options.is_a?(Hash)

      belongs_to :parent, :class_name => configuration[:node_class_name], :foreign_key => configuration[:foreign_key], :counter_cache => configuration[:counter_cache]

      class_eval <<-EOV
        include ActiveRecord::Acts::Tree::InstanceMethods

        def self.roots
          find(:all, :conditions => "#{configuration[:foreign_key]} IS NULL", :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}})
        end

        def self.root
          find(:first, :conditions => "#{configuration[:foreign_key]} IS NULL", :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}})
        end
      EOV
    end
这有点像黑客,但对我来说很有效,因为每个节点都有一种类型的子节点。您可以使用
children
函数来获得不同的行为,例如:

def children
  child_nodes | child_leaves
end
但它仍然需要一个额外的查询,您将丢失订单、范围和其他内容

最后,在我的Node类中,我有

acts_as_tree_node :node_class_name => 'NodeMatrix', :leaf_class_name => 'LeafMatrix'
在我的Leaf课程中,以下内容:

acts_as_tree_leaf :node_class_name => 'NodeMatrix'
这两个都继承自TreeMatrix,它是纯虚拟的(实际上没有任何东西被实例化为TreeMatrix,它只是一个基类)


同样,这是非常特定于应用程序的。但它让您了解了如何修改acts as树。

这是否意味着post和group也将有一个:container:as=>:containable?
acts_as_tree_leaf :node_class_name => 'NodeMatrix'