hol*_*eap 3 ruby model ruby-on-rails polymorphic-associations ruby-on-rails-4
我有两个使用该people表的模型:Person和Person::Employee(继承自Person).该people表有一type列.
还有另一个模型,Group它具有多态关联,称为:owner.该groups表包含owner_id列和owner_type列.
应用程序/模型/ person.rb:
class Person < ActiveRecord::Base
has_one :group, as: :owner
end
Run Code Online (Sandbox Code Playgroud)
应用程序/模型/人/ employee.rb:
class Person::Employee < Person
end
Run Code Online (Sandbox Code Playgroud)
应用程序/模型/ group.rb:
class Group < ActiveRecord::Base
belongs_to :owner, polymorphic: true
belongs_to :supervisor
end
Run Code Online (Sandbox Code Playgroud)
问题是,当我使用以下代码创建Person :: Employee时,该owner_type列设置为不正确的值:
group = Group.create
=> #<Group id: 1, owner_id: nil, owner_type: nil ... >
group.update owner: Person::Employee.create
=> true
group
=> #<Group id: 1, owner_id: 1, owner_type: "Person" ... >
Run Code Online (Sandbox Code Playgroud)
owner_type应设置为"Person::Employee",但设置为"Person".
奇怪的是,这在调用时似乎没有引起任何问题Group#owner,但在创建如下所示的关联时确实会引起问题:
应用程序/模型/ supervisor.rb:
class Supervisor < ActiveRecord::Base
has_many :groups
has_many :employees, through: :groups, source: :owner,
source_type: 'Person::Employee'
end
Run Code Online (Sandbox Code Playgroud)
使用这种类型的关联,调用Supervisor#employees将不会产生任何结果,因为它正在查询WHERE "groups"."owner_type" = 'People::Employees'但owner_type设置为'People'.
为什么这个字段设置不正确以及可以做些什么呢?
编辑:
根据此,该owner_type字段没有得到正确设置,但它是按设计工作和字段设置为名称的基础 STI模式.
问题似乎是has_many:through关联搜索Group带有owner_type模型自己名称的s 而不是基础模型的名称.
设置has_many :employees, through: :group正确查询Person::Employee条目的关联的最佳方法是什么?
您正在使用Rails 4,因此您可以在关联上设置范围.你的Supervisor课可能看起来像:
class Supervisor < ActiveRecord::Base
has_many :groups
has_many :employees, lambda {
where(type: 'Person::Employee')
}, through: :groups, source: :owner, source_type: 'Person'
end
Run Code Online (Sandbox Code Playgroud)
然后,您可以要求主管的员工,例如supervisor.employees,生成如下查询:
SELECT "people".* FROM "people" INNER JOIN "groups" ON "people"."id" =
"groups"."owner_id" WHERE "people"."type" = 'Person::Employee' AND
"groups"."supervisor_id" = ? AND "groups"."owner_type" = 'Person'
[["supervisor_id", 1]]
Run Code Online (Sandbox Code Playgroud)
这使您可以使用标准关联助手(例如build),并且比编辑2稍微简单一些.