如果多态关联的类型列不指向 STI 的基本模型,为什么多态关联对 STI 不起作用? [英] Why polymorphic association doesn't work for STI if type column of the polymorphic association doesn't point to the base model of STI?

查看:14
本文介绍了如果多态关联的类型列不指向 STI 的基本模型,为什么多态关联对 STI 不起作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我这里有一个多态关联和 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

为了使多态关联工作,根据关于多态关联的 API 文档,http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#label-Polymorphic+Associations 我必须设置 borrowable_type到 STI 模型的 base_class,在我的例子中是 Staff.

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

但它似乎只适用于 Staff 实例.结果是:

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 时遇到了完全相同的问题.看起来你不能这样做,因为它不起作用.可能这是一种预期的行为.显然,在 Rails 中使用多态关联和单表继承 (STI) 有点复杂.

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 3.2 当前的 Rails 文档给出了结合 多态关联和性传播疾病:

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.

在您的情况下,基本模型将是Staff",即所有项目的borrowable_type"应该是Staff",而不是Guard".使用becomes"可以使派生类显示为基类:guard.becomes(Staff).可以将列borrowable_type"直接设置为基类Staff",或者按照 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

这篇关于如果多态关联的类型列不指向 STI 的基本模型,为什么多态关联对 STI 不起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆