我需要在Rails(5.2)中为具有以下要求的树结构创建一个模型:
我决定使用以下数据库模型:
创建这些表的迁移看起来像这样:
class CreateItems < ActiveRecord::Migration[5.2]
def change
create_table :items, id: false, primary_key: :item_no do |t|
t.string :item_no, null: false
t.string :item_name
t.float :inventory
t.timestamps
end
add_index :items, :item_no, :unique => true
execute "ALTER TABLE items ADD PRIMARY KEY (item_no);"
end
end
class CreateTrees < ActiveRecord::Migration[5.2]
def change
create_table :trees, id: false, primary_key: %i[parent_item_no child_item_no] do |t|
t.string :parent_item_no
t.string :child_item_no
t.float :quantity
t.timestamps
end
execute "ALTER TABLE trees ADD PRIMARY KEY (parent_item_no, child_item_no);"
end
end
我的问题是设置Rails模型以使用关联反映此数据模型。
class Tree < ApplicationRecord
self.primary_keys = :parent_item_no, :child_item_no
belongs_to :item_no, class_name: 'Item', foreign_key: :parent_item_no
has_many :item_no, class_name: 'Item', foreign_key: :child_item_no
end
父关系还可以,但是has_many
显然无法正常工作,因为它期望Item表中有外键。
我需要一种访问树节点的子代的方法。
你会怎么做? 我感谢任何建议。
答案 0 :(得分:0)
我相信您会做类似的事情:
class Tree < ApplicationRecord
belongs_to :parent_item, class_name: 'Item', foreign_key: :parent_item_no
belongs_to :child_item, class_name: 'Item', foreign_key: :child_item_no
end
然后,您需要执行以下操作:
class Item < ApplicationRecord
has_many :children_trees, class_name: 'Tree', foreign_key: :parent_item_no
has_many :child_items, through: :children_trees
has_many :parent_trees, class_name: 'Tree', foreign_key: :child_item_no
has_many :parent_items, through: :parent_trees
end
由于未经测试,您可能需要对此付诸实践。
然后,您将可以执行以下操作:
@item.child_items
@item.parent_items
由于您规定Item
(您称其为“树叶”,但也可以称为“节点”)可以在多个树结构中重复使用,因此您需要做一些花哨的工作以确保您在特定树的上下文中检索父项和子项。但这是另一个问题。
我个人不知道这是关于什么的:
self.primary_keys = :parent_item_no, :child_item_no
如果您要确保在两个给定的Tree
之间只有一个Item
实例,那么我建议您validate uniqueness using a scope。
我不知道您为什么使用_no
而不是_id
。如果您有parent_item_id
和child_item_id
而不是parent_item_no
和child_item_no
,那么我认为您可以:
class Tree < ApplicationRecord
belongs_to :parent_item, class_name: 'Item'
belongs_to :child_item, class_name: 'Item'
end
但是,也许您有充分的理由违背惯例。
顺便说一句,Tree
似乎是班上一个奇怪的名字。 Tree
是层次结构中所有边缘和节点的集合。但是,您使用Tree
来表示结构的边缘。这对我来说似乎很奇怪。但是,嘿,这是个人喜好问题。因此,如果它使您的船漂浮起来,那就去吧!