【編者按】本文最早發佈與 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/