私のフォームには、混合数 (38 1/2 など) を受け入れて小数に変換できる仮想属性があります。何かが爆発した場合にエラーをスローする検証もいくつかあります (これを正しく処理しているかどうかはわかりません)。
class Client < ActiveRecord::Base
attr_accessible :mixed_chest
attr_writer :mixed_chest
before_save :save_mixed_chest
validate :check_mixed_chest
def mixed_chest
@mixed_chest || chest
end
def save_mixed_chest
if @mixed_chest.present?
self.chest = mixed_to_decimal(@mixed_chest)
else
self.chest = ""
end
end
def check_mixed_chest
if @mixed_chest.present? && mixed_to_decimal(@mixed_chest).nil?
errors.add :mixed_chest, "Invalid format. Try 38.5 or 38 1/2"
end
rescue ArgumentError
errors.add :mixed_chest, "Invalid format. Try 38.5 or 38 1/2"
end
private
def mixed_to_decimal(value)
value.split.map{|r| Rational(r)}.inject(:+).to_d
end
end
ただし、仮想属性を持つウィングスパンという別の列を追加したいのですが、これ:mixed_wingspan
を抽象化して再利用する方法がわかりません。数十の入力に対して同じ変換/検証を使用します。
accept_mixed :chest, :wingspan ...
理想的には、カスタムゲッター、セッター、検証などを処理するようなものを使用したいと思います.
編集:
メタプログラミングで機能を再作成しようとしていますが、いくつかの場所で苦労しています:
def self.mixed_number(*attributes)
attributes.each do |attribute|
define_method("mixed_#{attribute}") do
"@mixed_#{attribute}" || attribute
end
end
end
mixed_number :chest
これにより、チェストが「@mixed_chest」に設定されます。@mixed_chest
上記のようにインスタンス変数を取得しようとしています。