Custom Validation Methodを作ってみた

Rails 2.3.2

やっとrailsの勉強を始めた。もちろんrubyも初心者。とっかかりに 実践Rails を読みながらやったんだけど、最初は何がなんだかわからなくて、本を間違えたなーって思った。だけど単純なことはgoogleで調べればわかるのでちょうどよい本な気もした。この本のおかげでソースの見方や読み方がどうにかわかったきた気がする。

で、 ActiveRecord で belongs_to で指定した参照先が存在することをチェックしたいなーって思ったんだけど、validates_associated はなんか違うし、適切な validates_〜 が見つけることができなかったので、勉強をかねて作ってみることに。

http://guides.rubyonrails.org/activerecord_validations_callbacks.html#creating-custom-validation-methods
http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#M002104

http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#M002113
ここらへんのソースを参考にしたけど、 validates_〜のソースはすべて参考になりそう。

config/initializers/my_validators.rb を作成して以下の内容を記述。

#
# 独自で作成した validation methods
#
ActiveRecord::Base.class_eval do
  #
  # 参照先のレコードが存在することを確認する
  #
  def self.validates_exists_reference_of(*attr_names)
    configuration = { :on => :save }
    configuration.update(attr_names.extract_options!)

    validates_each(attr_names, configuration) do |record, attr_name, value|
      id_name = "#{attr_name}_id"
      id = record.send(id_name)
      if !id.blank? and value.nil?
        record.errors.add(id_name, :exists_reference, :default => configuration[:message])
      end
    end
  end

end

そしてエラーメッセージを config/locales/en.yml に追加。

en:
  #
  # Add my validation methods error messages.
  #
  activerecord:
    errors:
      messages:
        exists_reference: "record is not found"

これで、下のような感じで使える。

class Item < ActiveRecord::Base
  belongs_to :category
  validates_exists_reference_of :category
end

見よう見真似でつくったので、 :polymorphic の場合の対応とかできてないけど、今の僕ではここら辺が限界。こんだけのことをするのに4時間くらいかかった。。。あと少し i18n につてもわかった気がする。日本語/英語の切替くらいはどうにかなりそうだー。

うーん、、、でも参照先が存在するかのチェックは普通にみんな使う気がするので、やっぱりあるきがするな、、、そこら辺をうまく調べれないのが、やっぱり初心者ってことだね。。。はやく調べるのが上手になりたいぜー。