2012-07-26 5 views
25

から継承する場合、私はActiveRecordは::ベースから継承するクラスを持っている:私は、このクラスから継承する場合防止STIのRails 3.2.6でActiveRecordのモデル

class Section < ActiveRecord::Base 
    ... 
end 

、Railsは私がSTIをしたいと仮定します。

class AnotherSection < Section 
    ..Rails assumes I have a type field, etc... 
end 

私はSectionクラスから継承し、RailsのSTIの魔法なしで、通常のRubyのサブクラスとしてサブクラスを使用することができるようにしたいです。

ActiveRecord::Baseモデルからサブクラス化するときにSTIを防止する方法はありますか?

+2

あなたが気にしてはいけない 'type'カラムがなければ...' type'を持っているなら、@Veraticusが言ったことをすることでそれを無効にすることができます。 – shuriu

+0

実際にあなたはまだSTIを持っている:両方のクラスからのインスタンスが同じテーブルに格納される、STI(Single Table Inheritance)の定義は何か?あなたは、弁別子列( "型")を持つことは望ましくありません。ただし、セクションの各レコードがプレーン・セクションかAnotherSectionかどうかをどのように知るか? – atorres

答えて

28

あなたがそうのように、モデルのinheritance_columnを無効にすることでこれを実現することができます

class AnotherSection < Section 
    # disable STI 
    self.inheritance_column = :_type_disabled 

end 
+7

それ、または存在しないカラムで十分です。 – shuriu

+3

self.inheritance_column = nilは私のために働いた(しかし、私はずっと前にそれを試していたが、それはレール3.2だった) – Alexis

+0

これは、discriminatorカラムを無効にする。しかし、両方のクラスは同じテーブルに格納されていますが、STI(Single Table Inheritance)の定義は何ですか?あなたはdiscriminatorカラムを削除したばかりです。rubyは格納されているレコードの種類を決めることができません。(ロード時に決定する必要があります) – atorres

11

受け入れ答えは間違いなく動作しますが、お勧めします(私は「正しい」と言うあえて:)方法はabstract_classを設定することです:

class Section < ActiveRecord::Base 
    self.abstract_class = true 
end 
+3

これは正しいアプローチであり、Rails 1.1以降です。 –

+0

これは私のために働いていません。このモデルクラスのオブジェクトをインスタンス化することはできません。( 'NotImplementedError:MyModelは抽象クラスであり、インスタンス化できません。 ') @sathy – deepflame

+0

@deepflame抽象クラスをインスタンス化することはできません。抽象クラスです。 – smathy

1

ActiveRecordに継承を格納する完全にサポートされている戦略は、STIです。ただし、具体的なクラステーブルの継承を自己責任でシミュレートすることはできます。抽象スーパークラスを使用した具体的なクラステーブル継承は、スマッシュで指摘されているように、うまく機能します。

しかし、AnotherSection(データベースに保存されない)普通のクラスにすると、(Veraticusの示唆しているように)ディスクリミネータカラムを無効にすることができます。ただし、AnotherSectionを保存すると、それはSectionと同じテーブルに保持され、それらを区別することはできません。 AnotherSectionが、最も安全なパスを永続化するために意図されていない

#create a Section and saves it 
    sect = Section.create() 
    sect.save() 
    #retrieve the Section as a AnotherSection, breaking polymorphism... 
    sect = AnotherSection.find(sect.id) 
    # another section is more than a section, it is inconsistent. 

場合:を見つけることAnotherSection使用した場合も、それは破壊、オリジナルのインスタンス化をAnotherSectionを返します。 ()など()名前を付けて保存永続性操作を、オーバーライドして見つけること:

class AnotherSection < Section 
     # disable STI, as pointed by Veraticus 
     self.inheritance_column = :_type_disabled 
     # disable save and finding 
     def save(*args) 
     #exception? do nothing? 
     end 
     def find(*args) 
     #exception? do nothing? 
     end 
     def find_by(*args) 
     #exception? do nothing? 
     end 
     # this does not stops here! there is first, last, and even a forty_two finder method! not to mention associations... 
    end 

を一言で言えば、あなたはこれを行うことができますが、あなたSHOULDN'T。リスクは高いです。 継承の代わりにMIXINを使用するなど、別のオプションを検討する必要があります。

関連する問題