Rails самореферентный через has_many с пользовательским именованием таблицы соединений - PullRequest
5 голосов
/ 29 марта 2012

У меня возникли проблемы с нахождением головы в следующей ситуации ..

Я пытаюсь создать древовидную структуру, в которой я буду в состоянии давать собственные имена для соединений между узлами ..

Итак, я хочу иметь модели Node и Relation.Каждый

Node 
 has_many :relations

Каждый

Relation 
 has_many :nodes

Узел может быть либо родителем, либо ребенком. До сих пор все было легко, и существует множество примеров, показывающих, как сделать себяссылочная таблица has_many ... Проблема в том, что я хочу иметь возможность давать имена отношениям, чтобы я мог сделать что-то вроде:

relation1 = node1.relations.create(:name => "relation_name", :child => node2)

и в результате получить что-то вроде:

relation1.name == "relation_name"
relation1.parent == node1
relation1.child == node2

Все творения происходят внутри модели, это действие на самом деле не отображается пользователю, если это имеет значение.Спасибо!

EDIT2: Вот как это работает сейчас:

class Node < ActiveRecord::Base
  belongs_to :sentence

  has_one :parent_relation, :foreign_key => "child_id", :class_name => "Relation"
  has_many :child_relations, :foreign_key => "parent_id", :class_name => "Relation"

  has_one :parent, :through => :parent_relation
  has_many :children,  :through => :child_relations, :source => :child

  has_many :relations, :foreign_key => "child_id"
  has_many :relations, :foreign_key => "parent_id"

class Relation < ActiveRecord::Base

  has_many :videos, :as => :videoable, :dependent => :destroy
  has_many :phrases, :through => :videos

  belongs_to :parent, :class_name => "Node"#, :inverse_of => :parent_relation
  belongs_to :child, :class_name => "Node"#, :inverse_of => :child_relation

1 Ответ

5 голосов
/ 30 марта 2012

То, о чем вы говорите, больше похоже на Соединение модели , чем на самообращение.

Примечание: я изменил ваши relation ярлыки ассоциации, потому что мне было трудно с вашими именами, поэтому вам не нужно менять ваши ярлыки, которые были только для меня.

Так что для вашего Node класса вы могли бы сделать что-то вроде этого

class Node < ActiveRecord::Base
   has_one  :parent_relation, :foreign_key => "child_id",
                              :class_name => "Relation"
   has_many :child_relations, :foreign_key => "parent_id", 
                              :class_name => "Relation"

   has_one  :parent, :through => :parent_relation
   has_many :children, :through => :child_relations, :source => :child
end

Тогда для вашего Relation класса вы могли бы что-то вроде

class Relation < ActiveRecord::Base
  belongs_to :parent, :class_name => "Node", :inverse_of => :parent_relation
  belongs_to :child, :class_name => "Node", :inverse_of => :child_relations
end

Опция :inverse_of должна позволять вам строить, позволяя вам строить Node на основе parent и children ассоциаций из ваших Node экземпляров, это всего лишь предостережение от magic с :through отношениями. (Документация по этому вопросу находится внизу раздела Joins Model .)

Я не совсем понимаю вашу структуру ассоциации, но я думаю, что это должно правильно ее смоделировать. Позвольте мне знать, если есть какие-либо проблемы.

Side Note: Поскольку Relation является константой, установленной в модуле ActiveRecord, вы можете подумать о том, чтобы изменить его на что-то вроде NodeRelationship. Я не думаю, что это будет мешать вашей программе, но это определенно вызвало некоторые проблемы для моего мыслительного процесса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...