zoukankan      html  css  js  c++  java
  • ActiveRecord 資料驗證及回呼

    Validation 資料驗證

    ActiveRecord 的 Validation 驗證功能,透過 Rails 提供的方法,你可以設定資料的規則來檢查資料的正確性。如果驗證失敗,就無法存進資料庫。

    和 Database integrity 不同,這裡是在應用層設計驗證功能,好處是撰寫程式非常容易,Rails 已經整合進 HTML 表單的使用者介面。但是如果你的資料庫不只有 Rails 讀取,那你除了靠 ActiveRecord 之外,也必須要 DB 層實作 integrity 才能確保資料的正確性。

    確保必填

    validates_presence_of 是最常用的規則,用來檢查資料為非 nil 或空字串。

    class Person < ActiveRecord::Base
     validates_presence_of :name
     validates_presence_of :login
     validates_presence_of :email
    end

    你也可以合併成一行

    class Person < ActiveRecord::Base
     validates_presence_of :name, :login, :email
    end

    確保字串長度

    validates_length_of 會檢查字串的長度

    class Person < ActiveRecord::Base
      validates_length_of :name, :minimum => 2 # 最少 2
      validates_length_of :bio, :maximum => 500 # 最多 500
      validates_length_of :password, :in => 6..20 # 介於 6~20
      validates_length_of :registration_number, :is => 6 # 剛好 6
    end

    確保數字

    validates_numericality_of 會檢查必須是一個數字,以及數字的大小

    class Player < ActiveRecord::Base
      validates_numericality_of :points
      validates_numericality_of :games_played, :only_integer => true # 必須是整數      
      validates_numericality_of :age, :greater_than => 18
    end

    除了 greater_than,還有 greater_than_or_equal_to, equal_to, less_than, less_than_or_equal_to 等參數可以使用。

    確保唯一

    檢查資料在資料表中必須唯一。:scope 參數可以設定範圍,例如底下的 :scope => :year 表示,在 Holiday 資料表中,相同 year 的 name 必須唯一。

    class Account < ActiveRecord::Base
      validates_uniqueness_of :email
    end
    
    class Holiday < ActiveRecord::Base
      validates_uniqueness_of :name, :scope => :year
    end

    另外還有個參數是 :case_sensitive 預設是 true,表示要區分大小寫。

    這條規則並沒有辦法百分百確定唯一,如果很接近的時間內有多個 Rails processes 一起更新資料庫,就有可能發生重複的情況。比較保險的作法是資料庫也要設定唯一性。

    確保格式正確

    透過正規表示法檢查資料的格式是否正確,例如可以用來檢查 Email、URL 網址、郵遞區號、手機號碼等等格式的正確性。

    class User < ActiveRecord::Base
        validates_format_of :email, :with => /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\z/i
        validates_format_of :url, :with =>  /(^$)|(^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$)/ix
    end

    正規表示法(regular expression)是一種用來比較字串非常有效率的方式,讀者可以利用 Rubular 進行練習。

    確保資料只能是某些值

    用來檢查資料必須只能某些值,例如以下的 status 只能是 pending 或 sent。

    class Message < ActiveRecord::Base
        validates_inclusion_of :status, :in => ["pending", "sent"]
    end

    另外還有較少用到的 validates_exclusion_of 則是確保資料一定不會是某些值。

    其他

    validates_acceptance_of :terms_of_service

    用來讓使用者必須核選一個 checkbox 方塊,例如已閱讀使用者條款

    validates_confirmation_of :password 

    用在需要讓使用者在表單輸入兩次的情況,例如密碼確認。

    可共用的驗證參數

    以下這些參數都可以用在套用在上述的驗證方法上:

    allow_nil

    允許資料是 nil。也就是如果資料是 nil,那就略過這個檢查。

    class Coffee < ActiveRecord::Base
      validates_inclusion_of :size, :in => %w(small medium large), :message => "%{value} is not a valid size", :allow_nil => true
    end

    allow_blank

    允許資料是 nil 或空字串。

    class Topic < ActiveRecord::Base
      validates_length_of :title, :is => 5, :allow_blank => true
    end
    
    Topic.create("title" => "").valid? # => true
    Topic.create("title" => nil).valid? # => true

    message

    設定驗證錯誤時的訊息,若沒有提供則會用 Rails 內建的訊息。

    class Account < ActiveRecord::Base
      validates_uniqueness_of :email, :message => "你的 Email 重複了"
    end

    on

    可以設定只有新建立(:create)或只有更新時(:update)才驗證。預設值是都要檢查(:save)。

    class Account < ActiveRecord::Base
      validates_uniqueness_of :email, :on => :create
    end

    整合寫法

    在 Rails3 之後支援以下的整合寫法:

    validates :name,  :presence => true, 
                      :length => {:minimum => 1, :maximum => 254}
                   
    validates :email, :presence => true, 
                      :length => {:minimum => 3, :maximum => 254},
                      :uniqueness => true,
                      :email => true

    如果需要客製化錯誤訊息的話:

    validates :name,  :presence => { :message => "不能空白" } , 
                      :length => {:minimum => 1, :maximum => 254, :message => "長度不正確" }

    如何自定 validation?

    使用 validate 方法傳入一個同名方法的 Symbol 即可。

    validate :my_validation
    
    private
    
    def my_validation
        if name =~ /foo/
            errors[:name] << "can not be foo"
        elsif name =~ /bar/
            errors[:name] << "can not be bar"
        elsif name == 'xxx'
            errors[:base] << "can not be xxx"
      	end
    end

    在你的驗證方法之中,你會使用到 errors 來將錯誤訊息放進去,如果這個錯誤是因為某一屬性造成,我們就用那個屬性當做 errors 的 key,例如本例的 :name。如果原因不特別屬於某一個屬性,照慣例會用 :base。

    回呼 Callback

    在介紹過驗證之後,接下來讓我們來看看回呼。回呼可以在Model資料的生命週期,掛載事件上去,例如我們可以在資料儲存進資料庫前,做一些修正,或是再儲存成功之後,做一些其他動作。回呼大致可以分成三類:

    1. Validation驗證前後 2. 在儲存進資料庫前後 3. 在從資料庫移除前後

    以下是當一個物件儲存時的流程,其中1~7就是回呼可以觸發的時機:

    • (-) save
    • (-) valid
    • (1) before_validation
    • (-) validate
    • (2) after_validation
    • (3) before_save
    • (4) before_create
    • (-) create
    • (5) after_create
    • (6) after_save
    • (7) after_commit

    另外還有after_rollbackafter_commit這兩個回呼和Transaction交易有關。

    來看一個範例:設定一個before_validation回呼設定預設值,其中的setup_default方法會在資料驗證前執行:

    class Event < ActiveRecord::Base
    
        before_validation :setup_default
    
        protected
    
        def setup_default
            self.is_public ||= true
        end
    end
    1. 回呼的方法最好放在protectedprivate下,確保只能由Model內部呼叫。
    2. before_validationbefore_save的差別在於前者會經過Validation驗證。
    3. 請避免before_開頭的回呼方法中,最後運算的結果不小心回傳false。這樣會中斷儲存程序。如果不確定的話,請回傳return true。這算是常見的地雷,而且不容易除錯(你會發現資料莫名地無法儲存成功)。
  • 相关阅读:
    Centos 安装TensorFlow
    Centos 编译TensorFlow C/C++库 libtensorflow.so libtensorflow_framework.so
    机器学习常用库速查表 文献收藏
    Jupyter 取消括号自动匹配
    Sklearn 错误 No module named 'cross_validation' 错误 No module named 'mode_selection'
    Centos 设置iptables端口转发 “Unit iptables.service could not be found”错误
    三角函数tan、arctan与双曲函数tanh 学习笔记
    Moco框架
    fake_useragent
    chardet
  • 原文地址:https://www.cnblogs.com/rywx/p/2525013.html
Copyright © 2011-2022 走看看