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