has_many through(多对多) 与polymorphic(多态)混合使用

来源:互联网 发布:保留数据重置win10 编辑:程序博客网 时间:2024/06/05 22:43

首先是has_many through和polymorphice的用法

has_many model_names,through: model_names

belongs_to model_nameable,polymorphic:true

以人user养宠物pet为例

一个人可以养多个宠物,但是宠物又分种类 猫 狗等等

那么可以建立如下4个模型
class User <ActiveRecord::Base

has_many :pets

has_many :cats,through: :pets

has_many :dogs,through: :pets

end

class Pet  <ActiveRecord::Base

belongs_to :user

belongs_to :cat

belongs_to :dog

end

class Cat <ActiveRecord::Base

end

class Dog <ActiveRecord::Base

end

那么之后user可以调用cats dogs方法获取养的小猫小猪,但是有一个问题,如果希望一次性获取养的全部宠物的集合该怎么办?

答案应该是user.cats + user.dogs

但是如果养的宠物种类特别多的时候,这样做就显得麻烦了,而且数据处理起来很麻烦

于是这里就可以引入多态关联了,pet和cat dog就刚好是典型的多态关联,一个pet对象它对应的宠物有可能是cat也有可能是dog,但是cat和dog都对应这pet

这样的关联可以用多态来取代

class Pet

belongs_to :pettable,polymorphic: true

end

并且在pet表中增加pettable_id(integer) pettable_type(string)两个字段

这时可以直接通过pet.pettable,获取cat dog对象


将上述两种关联结合起来,各个模型如下所示

class User <ActiveRecord::Base

has_many :pets

has_many :cats,through: :pets,source_type: 'Cat',source: 'pettable'

has_many :dogs,through: :pets,source_type: 'Dog',source: 'pettable'

end

class Pet  <ActiveRecord::Base

belongs_to :user

belongs_to :pettable,polymorphic: true

end

User模型中source_type source是必须要指明的,在has_many through 关联是通过一个多态模型去关联其他模型的时候,只有指定了source和source_type这样才能够程序正确的模型对象,不然,像user.cats这样的调用的话,rails会去寻找Pet::Cat这样的关联,在sql语句中会去寻找pettable_type为pet的,但是实际上Pet只关联了pettable,所以会找不

到。


按照上述方式定义之后,就可以通过user.cats user.dogs找到其下的各种宠物了,最关键的是,可以更为方便的获取所有种类宠物的集合

直接通过  user.pets.pettable

结果就类似于 [Cat: {},Dog: {},Dog: {},Cat: {}...]这样一个数组,所有类型的宠物都在里面了,在子关联模型非常多的时候,非常有用

阅读全文
0 0