Aggregations - composed_of 方法
我们在一张表里有几个类似字段,比如 customers 表有 address_street, address_city 字段,用于保存地址信息。好的做法,当然是把它们拆分出来,单独做成 address 表。但如果我们不想/能折分表成的话(改动太大,处理遗留问题等),使用 composed_of 可以实现不用真正折分表,又能起到到分离的作用。
class Customer < ActiveRecord::Base
composed_of :address, mapping: [ %w(address_street street), %w(address_city city) ]
end这里,把 address 当做关联对象。原 customer 的 address_street 和 address_city 分别映射成为 address 的 street 和 city 属性。
根据"约定优于配置",关联对象 address 对应 class Address,我们实现它:
class Address
attr_reader :street, :city
def initialize(street, city)
@street, @city = street, city
end
end之后即可对 Address 的实例对象进行操作。
如何使用?
Customer 有 balance,address_street、address_city 字段。
class Customer < ActiveRecord::Base
# 把 balance 当做关联对象,amount 映射成为它的属性;对应着 class Money
composed_of :balance, class_name: "Money", mapping: %w(balance amount)
# 把 address 当做关联对象,street 和 city 映射成为它的属性;对应着 class Address
composed_of :address, mapping: [ %w(address_street street), %w(address_city city) ]
end可选参数 :class_name, :mapping, :allow_nil, :constructor, :converter,此外,你有下列读、写方法:
除了读、写方法外,composed_of 还创建管理了 Reflection 关联两者:
注意:我们没有 model Money 和 model Address,也没有它们对应的表,所以要实现其对应的 class,类似:
然后就能这么操作:
参考一下 has_one,让 composed_of 变得容易理解。使用 has_one 和 composed_of,两张表均属于一对一关系,只不过 composed_of 是我们想像出来的表,并不存在真正的数据库里。
Note: composed_of 创建的是'值对象',区别于一般的'实体对象'。值对象没有唯一身份标识,只有所有的值相等,两个值对象才相等;而实体对象,有唯一标识(如:id),只要唯一标识相等,两个实体对象就相等了。
可选参数详解
参数
解释
class_name
和其它关联一样,可以指定类名
mapping
旧字段与新字段的映射关系 旧字段在前,新字段在后
allow_nil
被关联的对象,其属性全部为空时,这个被关联的对象是否为 nil 对象 默认选项为 false
constructor
如何初始化值对象
converter
给值对象赋值时,如何处理
默认 关联对象只有在第一次调用,才会初始化 注意这个特点,否则你会发再一些奇怪现象。例如:
最后更新于
这有帮助吗?