ポリモーフィック関連付けの型列が STI の基本モデルを指していない場合、ポリモーフィック関連付けが STI で機能しないのはなぜですか? 質問する

ポリモーフィック関連付けの型列が STI の基本モデルを指していない場合、ポリモーフィック関連付けが STI で機能しないのはなぜですか? 質問する

ここでは多形性関連と性感染症の症例があります。

# 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+Associationsborrowable_typeSTI モデルの に設定する必要がありますbase_class。私の場合は ですStaff

質問は、borrowable_typeSTI クラスに設定するとなぜ機能しないのかということです。

それを証明するいくつかのテスト:

# 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

しかし、それはスタッフインスタンス。結果は次のとおりです。

# 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>.

ありがとう

ベストアンサー1

いい質問ですね。私も Rails 3.1 を使っていてまったく同じ問題を抱えていました。動作しないので、これはできないようです。おそらく、これは意図された動作です。どうやら、Rails でポリモーフィックな関連付けを単一テーブル継承 (STI) と組み合わせて使用​​するのは少し複雑です。

Rails 3.2の現在のRailsドキュメントでは、多形性関連とSTI:

ポリモーフィック関連付けを単一テーブル継承 (STI) と組み合わせて使用​​するのは少し注意が必要です。関連付けが期待どおりに機能するには、ポリモーフィック関連付けの type 列に STI モデルの基本モデルを必ず保存してください。

あなたの場合、ベースモデルは「スタッフ」です。つまり、「borrowable_type」はすべてのアイテムに対して「スタッフ」であり、「ガード」ではありません。「becomes」を使用して派生クラスをベースクラスとして表示することができます。guard.becomes(Staff)列「borrowable_type」をベースクラス「スタッフ」に直接設定するか、Railsドキュメントが示唆するように、次のように自動的に変換します。

class Car < ActiveRecord::Base
  ..
  def borrowable_type=(sType)
     super(sType.to_s.classify.constantize.base_class.to_s)
  end

おすすめ記事