我多态关联和STI在这里的情况。
I have a case of polymorphic association and STI here.
# app/models/car.rb
class Car < ActiveRecord::Base
belongs_to :borrowable, :polymorphic => true
end
# app/models/staff.rb
class Staff < ActiveRecord::Base
has_one :car, :as => :borrowable, :dependent => :destroy
end
# app/models/guard.rb
class Guard < Staff
end
为了对多态ASSOCATION工作,根据在多态ASSOCATION,http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#label-Polymorphic+Associations我必须设置 borrowable_type
到 BASE_CLASS
STI车型,这是在我的情况是员工
。
In order for the polymorphic assocation to work, according to the API documentation on Polymorphic Assocation, http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#label-Polymorphic+Associations that I have to set borrowable_type
to the base_class
of STI models, that is in my case is Staff
.
现在的问题是:为什么它不工作,如果 borrowable_type
设置为STI类
The question is: Why doesn't it work if the borrowable_type
set to STI class?
一些测试来证明这一点:
Some test to prove it:
# now the test speaks only truth
# test/fixtures/cars.yml
one:
name: Enzo
borrowable: staff (Staff)
two:
name: Mustang
borrowable: guard (Guard)
# test/fixtures/staffs.yml
staff:
name: Jullia Gillard
guard:
name: Joni Bravo
type: Guard
# test/units/car_test.rb
require 'test_helper'
class CarTest < ActiveSupport::TestCase
setup do
@staff = staffs(:staff)
@guard = staffs(:guard)
end
test "should be destroyed if an associated staff is destroyed" do
assert_difference('Car.count', -1) do
@staff.destroy
end
end
test "should be destroyed if an associated guard is destroyed" do
assert_difference('Car.count', -1) do
@guard.destroy
end
end
end
但似乎只与员工实例是真实的。结果是:
But it seems to be true only with Staff instance. The results are:
# Running tests:
F.
Finished tests in 0.146657s, 13.6373 tests/s, 13.6373 assertions/s.
1) Failure:
test_should_be_destroyed_if_an_associated_guard_is_destroyed(CarTest) [/private/tmp/guineapig/test/unit/car_test.rb:16]:
"Car.count" didn't change by -1.
<1> expected but was
<2>.
感谢
好问题。我有完全用Rails 3.1同样的问题。看起来,你不能这样做,因为这是行不通的。也许这是一个预期的行为。显然,使用单表继承(STI)在Rails中结合多态关联是有点复杂。
Good question. I had exactly the same problem using Rails 3.1. Looks like you can not do this, because it does not work. Probably it is an intended behavior. Apparently, using polymorphic associations in combination with Single Table Inheritance (STI) in Rails is a bit complicated.
目前Rails文档Rails的3.2给出了这样的建议,用于组合polymorphic协会和STI :
The current Rails documentation for Rails 3.2 gives this advice for combining polymorphic associations and STI:
在单台组合使用多态关联 继承(STI)是有点棘手。为了使协会 达到预期效果,请确保您的存储基础模型的STI 模型中的多态关联的类型列。
Using polymorphic associations in combination with single table inheritance (STI) is a little tricky. In order for the associations to work as expected, ensure that you store the base model for the STI models in the type column of the polymorphic association.
在你的情况基本型号将是工作人员,即borrowable_type应为工作人员的所有项目,而不是保护。这有可能使派生类使用显示为基类变成: guard.becomes(职员)
。人们可以设置列borrowable_type直接向基类员工,或Rails的文档建议,将其转换自动使用
In your case the base model would be "Staff", i.e. "borrowable_type" should be "Staff" for all items, not "Guard". It is possible to make the derived class appear as the base class by using "becomes" : guard.becomes(Staff)
. One could set the column "borrowable_type" directly to the base class "Staff", or as the Rails Documentation suggests, convert it automatically using
class Car < ActiveRecord::Base
..
def borrowable_type=(sType)
super(sType.to_s.classify.constantize.base_class.to_s)
end