moduleを追加するだけで任意のアクセッサーにbefore_action、after_actionが使えないクラスにフィルタリング機能を追加できるようにしてみる。
定義モジュール
filters.rb
module Filters
# attr_accessorを意識してメソッド定義にattrをつけたネーミングにしています。
# メソッド名と処理内容をhashで定義しメソッドを動的に作成
{
#指定したシンボルに対応するインスタンス変数をtrimする
attr_trim_filter: lambda { |value| value.strip },
# 指定したシンボルに対応するインスタンス変数を小文字に変換する
attr_downcase_filter: lambda { |value| value.downcase },
# 指定したシンボルに対応するインスタンス変数を大文字に変換する
attr_upcase_filter: lambda { |value| value.upcase }
}.each do |k, v|
define_method k do |*targets|
sym = k.to_s.sub /^attr\_/, ''
# 元のメソッドをalias chainで退避しておく
targets.each { |target|
self.new.send "#{target}=", nil
define_method "#{target}_with_#{sym}=" do |value|
next unless value.kind_of?(String)
send "#{target}_without_#{sym}=", v.call(value)
end
alias_method_chain "#{target}=", sym.to_sym
}
end
end
end
使用モジュール
user.rb
class User
extend Filters
attr_accessor :value_1, :value_2
# trimしたい項目を定義
attr_trim_filter :value_1, :value_2
end