Sequel::Model におけるしなやかな validation
Ramazeさんと相性抜群な感じのORM(としても使える)ライブラリ Sequel は、Sequel::Model が Rails や DataMapper 的にモデルを定義できちゃったりしてもうとっても楽チンなわけです。しかし残念なことに現状 validation に関しては極めてイマイチではないかと思います。
Sequel::Model における validation は Rails流の validation を実現する Assistance というライブラリを採用しています。しかしこの Assistance が微妙、バージョンナンバーも 0.1.4 (2008-02-08) という感じでまだまだ熟成していないせいでしょうか、なんだか使い勝手が悪いというか予め決められた種類の validation しか出来ないので柔軟さに欠きます(ホントは出来なくはないのですが、極めて面倒っちいので嫌です)。そう思うなら Assistance にパッチ投げればいいじゃないの!というわけなんですが、とりあえず今回は Assistance に頼らない方法を書き残しておきます。
しなやかというか粗野な validation 方法
まず、sequel_model/validations.rb (sequel_model-0.4.1) は次のようになっております。
gem "assistance", ">= 0.1.2" # because we need Validations require "assistance" module Sequel class Model include Validation alias_method :save!, :save def save(*args) return false unless valid? save!(*args) end end end
てなわけだから、valid? を呼び出して、真偽値を返せば良いわけです。だので、次のようにして valid? を定義しましょう。
class Model < Sequel::Model def valid? ... # ここに条件をずらずらと書く、良いなら真を、ダメなら偽を返すこと end end
とっても簡単!というか、Sequel::Model は validator ライブラリを自由に選択可能にすべきだと思う(現状Assistance以外に存在を知りませんが)。これもなんとかしたいところです。(追記:NotNaughtyというのがあります、もう既に選択可能になっているようです)
ついでに Assistance で柔軟に
一応 validates_each を使えば極めて柔軟にやれます。
class Model < Sequel::Model validates_each :col do |obj, attr, val| obj.errors[attr] << 'はダメなんだってさ!' unless val.is_valid? end end
みたいな感じで書くと良さそうです。でも validates_each の each がすごく気になったり、その面倒そうなブロック引数はなに?とか思うわけです。これを粗野に書くとさらに次のようになります。
class Model < Sequel::Model validations[:col] << proc {|obj, attr, val| obj.errors['猫'] << 'が発情期で困ってます' unless val.is_valid? end end
とりあえず each は消えましたが、多分こうやって使われることは意図していないものと思われます。あとAssistanceはエラーメッセージの国際化とか考えてないからやっぱり困ると思います。なんとかしたいものです。
追記
validationライブラリはAssistanceしかないのかと思ったら、NotNaughtyってのがあるんだって!しかもSequelでも使えますというか、Seqeulで使われることを主眼に置いているような感じです(ちゃんとSequel::Pluginも用意されていて、簡単に使えます)。というわけで近日中にNotNaughtyを試してみたいと思います。