Я полагаю, вы бы сделали что-то вроде:
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
с, то я бы предложил вам проверить уникальность, используя область действия .
Я не знаю, почему вы используете _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
, чтобы обозначить преимущество в вашей структуре. Это кажется мне своеобразным. Но, эй, это вопрос личных предпочтений. Так что, если она плывет на вашей лодке, дерзайте!