如何通过多个模型关联到多态模型?附Rails代码示例
如何通过多个模型关联到多态模型?
嘿,看了你的代码,发现问题出在User模型里重复定义了has_many :items——这两个同名的关联会互相覆盖,肯定没法正常工作。咱们来调整一下,让User能同时通过Playlist和Memory关联到多态的Item模型。
第一步:修正User模型的关联命名
给两个关联起不同的名字,然后通过source指定对应的源关联(也就是Playlist和Memory里的items关联):
class User < ApplicationRecord has_many :memories has_many :playlists # 通过Playlist关联到Item,命名为playlist_items has_many :playlist_items, through: :playlists, source: :items # 通过Memory关联到Item,命名为memory_items has_many :memory_items, through: :memories, source: :items end
这里的source: :items是告诉Rails:要关联的是Playlist/Memory模型里定义的has_many :items关联。因为Item的多态关联已经在Playlist和Memory里通过as: :itemable配置好了,所以这里不需要额外指定source_type(Rails会自动识别)。
其他模型的验证
你的其他模型配置基本没问题,再确认一下:
- Item模型的多态关联正确:
class Item < ApplicationRecord belongs_to :itemable, polymorphic: true, optional: true end - Playlist和Memory的关联也没问题(假设Memory模型的完整代码类似Playlist):
class Playlist < ApplicationRecord belongs_to :user has_many :items, as: :itemable, dependent: :destroy accepts_nested_attributes_for :items, allow_destroy: true end class Memory < ApplicationRecord belongs_to :user has_many :items, as: :itemable, dependent: :destroy # 如果需要嵌套属性,也可以加上accepts_nested_attributes_for :items end
使用示例
现在你可以轻松获取用户的不同类型Item了:
# 获取用户所有Playlist里的Item user.playlist_items # 获取用户所有Memory里的Item user.memory_items # 如果需要合并所有Item,可以加个实例方法 class User < ApplicationRecord # ... 其他关联 ... def all_items # 高效的数据库级联查询,避免内存中拼接数组 Item.where(id: playlist_items.select(:id).union(memory_items.select(:id))) end end
这样调整后,就能正常通过多个模型关联到多态的Item模型啦!
内容的提问来源于stack exchange,提问作者Jef Rice
相关产品推荐
相关产品推荐

