nandosola / dilithium-rb

A tiny framework to power your enterprise-ish stuff in Ruby
BSD 3-Clause "New" or "Revised" License
3 stars 3 forks source link

Define generic validations #22

Open mcamou opened 10 years ago

mcamou commented 10 years ago

It would be useful to be able to define common validations on attributes/references. Things like:

mcamou commented 10 years ago

Validating an attribute's formatting, range, length, etc. will be done by creating a class that extends one of the following types:

String
Integer
Float
DateTime
TrueClass
FalseClass

(which are defined in BasicAttributes::GENERIC_TYPES). The validation will be done in the constructor. Currently we must extend one of the above classes directly, extending a subclass is not supported at the moment (see BaseEntity.attribute and possibly other places in the code)

Invariants will be executed any time a setter is invoked for the specified attribute(s). Proposed usage example:

class TelephoneNumber < String
  def init(s)
    raise ArgumentError, "Malformed telephone number" unless correct_format?(s)
    super(s)
  end

  def correct_format?(s)
    # Validate correct number format
  end
end

class Trip < BaseEntity
  attribute :start_date, Date
  attribute :end_date, Date
  attribute :destination, Country
  reference_list :stops, Country
  attribute :code, String
  reference_list :companions, Person
  attribute :phone, TelephoneNumber

  invariant :start_date, :end_date do | sd, ed |
    raise ArgumentError, "Start date must be less than end date" unless sd < ed
  end

  invariant :start_date do | sd |
    raise ArgumentError, "Start date must be after today" unless sd >= Date.new
  end

  invariant :destination, MANDATORY # Class variable assigned to a lambda

  invariant :stops, count_exactly(2) # Method that returns a lambda to do the validation. Count_* implies a *_list attribute
  invariant :companions, count_between(0, 4)

  invariant :code, UNIQUE # Call the Repository and check there's no other entity with the same value for this attribute
end

Invariants will be checked in the UoW code, we will not use Sequel's restrictions when generating the schema. That means we need to remove special processing of :mandatory in GenericAttributes and in schemify. Note that we're not indicating anything to do with indexes and such since schemify is only a utility.

mcamou commented 10 years ago

There needs to be a way to defer validations during the execution of a block of code (I.e., changing both the start and end dates). I.e:

a_trip.update do |t|
  t.start_date = xxx
  t.end_date = yyy
end