【发布时间】:2012-06-20 11:21:05
【问题描述】:
在使用 STI 时,从与 rails 3 的 has_many 关联中获取集合时,我遇到了一些奇怪的行为。我有:
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})
}
但如果可能的话,我真的很想避免这种情况。任何人,有什么想法吗?
编辑:
finder_sql 和 counter_sql 并没有真正为我解决这个问题,因为似乎父关联不使用它,所以 organisation.employees has_many :employees, through: :branches 将再次只在选择中包含 User::Employee 类。
【问题讨论】:
标签: sql ruby-on-rails activerecord sti