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