🧙♀️
SimpleDelegator を使ってモデルに Warnings を追加してみる
はじめに
先日、データの登録フォームで入力した値に対して警告メッセージを表示する、という実装が必要になりました。
-
入力した内容が条件に合致していない場合は、警告メッセージを表示する
-
入力した内容が条件に合致していない場合でも、データの登録処理は可能にする
- バリデーションエラーとは分けて管理したい
実装方法はいろいろ考えられると思いますが、SimpleDelegator
を使った方法を検討してみたので、メモとして。
前提
$ ruby -v
ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19]
$ rails -v
Rails 6.1.0
SimpleDelegator
「委譲」を行うためのクラスです。委譲先に指定されたオブジェクトへメソッドの実行を委譲します。
使い方
require 'delegate'
class Foo < SimpleDelegator
def dance
pp "🕺"
end
end
class Bar
def walk
pp "🚶"
end
end
foo = Foo.new(Bar.new)
foo.dance
=> "🕺"
foo.walk
=> "🚶"
SimpleDelegator
で Warning を実装する
例えば User オブジェクトの Warning を取得する場合の実装です。
class UserWarnings < SimpleDelegator
include ActiveModel::Validations
validate :validates_name
NG_NAMES = %w[dummy ng_word]
def initialize(record)
super
valid?
end
def warnings; errors; end
def validates_name
errors.add(:base, '別の名前を設定してね') if NG_NAMES.include?(name)
end
end
class User < ApplicationRecord
def warnings
@warnings ||= UserWarnings.new(self).warnings
end
end
> user = User.new(name: 'dummy')
> user.warnings.full_messages
=> ["別の名前を設定してね"]
Warning の実体は ActiveModel::Errors
なので、full_messages
などのメソッドも使えます。
Discussion