Я получаю странное поведение при наборе коллекций из ассоциации has_many с рельсами 3 при использовании STI. У меня есть:Rails STI-ассоциация с подклассами
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
Желаемое поведение является то, что branch.employees
возвращает все сотрудники, включая администраторов филиалов. Админы ветви только кажется, быть «загружен» под этой коллекции, когда они были прочитаны в branch.admins
, это выход из консоли:
Branch.first.employees.count
=> 2
Branch.first.admins.count
=> 1
Branch.first.employees.count
=> 3
Это можно увидеть в созданном SQL, в первый раз:
SELECT COUNT(*) FROM "users" WHERE "users"."type" IN ('User::Employee') AND "users"."branch_id" = 1
и второй раз:
SELECT COUNT(*) FROM "users" WHERE "users"."type" IN ('User::Employee', 'User::BranchAdmin') AND "users"."branch_id" = 1
я мог бы решить эту проблему, просто указав:
class Branch < ActiveRecord::Base
has_many :employees, class_name: 'User'
has_many :admins, class_name: 'User::BranchAdmin'
end
, так как все они находятся в их branch_id, но это создает проблемы в контроллере, если я хочу сделать branch.employees.build
то класс будет по умолчанию User
и я должен взломать на колонке типа где-то. Я обошел это сейчас:
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})
}
, но я бы очень хотел избежать этого, если это возможно. Кто-нибудь, какие-нибудь идеи?
EDIT:
finder_sql и counter_sql не реально решить это для меня, потому что кажется, что родительские ассоциации не использовать это и так organisation.employees
, что has_many :employees, through: :branches
снова включать только User::Employee
класс в выборе.
Это замечательный улов, спасибо. В любом случае структура модели была фактически изменена, поэтому проблема исчезла, но я не думаю, что даже считал бы ее результатом воздействия окружающей среды! –