require 'glue/validation' module Glue # Extend the Validation methods defined in glue/validation.rb with # extra db related options. module Validation # Encapsulates a list of validation errors. class Errors cattr_accessor :not_unique, 'The value is already used' cattr_accessor :invalid_relation, 'Invalid relations' end module ClassMethods # Validates that the given field(s) contain unique values. # Ensures that if a record is found with a matching value, # that it is the same record, allowing updates. # # The Og libraries are required for this methdod to # work. You can override this method if you want to # use another OR mapping library. # # === Example # # validate_unique :param, :msg => 'Value is already in use' #-- # TODO: :unique should implicitly generate # validate_unique. #++ def validate_unique(*params) c = { :on => :save } c.update(params.pop) if params.last.is_a?(Hash) for name in params do c[:msg] ||= "#{self.name} with this #{name} already exists" code = %{ others = obj.class.send(:find_by_#{name}, obj.send(:#{name})) unless others.empty? if (others.size != 1) or (others[0].oid != obj.oid) errors.add(:#{name}, '#{c[:msg]}') end end } validations! << [code, c[:on]] end end # Validate the related object or objects. Works # with all relations. def validate_related(*params) c = { :msg => Glue::Validation::Errors.invalid_relation, :on => :save } c.update(params.pop) if params.last.is_a?(Hash) for name in params code = %{ unless (obj.#{name}.is_a?(Array) ? obj.#{name} : [obj.#{name}]).inject(true) { |memo, obj| (obj.nil? or obj.valid?) and memo } errors.add(:#{name}, '#{c[:msg]}') end; } validations! << [code, c[:on]] end end alias_method :validate_associated, :validate_related end end end # * George Moschovitis # * Bryan Soto