Addressというポリモーフィックモデルがあります。私が達成しようとしているのは、他のモデル(たとえば、ユーザー)にバインドされた多くのアドレスをヘビーにすることですが、それでも1つしかない場合と同じように使用し、タイプごとに区別してみてください。
私のプロジェクトは1つのアドレスのみを使用するように設計されているため、のようなコードUser.first.address
やUser.first.address=...
何もできないコードがたくさんあります。
これが一種の例です:
|id|addressable_type|addressable_id| type | street |
1|User |1 | first | Foo
2|User |1 | second | Bar
3|User |1 | NULL | Other
そして私がしたいのは:
User.find(1).address(:second)
どちらを返す必要があります<Address street:"Bar">
、
User.find(1).address
これはを返す必要<Address street:"Other">
がUser.find(1).addresses
ありますが、オブジェクトのコレクションを返す必要があります。
私はコードの一部を使用して、モデルにアドレス動作を追加します。
module Ext::Models::Addressable
def self.included(mod)
super
mod.class_eval do
def self.acts_as_addressable
include InstanceMethods
# Use has_many :delete_all for better performance
has_many :addresses, :as => :addressable, :dependent => :delete_all
has_one :address, :as => :addressable
end
end
end
module InstanceMethods
# I tried with this, but this doesn't even allow me to start rails becauses raises "there is no address method"
def address_with_type(type = nil)
if type
self.addresses.find(:first, :conditions => ["type = ?", type.to_s])
else
address_without_type
end
end
alias_method_chain :address, :type
end
end
Rails2.3.14とRuby1.9.2を使用しています。
これが可能であれば、特定のモデル(たとえばユーザー)の新しいアドレスを作成するための最良の方法も知りたいです。
前もって感謝します。
解決
私はすべての可能性を絞り込みました、そして現在プロジェクトでは2つのタイプのアドレスしかありません。アプローチを大幅に簡素化することができました。現在、私のようにself.included
見えます:
has_many :addresses, :as => :addressable, :dependent => :delete_all
has_one :address, :as => :addressable, :conditions => {:type => nil}
has_one :foo_address, :class_name => 'Address', :as => :addressable, :conditions => {:type => "foo"}
そして今、私はこのような新しいオブジェクトを構築することができます:
user.build_address(:street => "abc")
そしてuser.build_foo_address(:street => "def")
、まさに私が必要としているものです。