Obtengo un comportamiento extraño al recuperar colecciones de una asociación has_many con rails 3 cuando uso STI. Tengo:Rails Asociación de STI con las subclases
class Branch < ActiveRecord::Base
has_many :employees, class_name: 'User::Employee'
has_many :admins, class_name: 'User::BranchAdmin'
end
class User < ActiveRecord::Base
end
class User::Employee < User
belongs_to :branch
end
class User::BranchAdmin < User::Employee
end
El comportamiento deseado es que branch.employees
devuelve todos los empleados incluyendo los administradores de sucursales. Los administradores de las sucursales sólo parecen ser 'cargado' en virtud de esta colección cuando hayan sido visitada por branch.admins
, esta es la salida de la consola:
Branch.first.employees.count
=> 2
Branch.first.admins.count
=> 1
Branch.first.employees.count
=> 3
Esto se puede ver en el SQL generado, la primera vez:
SELECT COUNT(*) FROM "users" WHERE "users"."type" IN ('User::Employee') AND "users"."branch_id" = 1
y la segunda vez:
SELECT COUNT(*) FROM "users" WHERE "users"."type" IN ('User::Employee', 'User::BranchAdmin') AND "users"."branch_id" = 1
pude resolver este problema simplemente especificando:
class Branch < ActiveRecord::Base
has_many :employees, class_name: 'User'
has_many :admins, class_name: 'User::BranchAdmin'
end
ya que todos ellos se encuentran de su branch_id pero esto crea problemas en el controlador si quiero hacer branch.employees.build
entonces la clase será por defecto User
y tengo que cortar en la columna de tipo en alguna parte. Tengo todo esto por ahora con:
has_many :employees, class_name: 'User::Employee',
finder_sql: Proc.new{
%Q(SELECT users.* FROM users WHERE users.type IN ('User::Employee','User::BranchAdmin') AND users.branch_id = #{id})
},
counter_sql: Proc.new{
%Q(SELECT COUNT(*) FROM "users" WHERE "users"."type" IN ('User::Employee', 'User::BranchAdmin') AND "users"."branch_id" = #{id})
}
pero me gustaría evitar esto si es posible. Alguien, alguna idea?
EDIT:
El finder_sql y counter_sql no han resuelto realmente por mí porque parece que las asociaciones de padres no usan esto y por lo que organisation.employees
has_many :employees, through: :branches
volverán a incluir sólo la clase User::Employee
en la selección.
Esta es una gran captura, gracias. La estructura del modelo realmente se modificó de todos modos, así que el problema desapareció, ¡pero no creo que siquiera lo haya considerado como un efecto del medio ambiente! –