2

buildSTIタイプを介して特定のクラスのモデルをターゲットとするスコープでメソッドを呼び出し、ActiveRecordに正しいクラスのインスタンスを構築させたいと思います。

class LineItem < ActiveRecord::Base
  scope :discount, where(type: 'DiscountLineItem')
end

class DiscountLineItem < LineItem; end

> LineItem.discount.build # Expect an instance of DiscountLineItem here
=> #<LineItem ...>

DiscountLineItemここでは、のインスタンスではなく、のインスタンスを期待していましたLineItem

4

2 に答える 2

4

ActiveRecord はオブジェクトを正しいクラスとしてインスタンス化しませんが、タイプを正しく設定します。これには基本的に 2 つの方法があります。

1) オブジェクトを作成し、データベースから再ロードします。

item = LineItem.discount.create(attrs...)
item = LineItem.find(item.id)

2) STI クラスを使用して、そこから直接オブジェクトを作成します。

DiscountLineItem.build

ActiveRecord でできることはすべてありますが、これは意味のない制限のように思えますし、変更するのはそれほど難しくないかもしれません。今、あなたは私の興味をそそりました:)

アップデート:

これは最近Rails 4.0に追加され、次のコミット メッセージが追加されました。

BaseClass.new(:type => "SubClass") だけでなく、parent.children.build(:type => "SubClass") または parent.build_child を実行して、STI サブクラスを初期化できます。クラス名が有効なクラスであること、および関連付けが予期しているスーパー クラスの祖先にあることを確認します。

于 2012-07-09T00:43:51.623 に答える
1

ちょっと忘れてくださいbuild。いくつかある場合はLineItem l、インスタンスではなくインスタンスl.discountを取得します。インスタンスを取得したい場合は、スコープをメソッドに変換することをお勧めしますLineItemDiscountLineItemDiscountLineItem

def self.discount
  where(type: 'DiscountLineItem').map { |l| l.becomes(l.type.constantize) }
end

DiscountLineItemこれで、インスタンスのコレクションが返されます。

于 2012-07-09T00:44:10.743 に答える