1

複数のテーブルを手動で選択する非常に複雑な Rails (v 3.2) モデルがあります。これは、モデルを表示するために必要なすべてのデータを取得するのに最適です。ただし、データが存在せず、仮想オブジェクトを作成する必要がある場合、これらの列はモデルに存在しません。私の人生では、モデルで仮想列と実際の列の両方をサポートする方法を理解できません。

これよりもはるかに複雑ですが、これは私が現在持っている一般的な選択です:

class MyObject < ActiveRecord::Base

  attr_accessible :apples, :bananas, :oranges

  def self.get(id)
    select("my_objects.*, table1.apples, table2.bananas, table3.oranges")
      .joins("left outer join table1 on something
              left outer join table2 on something
              left outer join table2 on something")
      .where(:my_object => id)
  end
end

idこれは、存在するときに表示する必要があるものに最適です。ただし、場合によってidは存在せず、仮想 (またはデフォルト) オブジェクトを表示する必要があります。

その仮想オブジェクトに対して、次のようなことが簡単にできると思いました。

@my_object = MyObject.new({:apples => 1,
                           :bananas => 50,
                           :oranges => 10})

しかしもちろん、@my_object.applesMyObject には実際にはこれらの列がないため、ビューでエラーが発生します。

ActionView::Template::Error (unknown attribute: apples)

私が取った次のステップはattr_accessorMyObjectモデルに追加することでした:

attr_accessor :apples, :bananas, :oranges

virtualこれは、のバージョンに最適ですMyObject。しかし今、オブジェクトの実際のバージョンを表示しようとすると、リンゴ、バナナ、オレンジがすべて nil です! これは、attr_accessorgetter と setter が select が返すものをオーバーライドしているためだと思います。

このモデルで仮想属性と実際の属性の両方をサポートするにはどうすればよいですか?

method_missingps と一緒に複数の使用方法を試しましdefine_methodたが、成功するものは何も得られませんでした。

4

3 に答える 3

1

興味深い問題です。

1 つの方法は、仮想属性の setter メソッドを次のように定義することです。

# MyObject.rb

def set_virtual_attribs=(hsh)
 hsh.map{|key,value|  self[key] = value}
end

次に、そのような仮想オブジェクトを作成できます

@my_object = MyObject.new(:set_virtual_attribs => {
                           :apples => 1,
                           :bananas => 50,
                           :oranges => 10
                         })

仮想属性は として利用できるようになり、が呼び出され@my_object.applesない限り、実際のオブジェクトの属性メソッドはオーバーライドされません。set_virtual_attribs

于 2013-09-25T22:17:21.660 に答える