【编者按】本文最早发布与 JETRuby 博客,主要介绍了开发新手最容易犯的 Ruby 错误。文章系国内 ITOM 管理平台 OneAPM 编译呈现。

一年前,我们创立了以 “Rubyboost” 为名的 Ruby on Rails 课程。简而言之,本课程的目标是使对编程了解不多的新手也能在两个月内,提升技能、成为初级开发者。在成功完成课程之后,学生会收到为其两个月的实习邀请,实习地点就在我们公司。如果一切顺利,就会得到聘用。不得不说,这是一种相对公平且简单的成为职业开发者的道路,你觉得呢?

顺带说一句,你根本想不到,有多少人愿意来参加并学习 Rails 编程!

在分析了所有受训者编写的代码之后,我们总结了50个最常见的错误!更糟糕的是,每个小组所犯的错误与前一组的错误几乎一模一样。

以下是 Rails 新手常常忽略或做错的地方。我们还包含了“对“,”错”两个版本的代码样本,使得教程更为清楚。

1、他们不使用自动生成的方法

############
## WRONG ##
############ if course.visible
# do something
end ##############
## RIGHT ##
############## if course.visible?
# do something
end

通常,Rails 和许多 gems 会为它们使用的对象添加一些有用的帮助方法。例如,Rails 会自动为布尔字段添加声明。通常,这些方法的名字是以问号结尾的。请牢记这一点!

2、他们不知道“N+1”查询来自何处

#############
## WRONG ##
############# @homeworks = lesson.homeworks - @homeworks.each do |homework|
%p homework.user.email #############
## RIGHT ##
############# @homeworks = lesson.homeworks.includes(:user) - @homeworks.each do |homework|
%p homework.user.email

了解 ORM 如何与数据库交互是非常重要的。但是,新手往往没有这种了解。因此,他们很少使用 “includes”、“preload” 与 “eager_load” 这类方法,并且对 “bullet” gem 一无所知。

在第一个例子中,N+1 查询会传递至数据库。”N” 是已经完成的家庭作业数量。查询数量可能是10、20甚至100。而在第二个例子中,只有2个查询!

3、他们不用 scopes(域)

############
## WRONG ##
############ def index
@lessons = Сourse.lessons.order(position: :asc)
end ############
## RIGHT ##
############ class Lesson < ActiveRecord::Base
belongs_to :course scope :by_position, -> { order(position: :asc) }
end def index
@lessons = course.lessons.by_position
end

Scopes 允许你隐藏数据库的实现,并将代码唯一化(uniqualize)。而且,代码的可读性也会大幅提升,因为他们透露了开发者的意图,而非数据库的结构。

4、他们不了解 “after_create” 与 “after_commit” 间的差别

模型的数据,包括其在 “after_create” 中的新 ID,可以从内部,而非外部进行读取,原因是交易尚未完成。

如果我在数据库中创建了一条记录,之后打算将其 ID 放入 redis 或任意的存储中,会得到以下结果:

  • 如果 ID 在交易完成之前使用,“after_create” 可能会导致无效数据。

  • 借助 “Sidekiq” 或其他任意后台工作,我总是可以使用 “after_commit” 确保数据的完整性。

5、他们总是使用 ORM

#############
## WRONG ##
############# Article.all.each { |article| article.delete } Article.all.map { |article| article.title } Course.all.select { |course| course.created_at < 5.years.ago }.each { |course| course.articles.delete_all } #############
## RIGHT ##
############# Article.delete_all Article.pluck(:title) old_courses_ids = Course.where(‘created_at < ?’, 5.years.ago’).pluck(:id)
Article.where(course_id: old_courses_ids).delete_all

尽管使用对象无疑非常方便,但整个过程却非常缓慢,而且需要很多内存。新手们可能并不理解代码的工作原理,以及如何提高其效率。

6、他们不了解 “dependent destroy” 与 “delete_all” 的区别

在被移除之前,“dependent destroy” 会选择所有受限记录,建立其对象,并调用各自的毁灭方法。此方法允许你移除所有受限数据。但是,当涉及大量数据时,这种方法就不管用了。

至于 “dependent delete_all”,它会通过一条 SQL 查询移除自己。它效率很高,但是,在这种情况下,你得自己考虑数据库的完整性。

7、他们不用带 bang 的方法

#############
## WRONG ##
############# class Article
validates :body, length: { minimum: 200 }
end articles_data.each do |article_data|
Article.create(article_data)
end #############
## RIGHT ##
############# # There are 2 possible solutions articles_data.each do |article_data|
Article.create!(article_data)
end # In this case a developer will be able to see that data he was not expencting to receive will get on the input articles_data.each do |article_data|
article = Article.new(article_data) unless article.save
puts ‘Can not save article’
#process this situation
end
end
# Give a user a choice.

根据协议,将 bang(!) 添加至方法名的情况有如下两种:

  • 如果某个方法修改了其访问的对象

  • 如果某个方法在执行失败后抛出了异常

新手们常常忽略第二种情况。如果代码出了问题,你必须尽快找到问题根源。例如,如果完全不处理将记录保存至数据库的结果,最好还是抛出异常以找到哪段代码处理了无效数据。

在上例中,如果一个无效的物品传给输入,就会被忽视。

8、他们不在迁移中设置默认字段

#############
## WRONG ##
############# class Article
after_initialize :set_default_status def set_default_status
self.status = ‘pending’
end
end #############
## RIGHT ##
############# class MyMigration
def up
change_column :articles, status, :string, default: ‘pending’
end def down
change_column :articles, status, :string
end
end

如果字段中的某个模型必须要有一个默认值,应该通过数据库进行安装。

9、他们不在迁移中设置限制条件

#############
## WRONG ##
############# class MyMigration
def change
add_column :profiles, user_id, :integer
end
end #############
## RIGHT ##
############# class MyMigration
def change
add_column :profiles, user_id, :integer, null: false
end
end

对于基础架构的限制条件越多,我们的应用就会越可靠。此外,别忘记 “null:false”,用户不可以没有简介。

10、他们不在迁移中写反向迁移

如果不能回滚,迁移的意义在哪儿?

以上是新手们最常犯的 Ruby on Rails 错误的第一部分,如果喜欢本文,请记得分享哦。

未完待续……

本文系 OneAPM 工程师编译整理。OneAPM 能为您提供端到端的 Ruby 应用性能解决方案,我们支持所有常见的 Ruby 框架及应用服务器,助您快速发现系统瓶颈,定位异常根本原因。分钟级部署,即刻体验,Ruby 监控从来没有如此简单。想阅读更多技术文章,请访问 OneAPM 官方技术博客

本文转自 OneAPM 官方博客

原文地址:http://jetruby.com/expertise/common-ruby-rails-mistakes-beginners-make-model-database/

开发新手最容易犯的50个 Ruby on Rails 错误(1)的更多相关文章

  1. Android开发新手常见的10个误区

    在过去十年中最流行的移动应用开发开发平台中,我们认为,Android平台是一个新开发的最方便的平台.一个廉价的工具,友好的开发者社区,众所周知的编程语言(Java),使得开发Android应用程序从未 ...

  2. PHP 原创视频教程-网站开发新手视频教程

    PHP 原创视频教程-网站开发新手视频教程 有偿招徒弟,,视频免费提供. 本视频教程,面向的是毫无经验的新手,快速上手的. 第一次做视频做的不好的,请各位看官多多包含. 第一部分,HTML 视频教程 ...

  3. 给iOS开发新手送点福利,简述文本属性Attributes的用法

    给iOS开发新手送点福利,简述文本属性Attributes的用法   文本属性Attributes 1.NSKernAttributeName: @10 调整字句 kerning 字句调整 2.NSF ...

  4. Java开发人员最常犯的10个错误

    这个列表总结了10个Java开发人员最常犯的错误. Array转ArrayList 当需要把Array转成ArrayList的时候,开发人员经常这样做: List<String> list ...

  5. MVC4.0系统开发新手历程1

    MVC4.0系统开发新手历程(一) 接手了一个简单的销售奖金计算的项目,虽然不算大但是业务逻辑比较复杂,还夹杂了很多的特殊情况,毕竟是大公司什么样的人都有,好了不多说切入正题,项目是公司的一个前辈负责 ...

  6. Kernel Newbies内核开发新手的资源

    Jessica McKellar在Ksplice blog上的博客文章 <Linux Device Drivers> 如果你在写一个操作系统,OSDev wiki是一个不错的网站 Kern ...

  7. A-Frame WebVR开发新手教程

    WebVR和WebGL应用程序接口使得我们已经能够在浏览器上创建虚拟现实(VR)体验.但从project化的角度而言,开发社区还须要很多其它方便强大的开发库来简化编程.Mozilla的 A-Frame ...

  8. 开发新手教程【三】Arduino开发工具

    Arduino开发环境搭建 获取Arduino IDE开发工具 下载地址 :http://arduino.cc/en/Main/Software 能够下载release 版.Beta版和前期版本号 A ...

  9. 《IM开发新手入门一篇就够:从零开发移动端IM》

        登录 立即注册 TCP/IP详解 资讯 动态 社区 技术精选 首页   即时通讯网›专项技术区›IM开发新手入门一篇就够:从零开发移动端IM   帖子 打赏 分享 发表评论162     想开 ...

随机推荐

  1. .Net 并发写入文件的多种方式

    1.简介 本文主要演示日常开发中利用多线程写入文件存在的问题,以及解决方案,本文使用最常用的日志案例! 2.使用File.AppendAllText写入日志 这是种常规的做法,通过File定位到日志文 ...

  2. Java I/O : Java中的进制详解

    作者:李强强 上一篇,泥瓦匠基础地讲了下Java I/O : Bit Operation 位运算.这一讲,泥瓦匠带你走进Java中的进制详解. 一.引子 在Java世界里,99%的工作都是处理这高层. ...

  3. 编写高质量代码改善java程序的151个建议——[1-3]基础?亦是基础

    原创地址:   http://www.cnblogs.com/Alandre/  (泥沙砖瓦浆木匠),需要转载的,保留下! Thanks The reasonable man adapts himse ...

  4. java基础系列--volatile关键字

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/7833881.html 1.volatile简述 据说,volatile是java语言中最轻 ...

  5. MyBatis源码解析(八)——Type类型模块之TypeAliasRegistry(类型别名注册器)

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6705769.html 1.回顾 前面几篇讲了数据源模块,这和之前的事务模块都是enviro ...

  6. 结构型---代理模式(Proxy Pattern)

    代理模式的详细介绍 代理模式按照使用目的可以分为以下几种: 远程(Remote)代理:为一个位于不同的地址空间的对象提供一个局域代表对象.这个不同的地址空间可以是本电脑中,也可以在另一台电脑中.最典型 ...

  7. Maven私服 Nexus使用一例

    一.背景 本次搭建Nexus的私服是为了解决两件事 1.公司网络限制,部分项目组同事无法直接访问互联网,不能直接下载一些依赖的jar文件; 2.一些独立的jar无法通过Maven添加依赖的方式引入到项 ...

  8. fiddle使用小结

    1:保存发出的请求:右键Save,找到selected Sessions 选择 in ArchiveZip 2:更改header 重新发送请求:右键 Unlock For Editing 然后修改He ...

  9. vb.net 数字大写

    Private Function RMBChinese(ByVal Rmb As Double) As String Dim Rmbexp As String  Dim Rmbda As String ...

  10. 【Tomcat】Tomcat工作原理

    Tomcat 总体结构 Tomcat 的结构很复杂,但是 Tomcat 也非常的模块化,找到了 Tomcat 最核心的模块,您就抓住了 Tomcat 的“七寸”.下面是 Tomcat 的总体结构图: ...