为什么关联是不适合STI工作,如果多态关联的类型列没有指向性传播疾病的基本模型?不适合、模型、性传播、疾病

2023-09-09 22:04:26 作者:歌淺婼離

我多态关联和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_classof 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