(Rails) Modelクラスでの条件分岐
ビジネスバンクグループ エンジニア の高橋 慶太です。
今回は、RailsのModelクラス内で実施するバリデーションについて、ある条件の時だけバリデーションを行いたい場合の方法について書きたいと思います。
if、unless文
if、unless文を用いて、ある条件の場合のみバリデーションを実行する場合、以下のように記述します。
class Sample < ActiveRecord::Base
# name項目に値が入力されている場合のみ、8〜32桁の範囲内かどうかの入力チェックを行う。
# if文で書く場合
# 最小文字数
validates :name, length: { minimum: 8 }, if: "name.present?"
# 最大文字数
validates :name, length: { maximum: 32 }, if: "name.present?"
# unless文で書く場合
# 最小文字数
validates :name, length: { minimum: 8 }, unless: "name.blank?"
# 最大文字数
validates :name, length: { maximum: 32 }, unless: "name.blank?"
# 下記のように、まとめて書くこともできます
with_options if: ":name.present?" do |model|
model.validates :name, length: { minimum: 8 }
model.validates :name, length: { maximum: 32 }
end
end
:on
1つのModelに対して複数の箇所で登録処理などを行っている場合に、
箇所によってバリデーションを行う/行わないを制御したい場合があります。
このような場合、:onを用いることで制御することができます。
class SampleModel < ActiveRecord::Base
# 最大文字数
validates :name, length: { maximum: 32 }, on: :execute_validation
# 最小文字数
validates :name, length: { minimum: 1 }, on: :execute_validation
end
class SampleService
def create_with_validation
model = SampleModel.new
model.name = "test"
# saveメソッドの引数に「:execute_validation」を指定しているため、
# modelクラスの「on: :execute_validation」指定されているバリデーションが実行されます
model.save!(:execute_validation)
end
end
(補足)RSpecを使ったテストの記述
:onの記述についてRSpecを使ってテストする場合、以下のように記述することでテストすることができます。
describe SampleModel do
describe "#validate" do
# nameに33桁を指定
let(:model) { build :sample_model, name: "123456789012345678901234567890123" }
it "when name is longer than 32" do
# errors_onメソッドの引数にcontextの指定をすることで:onのテストが可能
expect(model).to have(1).errors_on(:name, context: :execute_validation)
end
end
end
エンジニア募集中!
ビジネスバンクグループではエンジニアを募集中しています。
弊社が採用しているテクノロジや開発環境に興味を持った方は、 ここから是非エントリー を!