Кажется, существует несколько способов обработки множественной ассоциации внешних ключей. Каждый путь, к которому я подошел, имеет свои обратные спины, и, поскольку я новичок в Rails, я убежден, что другие сталкиваются с похожим сценарием, и я, вероятно, работаю над чем-то, давно решенным.Rails - Ассоциация с несколькими индексами
Мой вопрос:
Что бы быть эффективным способом обработки множественного индекса ключа связи, сохраняя при этом все остальные Rails SQL модификаторы (например: включить и т.д.)?
Мой сценарий:
У меня есть таблица ассоциации следующим образом (упрощенный), который используется для подключения людей к другим людям с помощью ссылки:
People
+----+-----------+
| id | name |
+----+-----------+
| 1 | Joe |
+----+-----------+
| 2 | Sally |
+----+-----------+
| 3 | Bob |
+----+-----------+
Links
+----+-----------+---------+
| id | origin_id | rcvd_id |
+----+-----------+---------+
| 1 | 2 | 1 |
+----+-----------+---------+
| 2 | 1 | 3 |
+----+-----------+---------+
| 3 | 3 | 2 |
+----+-----------+---------+
Из строки 1 из вышеуказанных ссылок таблицу, можно видеть, что Лицо (Sally = 2) связано с другим Лицом (Joe = 1).
Мне легко найти все ссылки на Лица, если мой внешний ключ был «origin_id». Но это означало бы только «Люди, получающие связь». В моем сценарии мне нужно видеть все ссылки независимо от того, были ли они созданы или получены Лицом. Если, например, я должен был попросить все ссылки Салли (Sally = 2), то результат я хотел бы:
Links
+----+-----------+---------+
| id | origin_id | rcvd_id |
+----+-----------+---------+
| 1 | 2 | 1 |
+----+-----------+---------+
| 3 | 3 | 2 |
+----+-----------+---------+
Поэтому у меня есть 2 ключа индекса, как «origin_id» и «rcvd_id».
Один из способов это может быть решена с помощью является метод:
class Person < ActiveRecord::Base
has_many :link_origins, :class_name => "Link", :foreign_key => :origin_id, :dependent => :destroy
has_many :link_rcvds, :class_name => "Link", :foreign_key => :rcvd_id, :dependent => :destroy
def links
origin_person + rcvd_person
end
Однако, это не эффективно. Например, для этого требуется сбор всей коллекции из базы данных, и только тогда работает метод paginate (я использую жемчужину will_paginate), которая побеждает точку, поскольку paginate ускоряет процесс, ограничивая количество названных записей. Не ограничивайте записи после завершения всей коллекции.
Кроме того, вышесказанное не позволит мне позвонить, например, Joe.links (: first) .origin_id.name. Не совсем этот код, но это означает, что я не мог вызывать данные Person о origin_id выбранной ссылки, поскольку метод ссылок не знает, что origin_id связан с таблицей People.
Пока что наиболее работоспособным решением является: finder_sql.
class Person < ActiveRecord::Base
has_many :links, :finder_sql => 'SELECT * FROM links WHERE (links.origin_id = #{id} or links.rcvd_id = #{id})'
Это дает все ссылки, где person_id матчей либо Links.origin_id или Links.rcvd_id.
Недостатком этой опции является то, что использование: finder_sql исключает все другие модификаторы sql, поскольку Rails не знает, как анализировать и модифицировать SQL, который вы предоставляете. Например, я не смог бы использовать параметр include: with: finder_sql.
Итак, прямо сейчас я использую: finder_sql, solution. Но, похоже, может быть, что эта ассоциация не может быть выполнена таким образом, что мне не нужен: finder_sql. Например, существует ли способ написать пользовательскую строку sql, сохраняя при этом модификаторы sql Rails, которые снабжают Active Record.
Любые идеи по вышесказанному?
Спасибо Lelon. Я еще не прыгнул Rails3 (я знаю, смущаю), но в ближайшее время посмотрю на это. – Oscar