我有一个名为 Address 的多态模型。我想要实现的是将许多地址绑定到其他模型(例如用户),但仍然像只有一个一样使用它们,并尝试按类型区分它们。
我的项目设计为只使用一个地址,所以我有很多类似的代码,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
我正在使用 Rails 2.3.14 和 Ruby 1.9.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")
,我需要什么。