iT邦幫忙

2021 iThome 鐵人賽

DAY 29
0
自我挑戰組

Ruby on Rails JS系列 第 29

Ruby on Rails ⾃訂驗證器 Validator

現有的驗證器不夠⽤嗎?有幾種⽅式可以⾃訂驗證器:

  1. 寫⼀個⽅法,掛到 validate ⽅法上:
class User < ActiveRecord::Base
validate :name_validator
private
def name_validator
unless name.starts_with? 'Ruby'
errors[:name] << "必須是 Ruby 開頭喔!"
end
end
end

注意:這個⽅法是 validate ,不是 validates 喔。
這種寫法滿簡單的,就是直接寫⼀個普通的⽅法(通常會放在 private 區塊),
當條件不符規定的時候,就在 errors 這個 Hash 裡⾯塞錯誤訊息。⽤起來就跟⼀
般的驗證器差不多:

$ bin/rails console
Running via Spring preloader in process 4628
Loading development environment (Rails 5.0.1)
>> user1 = User.new(name: "孫悟空")
=> #<User id: nil, name: "孫悟空", age: nil, email: nil, created_a
t: nil, updated_at: nil>
>> user1.save
(0.1ms) begin transaction
(0.3ms) rollback transaction
=> false
>> user1.errors.full_messages
=> ["Name 必須是 Ruby 開頭喔!"]
  1. 遵循 Rails 的驗證器規則:
    想寫出這樣的語法嗎?
class User < ActiveRecord::Base
validates :name, presence: true, begin_with_ruby: true
end

這個驗證器可以跟其它內建的驗證器⼀起混著使⽤,使⽤起來會更簡潔。要寫這樣
的驗證器需要符合 Rails Validator 的命名規則:

  1. 參數是 begin_with_ruby ,類別名稱則是 BeginWithRuby 加上
    Validator ,並繼承⾃ ActiveModel::EachValidator 類別。
    19 Model 驗證及回呼
    293
  2. 必須實作 validate_each ⽅法。
    寫起來⼤概像這樣:
class BeginWithRubyValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
unless value.starts_with? 'Ruby'
record.errors[attribute] << "必須是 Ruby 開頭喔!"
end
end
end

在使⽤的時候,就是跟⼀般的 validates 差不多:

class User < ActiveRecord::Base
validates :name, begin_with_ruby: true
end

在 rails console 試⼀下效果:

$ bin/rails console
Running via Spring preloader in process 4750
Loading development environment (Rails 5.0.1)
>> user1 = User.new(name: "孫悟空")
=> #<User id: nil, name: "孫悟空", age: nil, email: nil, created_a
t: nil, updated_at: nil>
>> user1.save
(0.1ms) begin transaction
(0.0ms) rollback transaction
=> false
>> user1.errors.full_messages
=> ["Name 必須是 Ruby 開頭喔!"]

參考資料

[為你自己學Ruby on Rails]https://railsbook.tw/chapters/08-ruby-basic-4.html


上一篇
Ruby on Rails Model 驗證及回呼
系列文
Ruby on Rails JS29

尚未有邦友留言

立即登入留言