原文链接:nicholasren.github.com/2012/07/01/polymorphic-association.html
有这么一个需求,一个在线音乐商店系统,我们暂且叫它'online-store',需要记录消费者对每首歌的评论,一个有经验的rails developer会很快地写出下面的代码:
class Music
has_many :comments
end
class Comment
belongs_to :music
end
对应的表结构如下:
#musics:
| id | integer|
| name | varchar|
| ... | ... |
#comments:
| id | integer|
| text | varchar|
| music_id| integer|
如果需要给music添加,查看评论,可以通过如下代码实现:
#添加评论
music.comments.create {:text => 'this is realy nice'}
#查看评论
music.coments
风云变幻,斗转星移,apple的app store创造了软件销售的新模式,我们的vendor也坐不住了,决定在现有的音乐商店系统上出售应用程序,电影,游戏等内容,同样,这些内容也需要支持评论,有了前面成功的经验,你信心满满增加了下面几个model:
class Application
has_many :comments
end
class Movie
has_many :comments
end
class Game
has_many :comments
end
再来看看我们之前写的model Comment:
class Comment
belongs_to :music
end
现在需要支持多种内容,而且这些类内容之间出了都可以被评论外,再无其他关联,那这个belongs_to该怎么写呢?一个最直接的思路是,扩展Comment,让其支持对以上四类内容的评论,代码如下:
class Comment
belongs_to :music, though => "music_id"
belongs_to :game, though => "game_id"
belongs_to :application, though => "application_id"
belongs_to :movie, though => "movie_id"
end
表结构如下:
#comments:
| id | integer|
| text | varchar|
| music_id | integer|
| game_id | integer|
| application_id | integer|
| movie_id | integer|
有了以上的model,你就可以给应用程序,电影,游戏增加评论了:
#创建评论
application.comments.create {:text => "this is a nice app"}
movie.comments.create {:text => "this is a nice movie"}
game.comments.create {:text => "this is a nice game"}
#查看评论
application.comments
movie.comments
game.comments
目前看来,这些代码工作得很好,然而,做为一个有着良好直觉的程序员,你敏锐地觉察到,将来可能有更多的内容出现在这个"onlne-store"中,也会有更多的内容需要支持评论——你成功地识别出一个”易变点“,每当新增一种内容的时候,你就需要打开这个Comment类,新增一个association,同时,还需要增加migration,这个设计明显违背了开闭原则”。那么,这个问题该怎么解决呢? 再来分析下这个问题,上面我们提到,这些model唯一的共性是 “可以被评论”,于是我们可以抽象出一个概念——“commentable”。如果我们让comment对象知道它所对应的"commentable"对象的id以及类型(game/application/movie),我们就可以获得一个“commentable”对象的所有comments,参考下面的代码:
#查看id为1的music的评论
Comment.find(:commentable_id => 1, :commentable_type => 'music')
#查看id为1的application的评论
Comment.find(:commentable_id => 1, :commentable_type => 'application')
如此,comments的表结构就可以简化为:
#comments:
| id | integer|
| text | varchar|
| commentable_id | integer|
| commentable_type| varchar|
model代码简化为:
#添加评论
Comment.create({:text => "good staff", :commentable_id => "1", :commentable_type => "music"})
#查看评论
Comment.find(:commentable_id => 1, :commentable_type => 'music')
class Comment
belongs_to :commentable, :polymorphic => true
end
class Application
has_many :comments, :as => :commentable
end
class Movie
has_many :comments, :as => :commentable
end
class Game
has_many :comments, :as => :commentable
end
#添加评论
movie.comments.create {:text => 'this is realy nice'}
#查看评论
movie.coments
更多关于“polymorphic association”的信息,请参考这里 怎么样,这样一来,再新增多少种内容类型,处理起来都非常容易,扩展下commentable_type的值就可以了。这个思路的根本出发点在于为识别、分离变化点。这类问题可以抽象为这样一个问题:"如何把一个概念应用到一组除了这个概念,没有其他任何关联的对象上?" ,此类问题可以采用上述思路解决。
相关推荐
Ruby on Rails中文指南
Ruby On Rails中文教材(PDF)
自述 此自述文件通常会记录启动和运行应用程序所需的任何步骤。 您可能想要涵盖的内容: Ruby版 系统依赖 配置 数据库创建 数据库初始化 如何运行测试套件 服务(作业队列、缓存服务器、搜索引擎等) ...
敏捷Rails中文教程 敏捷Rails中文教程 敏捷Rails中文教程
rails-assets, 在 Rails 中,资产管理的解决 Rails 资产 Bundler 到 Bower 代理本自述文件涉及项目的开发方面。 访问站点了解如何在你的应用程序中使用 Rails 资产。 插件开发设置git clone git@github.com:tenex/r
rails指南 中文版
使用Aptana+Rails开发Rails Web应用 有Aptana的安装配置等等,中文
rails_email_preview, 在 Rails 中,预览和编辑应用程序邮件程序模板 Rails 电子邮件预览 使用这里 Rails 引擎在浏览器中预览电子邮件。 兼容 Rails 4.2 。电子邮件审阅: 所有电子邮件预览的列表: 代表有两个主题...
《Rails之道》详细讨论了Rails的程序代码并通过分析Rails中的代码片段来深入解释它的功能,同时,《Rails之道》部分章节也摘录了一些API文档中的内容,使读者能够快速地找到对应的API文档、相关的示例代码以及深入...
rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails 2.3.2离线安装rails ...
在过去的几年中,《Ruby on Rails Tutorial》这本书被视为介绍使用 Rails 进行 Web 开发的先驱者。 在这个全球互联的世界中,计算机编程和 Web 应用程序开发都在迅猛发展,我很期待能为中国的开发者提供 Ruby on ...
shoppe-example, 在 Rails 中使用Shoppe平台的示例存储实现 这是一个 Rails 应用程序,它使用 Shoppe 构建。 它具有一个可以爱的设计,以充分演示Shoppe平台提供的功能以及它在 Rails 应用程序中的。 正在启动要开始...
[Pragmatic Bookshelf] Crafting Rails Applications Expert Practices for Everyday Rails Development (E-Book) ☆ 图书概要:☆ Rails 3 is a huge step forward. You can now easily extend the framework, ...
本资源是参照rails敏捷开发第四版书中的例子,rails的版本是rails3.2.6
Ruby on Rails Guides v2 - Ruby on Rails 4.2.5
Administrate - 一个框架用于在Rails中创建灵活的、强大的管理仪表板
一个用Ruby on Rails搭建的图片分享的网站项目.完整源代码
NULL 博文链接:https://dendrobium.iteye.com/blog/305938
本文将介绍浅谈Ruby on Rails中的include和extend。include主要用来将一个模块插入到一个类或者其它模块。extend用来在一个对象中引入一个模块,这个类从而也具备了这个模块的方法。