<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 4.4 模型中的校驗(Validates) ## 概要: 本課時講解 Model 中的屬性校驗方法,以及在頁面上顯示校驗失敗信息。 ## 知識點: 1. validates 方法 1. errors 1. helpers 1. I18n 1. Rspec ## 正文 ### 4.4.1 數據校驗 我們將數據保存到數據庫的時候,可以有兩種數據校驗,一種是在數據庫中設定驗證規則,一種是在程序中進行校驗。 Rails 為我們提供了方便的屬性校驗。在 [4.2.1 兩個 Gem] 一節,我們介紹了ActiveRecord 中包含的兩個 Gem,在數據查詢和關聯關系中,我們主要使用的是 arel。數據校驗時,我們使用的是 [ActiveModel](https://github.com/rails/rails/tree/master/activemodel)。 ### 4.4.2 校驗方法 #### 4.4.2.1 常用的校驗方法 | 方法 | 含義 | 例子 | |-----|-----|-----| | acceptance | 必須接受選項,比如注冊條款(必須同意) | validates :terms_of_service, acceptance: true | | validates_associated | 校驗關聯資源,僅在關聯的一端使用即可,避免循環校驗 | [1] | | confirmation | 填寫確認 | validates :email, confirmation: true | | exclusion | 排除內容,如某些保留關鍵詞不允許注冊使用 | validates :subdomain, exclusion: { in: %w(www us ca jp), message: "%{value} is reserved." } | | format | 格式化,如郵件格式 | validates :legacy_code, format: { with: /\A[a-zA-Z]+\z/, message: "only allows letters" } | | inclusion | 包含內容,如特定的輸入內容 | validates :size, inclusion: { in: %w(small medium large), message: "%{value} is not a valid size" } | | length | 內容長度 | validates :name, length: { minimum: 2 } [2] | | numericality | 僅數字 | validates :points, numericality: true | | presence | 必填,使用 `blank?` 方法判斷 | validates :name, :login, :email, presence: true [3] [4] | | absence | 必空,使用 `present?` 判斷 | [5] | | uniqueness | 唯一 | validates :email, uniqueness: true [6] | 注解: [1] ~~~ class Library < ActiveRecord::Base has_many :books validates_associated :books end ~~~ [2] 有其他幾個選項: :minimum,最短長度:maximum,最大長度:in/:within,在某范圍:is,指定長度 [3] 也可以應用在關聯關系上,如: ~~~ class LineItem < ActiveRecord::Base belongs_to :order validates :order, presence: true end ~~~ 為了保持內存中引用相同地址,需要在 Order 上使用 inverse_of: ~~~ class Order < ActiveRecord::Base has_many :line_items, inverse_of: :order end ~~~ [4] 進入 console,做個試驗: ~~~ false.blank? => true true.blank? => false ~~~ 所以,使用 presence 判斷 true/false 屬性時,需要這樣使用: ~~~ validates :boolean_field_name, presence: true validates :boolean_field_name, inclusion: { in: [true, false] } validates :boolean_field_name, exclusion: { in: [nil] } ~~~ [5] 和 presence 一樣,需要使用 inverse_of 限定關聯關系,并且在判斷 true/false 時: ~~~ validates :boolean_field_name, absence: true validates :boolean_field_name, exclusion: { in: [true, false] } ~~~ [6] uniqueness 有兩個重要的選項。 scope,比如: ~~~ validates :number, uniqueness: { scope: : company_id } ~~~ 保存到數據庫前,uniqueness 會先檢索數據庫是否已經存在該字段的值,scope 可以使檢索時附帶一個字段,比如:不同的公司,可以有相同的訂單號,而同公司訂單號必須唯一。 ~~~ validates :name, uniqueness: { case_sensitive: false } ~~~ 默認是 true,區分大小寫。改為 false,可不區分大小寫。 #### 4.4.2.2 校驗方法中的選項 在檢驗方法 validates 中,可以使用幾個選項: | 選項 | 含義 | 例子 | |-----|-----|-----| | allow_nil | 是否允許為 nil | validates :size, allow_nil: true | | allow_blank | 是否允許為 blank?,為 false 時,不可填寫 `""`, `false`, `nil` | validates :title, allow_blank: true | | message | 自定義錯誤信息 | validates :subdomain, exclusion: { in: %w(www us ca jp), message: "%{value} 為保留關鍵詞" } | | on | 選擇在 create 或 update 上使用校驗 | validates :email, uniqueness: true, on: :create | | strict | 校驗失敗時拋出異常,或自定異常類 | validates :name, presence: { strict: true } [1] | 注解 [1] 自定義異常類 ~~~ class Person < ActiveRecord::Base validates :token, presence: true, uniqueness: true, strict: TokenGenerationException end Person.new.valid? => TokenGenerationException: Token can't be blank ~~~ ### 4.4.3 觸發校驗方法 在將數據保存到數據庫的時候,有些方法,會觸發校驗,有些則直接發送數據庫 sql 命令,不觸發校驗。 #### 4.4.3.1 觸發校驗的方法 - create - create! - save - save! - update - update! `!` 結尾的方法,在校驗失敗時,會拋出異常。`save(validate: false)` 可以跳過 save 方法的校驗。 #### 4.4.3.2 不觸發校驗的方法 - decrement! - decrement_counter - increment! - increment_counter - toggle! - touch - update_all - update_attribute - update_column - update_columns - update_counters #### 4.4.3.2 有條件的校驗 我們可以在校驗中增加 `:if` 或 `:unless` 條件判斷。 ~~~ class Order < ActiveRecord::Base validates :card_number, presence: true, if: :paid_with_card? def paid_with_card? payment_type == "card" end end ~~~ 這里使用的是方法判斷,也可以直接使用字符串,比如: ~~~ class Person < ActiveRecord::Base validates :surname, presence: true, if: "name.nil?" end ~~~ 或者一個代碼塊: ~~~ class Account < ActiveRecord::Base validates :password, confirmation: true, unless: Proc.new { |a| a.password.blank? } end ~~~ #### 4.4.3.3 `valid?` 方法 `valid?` 和 `invalid?` 方法會觸發校驗。校驗成功時返回 true,失敗時,返回 false,并且將校驗信息放入 errors 類。訪問 `order.errors`,返回的是 `ActiveModel::Errors` 實例,它的代碼在 [這里](https://github.com/rails/rails/blob/master/activerecord/lib/active_record/errors.rb)。 ### 4.4.4 Errors 對象 校驗失敗時,model.errors 會保存入校驗的屬性和失敗原因。我們可以通過幾個方法,從 errors 實例中拿到具體的信息。 ~~~ % model.errors.messages => {:number=>["must be blank"]} ~~~ `messages` 方法返回的是 hash 結構的信息,key 是校驗的屬性。 ~~~ % model.errors.full_messages => ["Number can't be blank", ...] ~~~ `full_messages` 方法返回 Array 結構的完整錯誤信息。這在資源編輯的 form 頁面,可以整體輸出錯誤信息,不過它沒有具體到某個屬性上。對于某個屬性,我們可以使用 `errors[:number]` 來讀取: ~~~ % order.errors[:number] => ["can't be blank"] ~~~ 在某些時候,我們需要添加自己的信息,可以使用: ~~~ order.errors.add(:number, "訂單號不能含有 !@#%*()_-+= 等字符") ~~~ 如果添加的信息,并不一定是某個具體屬性,可以添加到errors 的 base 中: ~~~ order.errors.add(:base, "訂單格式不正確") ~~~ `order.errors.clear`,可以清理掉所有信息. ### 4.4.5 使用中文的校驗信息 我們已經注意到了,目前所有的校驗信息都是英文的,雖然可以在自定義信息里寫入中文(Not Rails Style),但是我們可以利用 Rails 提供的 I18n gem,實現文本內容的漢化。這包括異常信息。 我們先修改一下 I18n 文件加載地址,在 application.rb 文件里,我們找到這一段: ~~~ config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**/*.{rb,yml}').to_s] config.i18n.default_locale = :"zh-CN" ~~~ 這樣會加載我們在 config/locales 中的全部語言包文件(注意,這里使用的是 `**/*.{rb,yml}`)。 我們創建語言包,為了便于維護,我在這里做了細分,大家可以在 [這里](https://github.com/liwei78/rails-practice-code/tree/master/chapter_4/shop/config/locales) 查看。 進到終端里,測試下: ~~~ % product = Product.new % product.valid? => false % product.errors.full_messages => ["名稱不能為空字符"] ~~~ 在后面的章節里,會專門講解 I18n 的問題,如果不像本例子中自己添加語言包,也可以安裝 [rails-i18n](https://github.com/svenfuchs/rails-i18n) 這個 gem 來解決問題。 #### 4.4.5.1 頁面中顯示錯誤信息 為了讓頁面集中的顯示錯誤信息,我們在 form 中使用了局部模板,把校驗失敗的內容顯示在輸入框的頂部。 ~~~ <% if @product.errors.any? %> <div id="error_expl" class="panel panel-danger"> <div class="panel-heading"> <h3 class="panel-title"><%= pluralize(@product.errors.count, "error") %> prohibited this product from being saved:</h3> </div> <div class="panel-body"> <ul> <% @product.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> </div> </div> <% end %> ~~~ `full_messages` 返回 Array 的校驗信息,我們只需循環顯示即可。如果想在輸入框旁邊顯示信息,可以單獨讀取該屬性,比如 `@product.errors[:name]`,可以放到一個 jquery 的 tooltip 中。 不過,這種信息是要提交到服務器端處理后,才能顯示出來的。為了在頁面端就顯示校驗,我們還是需要 jQuery 插件的。 #### 4.4.5.2 jQuery 校驗 Form 校驗的時候,有兩個插件較常用。 [http://jqueryvalidation.org/](http://jqueryvalidation.org/) 是較常用的一個,也很簡單,但是需要在頁面上顯示中文,還需要它的中文插件。 <%= javascript_include_tag 'spree/jquery.validate/localization/messages_zh' %> 中文語言包的源碼在[這里] ([https://github.com/jzaefferer/jquery-validation/blob/master/src/localization/messages_zh.js)。](https://github.com/jzaefferer/jquery-validation/blob/master/src/localization/messages_zh.js)。) 如果不需要校驗具體信息,因為我們已經使用了 bootstrap 這個前端框架,所以我們可以使用它的表單校驗:[http://bootstrapvalidator.com](http://bootstrapvalidator.com) 它會按照 bootstrap 的方式,將輸入框加上圖標,使校驗更加直觀。當然,你還可以讀取具體的屬性信息,放到 bootstrap 的 tooltip 里。 ### 4.4.6 Rspec 和上一張的關聯關系一樣,[shoulda-matchers](https://github.com/thoughtbot/shoulda-matchers#activemodel-matchers) 也提供了方便的校驗測試框架。 ~~~ describe Product do it { should validate_presence_of(:name) } end ~~~ 現在我們給 Model 增加了越來越多的內容,為了方便找到方法,我們可以對代碼進行一個簡單的分割,這樣就不會在測試和對應的業務代碼間切換浪費時間了。 ~~~ # extends ................................................................... # includes .................................................................. # security .................................................................. # relationships ............................................................. # validations ............................................................... # callbacks ................................................................. # scopes .................................................................... # additional config ......................................................... # class methods ............................................................. # public instance methods ................................................... # protected instance methods ................................................ # private instance methods .................................................. ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看