Палец вверх 1
Перевод
Перевод

Связи ActiveRecord для таблицы соединений, связывающей две записи одной и той же таблицы?

У меня есть модель персонажа и модель связи. Модель Link представляет собой ссылку от персонажа к другому персонажу. Ссылка имеет текстовый атрибут «описание». Ссылка от символа A к символу B отличается от противоположной ссылки от B к A. Символ имеет ноль или одну ссылку на другой символ. Персонаж может иметь различные ссылки на разных персонажей. Персонаж может быть связан с различными персонажами.

Я использовал связи Active Record для частичной реализации отношений между символами и моделями ссылок:

class Character 
 has_many :links # the links from the character to other characters

class Link 
 belongs_to :character # the character from which starts the link to another character

которые дают мне полезные методы, такие как character.links (массив всех ссылок, начинающихся с этого символа) или link.character (символ, с которого начинается ссылка)

В модели ссылок также есть to_character_id который содержит идентификатор персонажа, который идет по ссылке. Таким образом, ссылка от символа A к символу B является экземпляром со следующими атрибутами:

  • character_id = идентификатор персонажа А
  • to_character_id = идентификатор символа B
  • description = некоторый текст

Я написал несколько дополнительных методов, таких как character.links_to (возвращающий массив всех ссылок, которые указывают на символ) или link.to_character (возвращающий символ, на который указывает ссылка), или character.characters_who_link_to (возвращающий массив другого символы, имеющие ссылку на этот символ). Я также написал обратный вызов, чтобы убедиться, что при удалении символа удаляются все ссылки на этот символ (то же самое для восстановления).

Можно ли использовать дополнительные объявления отношений AR, которые бы предоставили мне такие дополнительные методы, чтобы мне не приходилось самим писать эти методы и обратные вызовы?

Agile Web Development с Rails представляет решение в разделе «Использование моделей в качестве таблиц объединения», но для таблицы объединения, объединяющей две разные таблицы. В моем случае моя таблица соединений Ссылки объединяют записи одной таблицы, символов.

ruby-on-rails activerecord
задан Florent2 5 июн. 2009 г., 21:43:21
источник

3 ответа

Решение 3
Перевод
Перевод

has_and_belongs_to_many больше не используется; Я бы использовал has_many :through вместо этого.

class Character < ActiveRecord::Base
   has_many :links, :dependent => destroy
   has_many :characters, :through => :links 

   has_many :source_links, :class_name => "Link", 
     :foreign_key => "to_character_id", :dependent => :destroy
   has_many :source_characters, :class_name => "Character", 
     :through => :destination_links
 end

 class Link < ActiveRecord::Base
   belongs_to :character
   belongs_to :source_character, :class_name => "Character", 
    :foreign_key => "to_character_id"
 end

Обратите внимание на параметры :dependent => :destroy - они будут удалять ссылки при удалении персонажа. Называние правильное - с точки зрения source_links , source_links - это ссылки на этого персонажа. Итак, теперь вы можете сделать:

@character.characters # characters I link to
@character.links # links I have to other characters
@character.source_characters # characters that link to me
@character.source_links # links other characters have to me
ответ дан Sarah Mei 5 июн. 2009 г., 23:02:43
источник
Палец вверх 2
Перевод
Перевод

Я думаю, что вы хотите что-то вроде следующего:

 class Character < ActiveRecord::Base
   has_many :outbound_links, :class_name => "Link", :foreign_key => "from_character_id"
   has_many :inbound_links, :class_name => "Link", :foreign_key => "to_character_id"
 end

 class Link < ActiveRecord::Base
   belongs_to :from_character, :class_name => "Character", :foreign_key => "from_character_id"
   belongs_to :to_character, :class_name => "Character", :foreign_key => "to_character_id"
 end

Вы можете прочитать обо всех ваших опциях в ассоциациях ActiveRecord по адресу http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html.

ответ дан Matt Gillooly 5 июн. 2009 г., 22:25:41
источник
Палец вверх 0
Перевод
Перевод

Я думаю, что вы действительно собираетесь здесь самоотносительные отношения HABTM с использованием таблицы соединений

так что если у вас был стол для соединения

create_table :character_links do |t|
   t.integer :character_id
   t.integer :linked_character_id
   t.timestamps #if you want to know when the relationship was created
end

Тогда вы бы

class Characters < ActiveRecord::Base
   has_and_belongs_to_many :linked_characters, 
      :class_name => "Characters", 
      :join_table => :character_links, 
      :foreign_key => "character_id", 
      :associated_foreign_key => "linked_character_id"

если вам нужны исходящие ссылки и входящие ссылки, то вы можете просто сделать

class Characters < ActiveRecord::Base
   has_and_belongs_to_many :outgoing_links, 
      :class_name => "Characters", 
      :join_table => :character_links, 
      :foreign_key => "character_id", 
      :associated_foreign_key => "linked_character_id"

   has_and_belongs_to_many :incoming_links, 
      :class_name => "Characters", 
      :join_table => :character_links, 
      :foreign_key => "linked_character_id", 
      :associated_foreign_key => "character_id"

Просто переключил Foreign_key и related_foreign_key

Это исключает необходимость иметь отдельную модель ссылок.

Это воздушный код (не проверено)

ответ дан ErsatzRyan 5 июн. 2009 г., 22:46:20
источник