【编者按】本文最早发布与 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. nginx 系列 1 linux下安装以及配置IIS分发

    一. 安装 操作系统:centos 7 ,nginx版本1.12.2,windows server 2008 iis 1.1 确认nginx所依赖的工具 Zlib:  nginx提供gzip模块,需要 ...

  2. Django使用Channels实现WebSocket--下篇

    希望通过对这两篇文章的学习,能够对Channels有更加深入的了解,使用起来得心应手游刃有余 通过上一篇<Django使用Channels实现WebSocket--上篇>的学习应该对Cha ...

  3. Java生成sitemap网站地图

    访问我的博客 sitemap 是什么?对应没有接触过网站 SEO 的同学可能不知道,这里引用一下百度站长的一段解释. Sitemap(即站点地图)就是您网站上各网页的列表.创建并提交Sitemap有助 ...

  4. 【原创】驱动加载之CreateService

    SC_HANDLE WINAPI CreateService( _In_ SC_HANDLE hSCManager, _In_ LPCTSTR lpServiceName, _In_opt_ LPCT ...

  5. Java中的instanceof和isInstance基础讲解

    1. instanceof 是一个操作符 使用方法: ? 1 2 if(a instanceof B){ } 表示:a 是不是 B 这种类型 2. isInstance是Class类的一个方法 ? 1 ...

  6. 飞跃式发展的后现代 Python 世界

    飞跃式发展的后现代Python世界 如果现代Python有一个标志性特性,那么简单说来便是Python对自身定义的越来越模糊.在过去的几年的许多项目都极大拓展了Python,并重建了“Python”本 ...

  7. TCP中往返时间的估计与超时

    往返时间的估计与超时   TCP采用超时/重传机制来处理报文段的丢失问题.尽管这在概念上面很简单,但是在实际中还是会产生很多微妙的问题.最明显还是超时时间间隔的设置.很显然,这个时间间隔肯定会大于RT ...

  8. Python循环结构用法

    本文介绍python中的while循环.for循环.在python中for可以用于循环,也可用于另一种近亲的列表解析,列表解析是python中非常重要的特性,详细内容见后面的文章. 一般来说,pyth ...

  9. [转]MySQL忘记root密码解决方法

    本文转自:https://www.cnblogs.com/wxdblog/p/6864475.html 今天重新装了一遍MySQL,因为用的是免安装的,所以需要重新设置密码,然后我一通,结果搞得自己也 ...

  10. 第一册:lesson ninety-three。

    原文:  our new neighbor. Nigel is our new next-door neighbor. He is a pilot. He was in the R.A.F. He w ...