Railsガイドにきちんと目を通して新しい知識を得る - バリデーション編 -

ドキュメントを読み込むのは大事、ということでRailsガイドを頭から読んでいく取り組みをしています。 各章ごとに、(Railsガイドにちゃんと書いてあるのに)知らなかった機能を雑にまとめていきます。

今回は、バリデーションの章です。  

railsguides.jp

upseart, upseart_all でバリデーションをスキップした更新

リンクはこちら

upsertというメソッドを知らなかったです。
特定の条件を満たすレコードがある場合はupdate, ない場合はinsertを行なってくれるメソッドのようです。
バリデーションをスキップするなど注意は必要ですが、ピッタリな使い道ができるケースもありそうです。

Product.upsert({ id: 4, price: 100 }, unique_by: :id)
# => idが4のレコードがあれば、priceを100に更新する。
# => idが4のレコードがなければ、新しく、idが4, priceが100のレコードを作成する

バリデーションメッセージのカスタマイズでオブジェクトとデータの引数を持つProcを渡せる

リンクはこちら

Stringを渡すことが多いと思うので、使う機会は限定的かもしれませんが、どこかで使えるかもと思いました。

class Product < ApplicationRecord
  validates :price, uniqueness: {
    scope: :name,
    message: -> (object, data) do
      "#{object.name}という商品名の#{data[:value]}円の商品は既に登録済み"
    end
  }
end
Product.create(name: 'sample', price: 100) # レコードを作成
product = Product.new(name: 'sample', price: 100)
product.valid?
# => false
product.errors.messages
# => {:price=>["sampleという商品名の100円の商品は既に登録済み"]}

# 上記バリデーションで、
# object には #<Product:0x0000000109bfd8d0 id: nil, created_at: nil, updated_at: nil, price: 100, name: "sample">
# data には {:model=>"Product", :attribute=>"Price", :value=>100}
# が入っている

strict: trueでvalid?などで例外を発生させる

リンクはこちら

valid?でfalseじゃなくて例外を返したいときが、想像しきれなかったのと、「?」で終わるメソッドで例外が返ってくるのがちょっと違和感がありました。

validates :name, presence: { strict: true }