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 setting :invalid_relation, :default => "Undefined" setting :not_unique, :default => 'The value is already used' 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 method 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 = parse_config(params, :on => :save) params.each do |field| c[:msg] ||= "#{self.name} with this #{field} already exists" define_validation(:unique, field, c[:on]) do |obj| # What to do if value is nil? Right now it is an empty string, # which can need to be unique. value = obj.send(field) || '' others = [*obj.class.send("find_by_#{field}".to_sym, value)] unless others[0].nil? obj.errors.add(field, c[:msg]) if others.size > 1 or others[0].oid != obj.oid end end end end # Validate that a property relation is not nil. # This works for all relations. # # You should not put a validation in both related # classes, because it can cause infinite looping. # # The Og libraries are required for this method to # work. You can override this method if you want to # use another OR mapping library. # # === Example # # class Uncle # has_many :secrets, Secret # validate_related :secrets # end # # class Secret # belongs_to :uncle, Uncle # end def validate_related *params c = parse_config(params, :msg => Glue::Validation::Errors.invalid_relation, :on => :save ) params.each do |field| define_validation(:related, field, c[:on]) do |obj| value = obj.send(field) if value.members.length == 0 obj.errors.add(field, c[:msg]) else valid = value.members.inject do |memo, rel_obj| (rel_obj.nil? or rel_obj.valid?) and memo end obj.errors.add(field, c[:msg]) unless valid end end end end alias validate_associated validate_related end end end