Especificación de la clave externa en una has_many: a través de la relación
-
21-09-2019 - |
Pregunta
Tengo los tres modelos siguientes: El usuario, proyecto y asignación
. Un Proyectos has_many
usuario a través de una asignación. Sin embargo, en realidad Asignación tiene dos claves externas que se relacionan a un usuario:. user_id
(que representan el usuario que le fue asignado el proyecto) y completer_id
(que representan al usuario que complete el proyecto)
A menudo, user_id
y completer_id
serán los mismos (si el usuario que le fue asignado el proyecto lo completa). Sin embargo, si otro usuario lo completa, user_id y completer_id serán diferentes.
En mi modelo de usuario, tengo el siguiente:
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
Me gustaría hacer otra asociación, llamada :completed_projects
, que utiliza completer_id
como la clave externa para el usuario en el modelo :through
, en lugar de :user_id
. ¿Es posible hacer esto?
Y, como un aparte, soy consciente de la opción :foreign_key
. Sin embargo, esta opción se ignora cuando se utiliza :through
, así que me gustaría saber si hay una manera de hacer esto sin él.
Por último, debo mencionar que estoy abierto a otros diseños, si no se puede hacer de esta manera y que alguien puede pensar en una mejor manera.
Solución
Siempre se puede utilizar SQL para la selección si ActiveRecord no puede expresar fácilmente la relación de la caja:
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}'
Otros consejos
¿Tiene otros metadatos en su tabla de asignaciones?
Si no me acaba de utilizar HABTM y añadir la completer_id a la mesa de proyectos en cambio, tiene sentido para vivir allí de todos modos.
Si necesita / desea utilizar has_many: a través de usted podría buscar en el uso named_scopes (rieles versión permite) por lo que se podría decir user.projects.completed
y user.projects.incomplete