创建具有树结构的模型

我有树结构的类别。 我试图通过为每个人定义父母来将他们联系在一起。 (我无法弄清楚如何调用属性parent所以它现在只是category ,但它意味着父级)。

 class Category < ActiveRecord::Base has_one :category # the parent category end 

但这种关系最终走错了路。

getter函数在子类别上(正确),但category_id存储在父类中:

 parent = Category.create(:name => "parent") child = Category.create(:name => "child", :category => parent) parent.id # 1 child.id # 2 child.category_id # nil parent.category_id # 2 child.category.name # "parent" (!!) 

父母需要能够有多个孩子,所以这不会起作用。

您正在寻找的是自我加入。 请查看Rails指南的这一部分: http : //guides.rubyonrails.org/association_basics.html#self-joins

 class Category < ActiveRecord::Base  has_many :children, class_name: "Category", foreign_key: "parent_id"  belongs_to :parent, class_name: "Category" end 

每个类别都belong_to父级,甚至是您的父类别。 您可以创建最高级别类别所属的单个类别父级,然后您可以忽略应用程序中的该信息。

您可以使用acts_as_tree gem来实现此目的,查找下面的示例和链接。

https://github.com/amerine/acts_as_tree/tree/master

 class Category < ActiveRecord::Base include ActsAsTree acts_as_tree order: "name" end root = Category.create("name" => "root") child1 = root.children.create("name" => "child1") subchild1 = child1.children.create("name" => "subchild1") root.parent # => nil child1.parent # => root root.children # => [child1] root.children.first.children.first # => subchild1 

类别应该有许多类别,每个类别的外键应该是parent_id 。 因此,当您执行parent.children它会列出所有具有parent_id=parent.id的类别。

你读过单表inheritance吗?

你应该看一下祖先的gem: https : //github.com/stefankroes/ancestry

它提供了您需要的所有function,并且能够通过使用物化路径的变体通过单个SQL查询获取所有后代,兄弟姐妹,父母等,因此它将具有比上面的自联接和acts_as_tree答案更好的性能。

全文 – https://blog.francium.tech/best-practices-for-handling-hierarchical-data-structure-in-ruby-on-rails-b5830c5ea64d

一个简单的表

 Table Emp id: Integer name: String parent_id: Integer 

协会

 app/models/emp.rb class Emp < ApplicationRecord has_many :subs, class_name: 'Emp', foreign_key: :parent_id belongs_to :superior, class_name: 'Emp', foreign_key: :parent_id end 

范围定义

 class Emp < ApplicationRecord ---- ---- scope :roots, -> { where(parent_id: nil) } end 

获取数据

 def tree_data output = [] Emp.roots.each do |emp| output << data(emp) end output.to_json end def data(employee) subordinates = [] unless employee.subs.blank? employee.subs.each do |emp| subordinates << data(emp) end end {name: employee.name, subordinates: subordinates} end 

渴望加载

 def tree_data output = [] Emp.roots.includes(subs: {subs: {subs: subs}}}.each do |emp| output << data(emp) end output.to_json end