文/胡振波

作为一个有着一年多Rails开发经验的开发人员,笔者希望通过这篇文章跟读者交流和探讨一下Rails开发的心得体会,体验一下Rails之美。

Rails开发之美,我总结的有这样几点:简洁、透明、自由、开放、轻灵、丰富和优美。可能你已经感觉到,这些词汇大多展现的是感性的一面。没错,Rails开发的每一天都是那么“畅快”,畅快背后其实就是这些生动的感触。笔者希望从这些简单的感触出发,结合实际的例子,来展示Rails真实的美。 Rails之美 简洁

可能很多人在推荐别人使用Rails的时候,都会列举一个理由:简洁。的确,简洁是促使很多人开始学习和使用Rails的原因。那到底什么是简洁?简洁可能代表少,简洁可能代表没有重复,简洁当然也代表复杂的对立面。

Rails是基于ruby语言的。动态语言带来的好处之一是代码量的急剧减少。有一个鲜活的例子,有一次跟客户进行pair,把曾经用Java实现的一个900多行的类,缩减到了100行。客户很是惊讶。当然,纯粹量的减少可能并不代表什么,但至少带来了清晰和易读这两个对代码来说非常重要的特性。

因为动态语言的良好支持,Rails框架使重复的配置工作减少到了极致。比如在Java世界的大量OR Mapping配置文件,在Rails里面不再需要。虽然现在Java世界的配置量也在不断地精简,但还是占据了一定的工作量。重复工作的减少,亦即工作效率的提升。

作为WEB开发领域的DSL,Rails提供的各种机制在各个层面极大地简化了开发的工作量和难度。比如ActionView提供的FormHelper,简化了页面上form的生成;比如ActiveRecord提供的Association,简化了模型之间关联的维护。

举个association的例子,来看一下Rails的简洁之处。下面这两个模型是一对多的关系:一个lightbox有很多images。 class Lightbox < ActiveRecord::Base end class Image < ActiveRecord::Base end

要删除一个lightbox,以及它的所有images,需要这样写: @images = Image.find_by_lightbox_id(@lightbox.id) @images.each do |image| image.destroy end @lightbox.destroy

接下来,让我们给它们声明正确的关联关系: class Lightbox < ActiveRecord::Base has_many :images, :dependent => :destroy end class Image < ActiveRecord::Base belongs_to :lightbox end

则删除操作就变得简单了,且在语义和逻辑上更加明确和清晰: @lightbox.destroy

DSL的一个目的是使某个领域的开发变得更加具体、简单和清晰。Rails框架是从一个现实项目中提炼出来的,这同时也证明了一句话:好的框架都不是凭空想象出来的。 Rails还有很多其它方面可以体现它的简单。简单,就是美。 透明

项目开发过程中,让我觉得很痛快的一件事情是:基本上不需要借助任何外部的文档。 因为Rails本身是透明的,这首先是动态语言提供的好处。当需要了解任何一个方法的功能或者实现时,只需要跳到那个方法查看源代码即可。

同时,对大多数方法,Rails都提供了详尽的文档以及具体的示例。

开放的源代码,以及详尽的注释,让开发人员得以在一个“透明的环境”上进行开发。开发中可以彻底地了解所用工具的习性,这不可谓不是一件痛快的事情。 自由

对一个问题,Rails往往都提供了多种解决方案。我们可以根据问题的场景,自由地选择合适的方案。

比如对于页面中form的生成,我们可以选择使用form_tag方法。但当这个form跟对象关联的时候,更好的选择是使用form_for方法。结合text_field等helper方法,使页面上的元素跟对象的属性更加紧密地结合。

下面再举一个association的例子,来看看Rails如何表现自由的精神。声明多对多关系时,一般是这样的: class Teacher has_and_belongs_to_many :students end class Student has_and_belongs_to_many :teachers end

但有时我们需要利用中间表,并让它映射到一个模型。那么,可以这样来声明模型之间多对多的关联: class Teacher has_many :relations has_many :students, :through => :relations end class Relation belongs_to :teacher belongs_to :student end class Student has_many :relations has_many :teachers, :through => :relations end

选择的多样化带来的是自由。但根据需要和场合选择正确的方案,更加重要。 开放

Rails所体现的一点极其重要的精神是:开放。因为Rails从来不限制你去做任何事情。 有个项目是建立在一个遗留数据库上,并且大多数数据库表结构和遗留数据因为有些原因不能更改。但问题是表结构并不满足Rails的约定,下面列举一些问题和解决办法来窥探一下Rails的开放精神所在。

问题1:单数表名

根据Rails的约定,表名都是复数形式的。比如一个User模型,对应的表名是users。而遗留数据库上的表名是单数形式:user。

解决方案

在environment.rb文件的配置初始化里,关闭默认的复数表名配置: config.active_record.pluralize_table_names = false

问题2:type字段不代表单表继承

根据Rails的约定,type字段是单表继承的保留字段。当从数据库读取数据并实例化成对象时,它会根据type字段的内容来寻找相应的子类型。但这里type字段并不代表单表继承。

解决方案

在模型里面声明另一个字段代表单表继承,比如: set_inheritance_column :clazz

问题3:type字段的值不满足单表继承的约定

又出现另一个问题,type字段用来表示单表继承,但是它的值并不满足单表继承的约定。根据Rails的约定,type的值应该是类名。比如ShoppingCart继承自ImageCollection,那么type的值应该是"ShoppingCart"。但在遗留数据库里,使用的是"shopping_cart"。

解决方案

这里涉及到两

Logo

20年前,《新程序员》创刊时,我们的心愿是全面关注程序员成长,中国将拥有新一代世界级的程序员。20年后的今天,我们有了新的使命:助力中国IT技术人成长,成就一亿技术人!

更多推荐