コード日進月歩

しんくうの技術的な小話、メモ、つれづれ、など

ActiveRecordなどのoption類で複数の対象に同一のものをつけたいときはwith_optionsというものがある

こういうまとめかたもあるとは知らなかったのでメモ、原理は参考リンク参照

環境

$ bin/rails -v
Rails 5.2.2

やり方

with_options で囲む

下記のようなモデルがあったとする

# == Schema Information
#
# Table name: messages
#
#  id         :bigint(8)        not null, primary key
#  name       :string(255)
#  user_id    :integer
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

class Message < ApplicationRecord
  belongs_to :user
end

user_idが偶数のときだけ name は10文字以上、12文字以下にしたいとしたとき、下記のように書ける

# == Schema Information
#
# Table name: messages
#
#  id         :bigint(8)        not null, primary key
#  name       :string(255)
#  user_id    :integer
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

class Message < ApplicationRecord
  belongs_to :user

  # user_idが偶数のときだけ10文字以上、12文字以下制限がかかる
  validates :name,length: { minimum: 10 }, if: :user_id_even_number?
  validates :name,length: { maximum: 12 }, if: :user_id_even_number?

  def user_id_even_number?
    (user_id % 2) == 0
  end
end

if: :user_id_even_number? の部分のオプション指定が重複しているので、ここはまとめることができる

# == Schema Information
#
# Table name: messages
#
#  id         :bigint(8)        not null, primary key
#  name       :string(255)
#  user_id    :integer
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

class Message < ApplicationRecord
  belongs_to :user

  # user_idが偶数のときだけ10文字以上、12文字以下制限がかかる
  with_options(if: :user_id_even_number?) do |mes|
    mes.validates :name, length: {minimum: 10}
    mes.validates :name, length: {maximum: 12}
  end

  def user_id_even_number?
    (user_id % 2) == 0
  end
end

参考サイト