Class: ActiveModel::Validations::NestedUniquenessValidator

Inherits:
EachValidator
  • Object
show all
Defined in:
lib/validates_nested_uniqueness.rb

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ NestedUniquenessValidator

Returns a new instance of NestedUniquenessValidator.



8
9
10
11
12
13
# File 'lib/validates_nested_uniqueness.rb', line 8

def initialize(options)
  super(options)
  @klass =        get_class_name(options[:scope])
  @association =  options[:association]
  @message =      options[:message]
end

Instance Method Details

#get_child_count(parent, record, attribute) ⇒ Object

Searches the parent for duplicate children. A duplicate is defined as another child with an equivilant attribute.



50
51
52
53
54
# File 'lib/validates_nested_uniqueness.rb', line 50

def get_child_count(parent, record, attribute)
  count = parent.try(@association).to_a.count { |r| 
    r[attribute] == record[attribute] 
  }
end

#get_class_name(sym) ⇒ Object

Gets a class name from a symbol.



32
33
34
# File 'lib/validates_nested_uniqueness.rb', line 32

def get_class_name(sym)
  sym.to_s.split('_').collect(&:capitalize).join
end

#get_parent(record) ⇒ Object

Searches ObjectSpace for the parent object of record.

It looks at all objects for the given class, then checks



39
40
41
42
43
44
45
# File 'lib/validates_nested_uniqueness.rb', line 39

def get_parent(record)
  parent = nil
  ObjectSpace.each_object(eval(@klass)) { |r| 
    parent = r if r.try(@association).include?(record) 
  }
  parent
end

#validate_each(record, attribute, value) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/validates_nested_uniqueness.rb', line 15

def validate_each(record, attribute, value)
  
  # working on trying to use conventions to determine association
  # also, if has only one belongs_to, can use that as a default.
  #puts record.class.name.underscore.to_sym
  #puts(eval(@klass).reflect_on_association(record.class.name.underscore.to_sym))
  
  if parent = get_parent(record)
    if get_child_count(parent, record, attribute) > 1
      record.errors.add(attribute, 
                        @message, 
                        :value => record[attribute] )
    end
  end
end