创建具有树结构的模型
我有树结构的类别。 我试图通过为每个人定义父母来将他们联系在一起。 (我无法弄清楚如何调用属性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答案更好的性能。
一个简单的表
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