Especificando a chave estrangeira em um has_many: através do relacionamento
-
21-09-2019 - |
Pergunta
Eu tenho os três modelos a seguir: usuário, projeto e atribuição.
Um usuário has_many
Projetos através de uma tarefa. No entanto, a tarefa realmente tem dois Chaves estrangeiras relacionadas a um usuário: user_id
(representando o usuário que foi atribuído ao projeto) e completer_id
(representando o usuário que concluiu o projeto).
Muitas vezes, user_id
e completer_id
será o mesmo (se o usuário que recebeu o projeto o concluir). No entanto, se outro usuário o concluir, user_id e Completer_id serão diferentes.
No meu modelo de usuário, tenho o seguinte:
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
Eu gostaria de fazer outra associação, chamada :completed_projects
, que usa completer_id
como a chave estrangeira para o usuário no :through
modelo, em vez de :user_id
. É possível fazer isso?
E, como um aparte, estou ciente do :foreign_key
opção. No entanto, esta opção é ignorada ao usar :through
, então eu gostaria de saber se há uma maneira de fazer isso sem ele.
Por fim, devo mencionar que estou aberto a outros designs, se não puder ser feito dessa maneira e alguém pode pensar em uma maneira melhor.
Solução
Você sempre pode usar o SQL para a seleção se o ActiveRecord não puder expressar facilmente o relacionamento fora da caixa:
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}'
Outras dicas
Você tem outros meta -dados em sua tabela de atribuições?
Caso contrário, eu usaria o HABTM e adicionaria o Completer_id à tabela de projetos, faz sentido morar lá de qualquer maneira.
Se você precisar/quiser usar Has_Many: através, você pode olhar usando o nome do nome (versão do Rails da Rails) para que você possa dizer user.projects.completed
e user.projects.incomplete