Rails 请教多个模型复用 Category 的办法

wuwx · 2013年03月10日 · 最后由 vkill 回复于 2013年03月14日 · 3422 次阅读

是这样的,假设应用系统里有 电影(Movie),音乐(Music),图片(Image)这三个模型

而这三个模型都需要分类的支持 可能就会需要 MovieCategory,MusicCategory,ImageCategory 这三个分类模型

Movie belongs_to MovieCategory Music belongs_to MusicCategory Image belongs_to ImageCategory

但是 MovieCategory、MusicCategory、ImageCategory 这三个里面肯定有很多重复的代码。

所以希望系统可以只用一个 Category 模型代替 MovieCategory、MusicCategory、ImageCategory 这三个模型

这样就可以变成: Movie belongs_to Category Music belongs_to Category Image belongs_to Category

这样的话,应该如何设计 Category 的数据结构呢? 另外如果想取出 Movie 的所有分类应该如何编码可以显得比较美一些?

加个分类类型字段呢

#1 楼 @themorecolor 假如某个 category(比如 “外语”, id=22)还想同时给 Movie 和 Music 用呢?

#2 楼 @wuwx 那用 多对多 关联? 还得再多建三张表

#2 楼 @wuwx 好像 不对 有点晕 不过 要想只是 少写重复代码的话 给三个分类整个父类 重复代码放到里面 这样方便点吧

lz 怎么一说我也想起一个问题,我要查找所有分类是 English 的 Music 和 Movie 的话应该怎么写?顺路问一下..

感覺你需要的,如果不是 5 樓提到的 polymorphic association,大概就是 STI 了吧? http://api.rubyonrails.org/classes/ActiveRecord/Base.html#label-Single+table+inheritance

#5 楼 @thisiskun 感觉不是用 polymorphic association 实现,因为并不是 category belongs_to movie

#7 楼 @mclee STI 好像也不是我需要的,因为不想建立 MusicCategory,MovieCategory,ImageCategory 三个子类 并且如果用 STI 的话,无法实现某个分类同时被用于 Music 和 Movie

思路: 1, Categorizable (Music, Movie) 与 Category 是多对多关系, 2, Category knows nothing about Categorizable, the connections between "Categorizable" and "Category" are made by a table named "Categorization"

偶觉得有时候打标签比用分类更方便,大不了一个标签代表一个分类,以后还可以扩展同时属于多个分类 gem acts as taggable on 如果自己做,也可以参见插件的源代码

#11 楼 @as181920 想把分类作为 tab 形式列出来 :)

#12 楼 @wuwx 可以把标签也作为 tab 形式列出来,这个不影响。 如果考虑哪些分类/标签要列出来,是另外的事情了

#13 楼 @as181920 假如某分类下没有内容,同样需要列出来啊

#10 楼 @leomayleomay 那假如想列出 Movie 的所有分类应该如何写呢? 包括空的分类(就是还没有分类给某个 @movie 的分类 ---- 空分类)

@as181920 tag 跟 category 应该还是有区别的,一个是多对多,一个是一对多

@wuwx 感觉应该是用单表继承来做吧,Category 跟 Item 是一对多关系, Item 下有子类 Music, Book 等,子类共同属性放在 items 表,不同属性各自 has_one 实现,

Movie 所有分类可以这样 Category.joins(:items).where("items.type = ?", "Music")

#16 楼 @thisiskun 想列出 Movie 的所有的 Category 怎么办呢?包括没有被使用的 category

想偷懒就用 acts as taggable. category 可以看做单 tag

@wuwx, movie has_many :categories, :through => :categorizations

#18 楼 @everett #19 楼 @leomayleomay

这样显示不出来不被任何模型使用的 category 啊……

#20 楼 @wuwx 所以我说,要显示什么,可以考虑另外一个问题或者功能,就像 cms 一样,有个地方专门负责显示什么内容的逻辑。上面说的表关系,仅仅是关系。

@wuwx 你可以看一下 acts_as_taggable 的模型结构 他是 tag -> tagging <- tagger 的结构,我在上一个项目中就用借用了他的代码,再打了几个 patch,把 string basis 改成了 id basis, 其代码主要是在 core 模块中。你用 ActsAsTaggableOn::Tag.all 就能获得全部的 categories,然后就是 scope... 你也能自己通过搭多对多来做。道理和结构都是一样的。

category 封装起来用代理。

用 polymorphic http://guides.rubyonrails.org/association_basics.html#polymorphic-associations

不过我也觉得用 tag 比较合适,不过这个 categories 可以作为节点

@Ddl1st 能解释一下这个做法吗?谢谢

#25 楼 @everett 以后使用更多的分类可以使代码可读性增强

27 楼 已删除
28 楼 已删除

就用 category 字段就好了,重复的代码写到 module

需要 登录 后方可回复, 如果你还没有账号请 注册新账号