- V
執行個體公開方法
validates_absence_of(*attr_names) 連結
驗證指定的屬性不存在(由 Object#present?
定義)。如果屬性是關聯,則關聯的物件也會被視為不存在,如果它被標記為要銷毀。
請參閱 ActiveModel::Validations::HelperMethods.validates_absence_of
以取得更多資訊。
來源:顯示 | 在 GitHub 上
# File activerecord/lib/active_record/validations/absence.rb, line 20 def validates_absence_of(*attr_names) validates_with AbsenceValidator, _merge_attributes(attr_names) end
validates_associated(*attr_names) 連結
驗證關聯的物件是否都有效。適用於任何類型的關聯。
class Book < ActiveRecord::Base
has_many :pages
belongs_to :library
validates_associated :pages, :library
end
警告:此驗證不得用於關聯的兩端。這樣做將導致循環依賴並造成無限遞迴。
注意:如果關聯尚未指定,此驗證不會失敗。如果您要確保關聯同時存在且保證有效,您還需要使用 validates_presence_of。
設定選項
-
:message
- 自訂錯誤訊息(預設為:「無效」)。 -
:on
- 指定此驗證處於活動狀態的內容。預設在所有驗證內容中執行nil
。您可以傳遞符號或符號陣列。(例如on: :create
或on: :custom_validation_context
或on: [:create, :custom_validation_context]
) -
:if
- 指定要呼叫的方法、程序或字串,以判斷驗證是否應發生(例如if: :allow_validation
,或if: Proc.new { |user| user.signup_step > 2 }
)。方法、程序或字串應傳回或評估為true
或false
值。 -
:unless
- 指定要呼叫的方法、程序或字串,以判斷驗證是否不應發生(例如unless: :skip_validation
,或unless: Proc.new { |user| user.signup_step <= 2 }
)。方法、程序或字串應傳回或評估為true
或false
值。
來源:顯示 | 在 GitHub 上
# File activerecord/lib/active_record/validations/associated.rb, line 54 def validates_associated(*attr_names) validates_with AssociatedValidator, _merge_attributes(attr_names) end
validates_length_of(*attr_names) 連結
驗證指定的屬性是否符合提供的長度限制。如果屬性是關聯,則標記為要銷毀的記錄不會被計算在內。
請參閱 ActiveModel::Validations::HelperMethods.validates_length_of
以取得更多資訊。
來源:顯示 | 在 GitHub 上
# File activerecord/lib/active_record/validations/length.rb, line 19 def validates_length_of(*attr_names) validates_with LengthValidator, _merge_attributes(attr_names) end
validates_numericality_of(*attr_names) 連結
透過嘗試使用 Kernel.Float
將指定屬性的值轉換為浮點數(如果 only_integer
為 false
)或將其套用至正規表示式 /\A[+\-]?\d+\z/
(如果 only_integer
設為 true
)來驗證該值是否為數字。Kernel.Float
精確度預設為欄位的精確度值或 15。
請參閱 ActiveModel::Validations::HelperMethods.validates_numericality_of
以取得更多資訊。
來源:顯示 | 在 GitHub 上
# File activerecord/lib/active_record/validations/numericality.rb, line 31 def validates_numericality_of(*attr_names) validates_with NumericalityValidator, _merge_attributes(attr_names) end
validates_presence_of(*attr_names) 連結
驗證指定的屬性不為空白(由 Object#blank?
定義)。如果屬性是關聯,如果關聯物件標記為要銷毀,則也視為空白。
class Person < ActiveRecord::Base
has_one :face
validates_presence_of :face
end
物件中必須有 face 屬性,且不能為空白或標記為要銷毀。
此驗證器委託 Active Model 進行存在驗證,並加入檢查以查看關聯物件是否標記為要銷毀。這可防止父物件成功驗證並儲存,然後刪除關聯物件,進而使父物件進入無效狀態。
請參閱 ActiveModel::Validations::HelperMethods.validates_presence_of
以取得更多資訊。
注意:如果使用關聯時,後者已指派但無效,此驗證不會失敗。如果您要確保關聯存在且有效,您還需要使用 validates_associated。
來源: 顯示 | 在 GitHub 上
# File activerecord/lib/active_record/validations/presence.rb, line 40 def validates_presence_of(*attr_names) validates_with PresenceValidator, _merge_attributes(attr_names) end
validates_uniqueness_of(*attr_names) 連結
驗證指定屬性的值在系統中是否唯一。對於確保只有一個使用者可以命名為「davidhh」很有用。
class Person < ActiveRecord::Base
validates_uniqueness_of :user_name
end
它也可以根據 :scope
參數驗證指定屬性的值是否唯一
class Person < ActiveRecord::Base
validates_uniqueness_of :user_name, scope: :account_id
end
甚至可以有多個範圍參數。例如,確保一位老師在特定課程中每學期只能在課表上出現一次。
class TeacherSchedule < ActiveRecord::Base
validates_uniqueness_of :teacher_id, scope: [:semester_id, :class_id]
end
也可以將唯一性約束限制為符合特定條件的一組記錄。在此範例中,驗證標題屬性的唯一性時,不會考慮已封存的文章
class Article < ActiveRecord::Base
validates_uniqueness_of :title, conditions: -> { where.not(status: 'archived') }
end
若要根據記錄的狀態建立條件,請定義條件可呼叫,並帶有一個參數,該參數將是記錄本身。此範例驗證標題對於出版年份是唯一的
class Article < ActiveRecord::Base
validates_uniqueness_of :title, conditions: ->(article) {
published_at = article.published_at
where(published_at: published_at.beginning_of_year..published_at.end_of_year)
}
end
建立記錄時,會執行檢查以確保資料庫中沒有記錄具有指定屬性(對應到欄位)的給定值。更新記錄時,會進行相同的檢查,但會忽略記錄本身。
設定選項
-
:message
- 指定自訂錯誤訊息(預設為:「已被使用」)。 -
:scope
- 用於限制唯一性約束範圍的一或多個欄位。 -
:conditions
- 指定要包含在WHERE
SQL 片段中的條件,以限制唯一性約束查詢(例如conditions: -> { where(status: 'active') }
)。 -
:case_sensitive
- 尋找完全相符。非文字欄位會忽略。預設行為會遵循預設資料庫校對規則。 -
:allow_nil
- 如果設為true
,當屬性為nil
時會略過此驗證(預設為false
)。 -
:allow_blank
- 如果設為true
,當屬性為空白時會略過此驗證(預設為false
)。 -
:if
- 指定要呼叫的方法、程序或字串,以判斷驗證是否應發生(例如if: :allow_validation
,或if: Proc.new { |user| user.signup_step > 2 }
)。方法、程序或字串應傳回或評估為true
或false
值。 -
:unless
- 指定要呼叫的方法、程序或字串,以判斷驗證是否不應發生(例如unless: :skip_validation
,或unless: Proc.new { |user| user.signup_step <= 2 }
)。方法、程序或字串應傳回或評估為true
或false
值。
並行性和完整性
將此驗證方法與 ActiveRecord::Base#save 搭配使用無法保證不會插入重複記錄,因為應用程式層級的唯一性檢查本質上容易發生競爭條件。例如,假設兩個使用者同時嘗試張貼留言,而留言的標題必須是唯一的。在資料庫層級,這些使用者執行的動作可能會以以下方式交錯
User 1 | User 2
------------------------------------+--------------------------------------
# User 1 checks whether there's |
# already a comment with the title |
# 'My Post'. This is not the case. |
SELECT * FROM comments |
WHERE title = 'My Post' |
|
| # User 2 does the same thing and also
| # infers that their title is unique.
| SELECT * FROM comments
| WHERE title = 'My Post'
|
# User 1 inserts their comment. |
INSERT INTO comments |
(title, content) VALUES |
('My Post', 'hi!') |
|
| # User 2 does the same thing.
| INSERT INTO comments
| (title, content) VALUES
| ('My Post', 'hello!')
|
| # ^^^^^^
| # Boom! We now have a duplicate
| # title!
解決此問題的最佳方法是使用 connection.add_index 為資料庫表格新增唯一索引。在極少數發生競爭條件的情況下,資料庫會保證欄位的唯一性。
當資料庫偵測到重複插入時,ActiveRecord::Base#save 會引發 ActiveRecord::StatementInvalid
例外。你可以選擇讓此錯誤傳播(這將導致顯示預設的 Rails 例外頁面),或者你可以捕捉它並重新啟動交易(例如,告訴使用者標題已存在,並要求他們重新輸入標題)。此技術也稱為 樂觀並行控制。
已套件化的 ActiveRecord::ConnectionAdapters 會透過擲出 ActiveRecord::RecordNotUnique
例外來區分唯一索引約束錯誤與其他類型的資料庫錯誤。對於其他轉接器,你必須解析(資料庫特定的)例外訊息才能偵測此類情況。
以下已套件化的轉接器會擲出 ActiveRecord::RecordNotUnique
例外
來源:顯示 | 在 GitHub 上
# File activerecord/lib/active_record/validations/uniqueness.rb, line 286 def validates_uniqueness_of(*attr_names) validates_with UniquenessValidator, _merge_attributes(attr_names) end