我有树结构的类别。我试图通过为每个人定义父母来将他们联系在一起。 (我无法弄清楚如何调用属性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" (!!)
父母需要有多个孩子,所以这不会起作用。
答案 0 :(得分:34)
您正在寻找的是自我加入。请查看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
为父级,甚至是您的父类别。您可以创建最高级别类别所属的单个类别父级,然后您可以忽略应用程序中的该信息。
答案 1 :(得分:3)
您可以使用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
答案 2 :(得分:3)
你应该看一下祖先的宝石:https://github.com/stefankroes/ancestry
它提供了您需要的所有功能,并且能够通过使用物化路径的变体通过单个SQL查询获取所有后代,兄弟,父母等,因此它将具有比自联接和acts_as_tree答案更好的性能以上。
答案 3 :(得分:2)
类别应该有很多类别,每个类别的外键应该是parent_id
。因此,当您执行parent.children
时,它会列出所有具有parent_id=parent.id
。
您是否阅读过单表继承?
答案 4 :(得分:0)
简单表
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