【编者按】本文最先发布与 JETRuby 博客,主要介绍了开发新手最容易犯的 Ruby 错误。文章系国内 ITOM 管理平台 OneAPM 编译呈现。html
一年前,咱们创立了以 “Rubyboost” 为名的 Ruby on Rails 课程。简而言之,本课程的目标是使对编程了解很少的新手也能在两个月内,提高技能、成为初级开发者。在成功完成课程以后,学生会收到为其两个月的实习邀请,实习地点就在咱们公司。若是一切顺利,就会获得聘用。不得不说,这是一种相对公平且简单的成为职业开发者的道路,你以为呢?redis
顺带说一句,你根本想不到,有多少人愿意来参加并学习 Rails 编程!数据库
在分析了全部受训者编写的代码以后,咱们总结了50个最多见的错误!更糟糕的是,每一个小组所犯的错误与前一组的错误几乎如出一辙。编程
如下是 Rails 新手经常忽略或作错的地方。咱们还包含了“对“,”错”两个版本的代码样本,使得教程更为清楚。ruby
############ ## WRONG ## ############ if course.visible # do something end ############## ## RIGHT ## ############## if course.visible? # do something end
一般,Rails 和许多 gems 会为它们使用的对象添加一些有用的帮助方法。例如,Rails 会自动为布尔字段添加声明。一般,这些方法的名字是以问号结尾的。请牢记这一点!服务器
############# ## 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” 是已经完成的家庭做业数量。查询数量多是十、20甚至100。而在第二个例子中,只有2个查询!框架
############ ## 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)。并且,代码的可读性也会大幅提高,由于他们透露了开发者的意图,而非数据库的结构。less
模型的数据,包括其在 “after_create” 中的新 ID,能够从内部,而非外部进行读取,缘由是交易还没有完成。ide
若是我在数据库中建立了一条记录,以后打算将其 ID 放入 redis 或任意的存储中,会获得如下结果:
若是 ID 在交易完成以前使用,“after_create” 可能会致使无效数据。
借助 “Sidekiq” 或其余任意后台工做,我老是可使用 “after_commit” 确保数据的完整性。
############# ## 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
尽管使用对象无疑很是方便,但整个过程却很是缓慢,并且须要不少内存。新手们可能并不理解代码的工做原理,以及如何提升其效率。
在被移除以前,“dependent destroy” 会选择全部受限记录,创建其对象,并调用各自的毁灭方法。此方法容许你移除全部受限数据。可是,当涉及大量数据时,这种方法就无论用了。
至于 “dependent delete_all”,它会经过一条 SQL 查询移除本身。它效率很高,可是,在这种状况下,你得本身考虑数据库的完整性。
############# ## 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(!) 添加至方法名的状况有以下两种:
若是某个方法修改了其访问的对象
若是某个方法在执行失败后抛出了异常
新手们经常忽略第二种状况。若是代码出了问题,你必须尽快找到问题根源。例如,若是彻底不处理将记录保存至数据库的结果,最好仍是抛出异常以找到哪段代码处理了无效数据。
在上例中,若是一个无效的物品传给输入,就会被忽视。
############# ## 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
若是字段中的某个模型必需要有一个默认值,应该经过数据库进行安装。
############# ## 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”,用户不能够没有简介。
若是不能回滚,迁移的意义在哪儿?
以上是新手们最常犯的 Ruby on Rails 错误的第一部分,若是喜欢本文,请记得分享哦。
未完待续……
本文系 OneAPM 工程师编译整理。OneAPM 能为您提供端到端的 Ruby 应用性能解决方案,咱们支持全部常见的 Ruby 框架及应用服务器,助您快速发现系统瓶颈,定位异常根本缘由。分钟级部署,即刻体验,Ruby 监控历来没有如此简单。想阅读更多技术文章,请访问 OneAPM 官方技术博客。
本文转自 OneAPM 官方博客
原文地址:http://jetruby.com/expertise/common-ruby-rails-mistakes-beginners-make-model-database/