Указание внешнего ключа в связи has_many :through
-
21-09-2019 - |
Вопрос
У меня есть следующие три модели:Пользователь, Проект и Назначение.
Пользователь has_many
Проекты с помощью задания.Однако Назначение на самом деле имеет два внешние ключи, относящиеся к Пользователю: user_id
(представляющий пользователя, которому был назначен проект) и completer_id
(представляющий пользователя, завершившего проект).
Часто, user_id
и completer_id
будет таким же (если пользователь, которому был назначен проект, завершит его).Однако, если его завершит другой пользователь, user_id и completer_id будут разными.
В моей пользовательской модели у меня есть следующее:
class User < ActiveRecord::Base
has_many :assignments
has_many :incomplete_assignments, :class_name => 'Assignment',
:conditions => 'completer_id IS NULL'
has_many :completed_assignments, :class_name => 'Assignment',
:foreign_key => 'completer_id'
# this is the important one
has_many :incomplete_projects,
:through => :assignments,
:source => :project,
:conditions => 'completer_id IS NULL'
end
Я хотел бы создать еще одну ассоциацию, называемую :completed_projects
, который использует completer_id
в качестве внешнего ключа для пользователя в :through
модель, а не :user_id
.Возможно ли это сделать?
И, в качестве отступления, я осведомлен о :foreign_key
вариант.Однако этот параметр игнорируется при использовании :through
, поэтому я хотел бы знать, есть ли способ сделать это без этого.
Наконец, я должен упомянуть, что я открыт для других проектов, если это невозможно сделать таким образом и кто-то может придумать способ получше.
Решение
Вы всегда можете использовать SQL для выбора, если ActiveRecord не может легко выразить связь из коробки:
has_many :completed_projects,
:class_name => "Project",
:finder_sql => 'SELECT p.* FROM projects p ' +
'INNER JOIN assignments a ON p.id=a.project_id ' +
'INNER JOIN users u on u.id=a.completer_id ' +
'WHERE u.id=#{id}'
Другие советы
Есть ли у вас другие метаданные в вашей таблице заданий?
Если нет, я бы просто использовал habtm и вместо этого добавил completer_id в таблицу projects, в любом случае имеет смысл жить там.
Если вам нужно / хотите использовать has_many :through, вы могли бы посмотреть на использование named_scopes (если позволяет версия Rails), чтобы вы могли сказать user.projects.completed
и user.projects.incomplete