# encoding: UTF-8 require File.expand_path("./helper", File.dirname(__FILE__)) class Event < Ohm::Model attribute :name attribute :place attribute :capacity index :name index :place def validate assert_format(:name, /^\w+$/) end end class Validatable attr_accessor :name include Ohm::Validations end # A new model with validations scope do setup do Event.new end # That must have a present name scope do test "not be created if the name is never assigned" do |event| event.create assert event.new? end test "not be created if the name assigned is empty" do |event| event.name = "" event.create assert event.new? end test "be created if the name assigned is not empty" do |event| event.name = "hello" event.create assert event.id end # And must have a name with only \w+ scope do test "not be created if the name doesn't match /^\w+$/" do |event| event.name = "hello-world" event.create assert event.new? end end end # That must have a numeric attribute :capacity scope do test "fail when the value is nil" do |event| def event.validate assert_numeric :capacity end event.name = "foo" event.place = "bar" event.create assert event.new? assert [[:capacity, :not_numeric]] == event.errors end test "fail when the value is not numeric" do |event| def event.validate assert_numeric :capacity end event.name = "foo" event.place = "bar" event.capacity = "baz" event.create assert event.new? assert [[:capacity, :not_numeric]] == event.errors end test "succeed when the value is numeric" do |event| def event.validate assert_numeric :capacity end event.name = "foo" event.place = "bar" event.capacity = 42 event.create assert event.id end end # That must have a unique name scope do test "fail when the value already exists" do |event| def event.validate assert_unique :name end Event.create(:name => "foo") event.name = "foo" event.create assert event.new? assert [[:name, :not_unique]] == event.errors end end # That must have a unique name scoped by place scope do test "fail when the value already exists for a scoped attribute" do |event| def event.validate assert_unique [:name, :place] end Event.create(:name => "foo", :place => "bar") event.name = "foo" event.place = "bar" event.create assert event.new? assert [[[:name, :place], :not_unique]] == event.errors event.place = "baz" event.create assert event.valid? end end # That defines a unique validation on a non indexed attribute scope do test "raise ArgumentError" do |event| def event.validate assert_unique :capacity end assert_raise(Ohm::Model::IndexNotFound) do event.valid? end end end end # An existing model with a valid name scope do setup do event = Event.create(:name => "original") end # That has the name changed scope do test "not be saved if the new name is nil" do |event| event.name = nil event.save assert false == event.valid? assert "original" == Event[event.id].name end test "not be saved if the name assigned is empty" do |event| event.name = "" event.save assert false == event.valid? assert "original" == Event[event.id].name end test "be saved if the name assigned is not empty" do |event| event.name = "hello" event.save assert event.valid? assert "hello" == Event[event.id].name end end end # Validations module scope do setup do Validatable.new end # assert scope do test "add errors to a collection" do |target| def target.validate assert(false, "Something bad") end target.validate assert ["Something bad"] == target.errors end test "allow for nested validations" do |target| def target.validate if assert(true, "No error") assert(false, "Chained error") end if assert(false, "Parent error") assert(false, "No chained error") end end target.validate assert ["Chained error", "Parent error"] == target.errors end end # assert_present scope do setup do target = Validatable.new def target.validate assert_present(:name) end target end test "fail when the attribute is nil" do |target| target.validate assert [[:name, :not_present]] == target.errors end test "fail when the attribute is empty" do |target| target.name = "" target.validate assert [[:name, :not_present]] == target.errors end end end