STIを使用しているときにrails3との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
そして2回目:
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