14条Rails最佳实践

参考链接:https://www.sitepoint.com/10-ruby-on-rails-best-practices-3/

1. 两个空格的缩紧
2. 定义断言方法时以问号(?)结尾
3. Iteration: 用each替代for
4. 用unless替代!if
5. Short Circuit: 当判断条件确定时,尽早退出

示例:

if user.gender == "male" && user.age > 17
  do_something
elsif user.gender == "male" && user.age < 17 && user.age > 5
  do_something_else
elsif user.age < 5
  raise StandardError
end

Short Circuit代码:

raise StandardError if user.age < 5
if user.gender == "male" && user.age > 17
  do_something
elsif user.gender == "male" && user.age < 17 #we saved a redundant check here
  do_something_else
end
6. 写测试
  • 测试相当于你的程序和特性的详细规范
  • 测试相当于给其他开发者的文档,使他人更好的理解你实现的意图
  • 测试可以更早的发现和消灭bugs
  • 测试可以在重构以及性能调优的时候给你更多信心,保证不会影响现有功能。
7. DRY(不要重复自己)
  • 使用抽象类
  • 使用Modules
8. 聪明的使用Enums

参考代码:

class Book
  enum status: { draft: 0, completed: 1, published: 2 }
  ...
end

...

if book.draft?
  do_something
elsif book.completed?
  do_something
elsif book.published?
  do_something
end
9. 胖Models, 瘦Controllers和Concerns
  • 将响应(response)无关的代码挪出Controllers, 比如业务逻辑以及持久化/模型变更的代码.
  • Controllers应该只调用model的简单queries, 负责的queries应该挪到Model里面并且封装成scopes. Controllers主要负责的是如何处理请求( request handling), 以及如何返回响应(response related logic).
  • 任何跟request和reponse无关并且和Model有直接联系的代码都应该放到对应Model里.
  • 任何包含了数据结构的类都应该放到app/models目录, 作为Non-ActiveRecord model(table-less class).
  • 当业务逻辑是为了一个特定的领域用途(Printing, Library & etc.)并且和已有的model上下文无关, 应该使用PORO(Plain Old Ruby Objects)类, 并且可以放到app/models/some_directory目录. 所有/app下的代码都会在app启动时自动加载. POROs也可以放到app/models/concerns和app/controllers/concerns目录.
  • 如果一些PORO, Modules或者Classes跟具体应用无关(application independent), 并且可以用于其他应用,请放到/app/lib目录下.
  • 使用Modules来抽象一些共用功能(common functionality), 并且放到app/*目录, 或者在和应用无关(independent)情况下放到app/lib目录.
  • "Service"层是经典MVC模式中重要的一环, 当程序代码增长到难以决策该把一些特定逻辑放在哪里的时候. 想象一下, 你需要一个机制来给订阅者发送图书已出版的短信、邮件或者其他类型的通知. 你可以创建一个关于通知的Service, 并且放到/app/services目录.
10. 国际化/本地化(Internationalization/Localization): 将文字放到yml而不是代码中
11. 数据库方面最佳实践
  • 数据库有任何改变时中, 总是向版本管理系统签入最新的db/schema.rb文件.
  • 当在新系统中创建数据库时, 应使用db:schema load而不是db:migrate.
  • 其他所有情况下, 使用db:migrate来应用新的migration.
  • 不要使用migration向数据库添加数据,使用db/seeds.db来做这件事.
12. 使用嵌套(Nested) Resources/Routes当两个resource有从属关系时
13. 使用Time.zone.now替代Time.now
  • 一个最佳实践是宗师定义默认的timezone在config/application.rb里.
  • Date.today和Time.now总是基于当前及其的timezone.
  • Time.zone.now和Time.zone.today可以解决一些开发环境和生产环境之间的timezone方面的不一致和冲突.
14. 不要将太多逻辑放到Views层,放到app/helpers