`
NicholasBugs
  • 浏览: 51783 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

Rails中的Polymorphic Association

阅读更多

原文链接: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中文指南中,你将全面学习到如何利用这个强大的框架来构建动态的、数据驱动的Web应用程序。 首先,让我们深入理解Rails的核心概念: 1. **路由(Routes)**:Rails的路由系统是应用程序的导航蓝图...

    在rails中 使用RSpec生产CHM文档

    标题 "在Rails中使用RSpec生产CHM文档" 暗示了这个话题是关于如何在Ruby on Rails(简称Rails)框架中使用RSpec测试工具来创建帮助文档,特别是以CHM(Microsoft Compiled HTML Help)格式。CHM文件是一种常见的...

    rails指南 中文版

    1. **ActiveRecord**:这是Rails框架中的ORM(Object-Relational Mapping)组件,它负责处理数据库操作。通过ActiveRecord,开发者可以使用面向对象的方式来操作数据,而无需编写SQL语句。 2. **ActionController**...

    Ruby On Rails中文教材(PDF)

    4. **ActiveRecord**:这是Rails中的ORM(对象关系映射)库,它允许开发者用Ruby代码操作数据库,无需编写SQL。 5. **Scaffolding**:Rails的快速开发工具,能自动生成CRUD(创建、读取、更新、删除)操作的模型、...

    Rails 中mongrel的安装

    在Rails项目中安装Mongrel通常通过RubyGems进行,这是一个Ruby的包管理器。首先确保RubyGems已经安装,然后在命令行执行以下命令: ```bash gem install mongrel ``` 安装完成后,可以通过`mongrel_rails`命令来...

    rubyschool-rails-polymorphic-associations-demo

    自述 此自述文件通常会记录启动和运行应用程序所需的任何步骤。 您可能想要涵盖的内容: Ruby版 系统依赖 配置 数据库创建 数据库初始化 如何运行测试套件 服务(作业队列、缓存服务器、搜索引擎等) ...

    使用Aptana+Rails开发Rails Web应用(中文)

    安装过程中,遵循提示进行,确保选择自定义安装并勾选Rails相关的插件,以便在Aptana中获得对Rails的全面支持。 安装完成后,打开Aptana Studio,创建一个新的Rails项目。在“File”菜单中选择“New”然后点击...

    Rails101_by_rails4.0

    此外,书中还介绍了一些Rails中的高级概念,如Strong Parameters(强参数),它在Rails 4.0版本中引入,用于解决之前版本中的参数篡改问题,从而帮助开发者安全地处理外部提交的数据。 通过一系列的教学内容,包括...

    Rails项目源代码

    这个Rails项目提供了学习和研究Web开发的机会,特别是对于Ruby on Rails新手,可以通过阅读和理解源代码来提升技能,了解实际应用中Rails的用法。同时,对于有经验的开发者,这个项目也可以作为一个起点,进行二次...

    rails-assets, 在 Rails 中,资产管理的解决.zip

    rails-assets, 在 Rails 中,资产管理的解决 Rails 资产 Bundler 到 Bower 代理本自述文件涉及项目的开发方面。 访问站点了解如何在你的应用程序中使用 Rails 资产。 插件开发设置git clone git@github.com:tenex/r

    敏捷Rails中文教程

    - **数据库重构**:Rails支持在开发过程中灵活地修改数据库结构,这在敏捷开发中尤为重要,因为需求的变化可能会导致数据模型的调整。 - **代码生成器**:Rails提供了强大的代码生成工具,帮助开发者快速搭建起...

    中文版rails教程

    在Ruby on Rails中,开发者可以快速构建功能丰富的动态网站,因为它提供了大量的内置功能和库,如数据库连接、ORM(对象关系映射)系统ActiveRecord、模板引擎ActionView以及路由系统ActionController等。...

    rails查询学习笔记

    **ActiveRecord查询接口**:这是Rails中最基础的查询方式,如`Model.find(id)`用于根据ID获取记录,`Model.where(condition)`用于根据条件筛选记录,`Model.order(column)`用于排序,`Model.includes(:association)`...

    关于rails 3.1 cucumber-rails 1.2.0

    总的来说,了解和熟练掌握Rails 3.1和Cucumber-Rails 1.2.0的用法,对于任何希望在Ruby on Rails环境中进行高效、高质量开发的团队来说都是至关重要的。通过阅读相关的博客文章(如给出的链接),开发者可以深入学习...

    RailsGuides中那个blog程序源码

    RailsGuides中的"blog"程序是一个典型的入门级示例,旨在帮助初学者理解RoR的工作原理和核心概念。 在Rails中,**模型(Model)** 负责处理数据和业务逻辑,通常与数据库交互。在这个"blog"程序中,可能会有一个`...

    Rails中应用Ext.tree:以中国的省市地区三级联动选择为例

    在Ruby on Rails(Rails)框架中,开发人员经常需要实现各种用户交互功能,例如三级联动选择,这在处理如中国省市区这样的地理数据时尤其常见。这篇博客文章“Rails中应用Ext.tree:以中国的省市地区三级联动选择为...

    rails2-sample

    这一章节将讨论Rails中的安全特性,如防止SQL注入、跨站脚本攻击(XSS)和跨站请求伪造(CSRF)等。通过实施这些防护措施,可以大大降低应用遭受攻击的风险。 #### 9. Advanced Topics(高级主题) 这一部分将覆盖...

    Ruby on Rails Guides v2 - Ruby on Rails 4.2.5

    ### Ruby on Rails Guides v2 - Ruby on Rails 4.2.5 #### 一、重要概念及基础假设 - **重要概念**:本指南旨在帮助读者深入理解Ruby on Rails(以下简称Rails)4.2.5版本的核心功能与最佳实践。 - **基础假设**:...

Global site tag (gtag.js) - Google Analytics