Class: ActiveRecord::Validations::GlobalizedUniquenessValidator

Inherits:
ActiveModel::EachValidator
  • Object
show all
Defined in:
lib/active_record/validations/globalized_uniqueness.rb

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ GlobalizedUniquenessValidator

Returns a new instance of GlobalizedUniquenessValidator.



6
7
8
# File 'lib/active_record/validations/globalized_uniqueness.rb', line 6

def initialize(options)
  super(options.reverse_merge(:case_sensitive => true))
end

Instance Method Details

#setup(klass) ⇒ Object

Unfortunately, we have to tie Uniqueness validators to a class.



11
12
13
# File 'lib/active_record/validations/globalized_uniqueness.rb', line 11

def setup(klass)
  @klass = klass
end

#validate_each(record, attribute, value) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/active_record/validations/globalized_uniqueness.rb', line 15

def validate_each(record, attribute, value)
  finder_class = find_finder_class_for(record)
  table = finder_class.arel_table

  coder = record.class.serialized_attributes[attribute.to_s] # FIXME add/test support for serialized attributes with globalize3

  # determine table / attr_column_class respecting globalize3 translations
  globalized_column_class = find_globalized_column_class_for(record, attribute)
  globalized = globalized_column_class.present?
  if globalized
    attr_column_class = globalized_column_class
    table = attr_column_class.arel_table
  else
    attr_column_class = finder_class
  end

  if value && coder
    value = coder.dump value
  end

  # build relation respecting globalize3 translations
  relation = build_relation(attr_column_class, table, attribute, value)
  relation = relation.and(finder_class.arel_table[finder_class.primary_key.to_sym].not_eq(record.send(:id))) if record.persisted?

  Array.wrap(options[:scope]).each do |scope_item|
    if globalized && ([:locale] | record.class.translated_attribute_names).include?(scope_item)
      # handle globalize3 translated attribute scopes and :locale scope
      scope_value = if scope_item == :locale
                      Globalize.locale.to_s
                    else
                      record.read_attribute(scope_item)
                    end
      relation = relation.and(table[scope_item].eq(scope_value))
    else
      scope_value = record.read_attribute(scope_item)
      relation = relation.and(finder_class.arel_table[scope_item].eq(scope_value))
    end
  end

  # finalize building & execute query (respecting globalize3 translations)
  scoped = finder_class.unscoped
  scoped = scoped.joins(:translations) if globalized
  if scoped.where(relation).exists?
    record.errors.add(attribute, :taken, options.except(:case_sensitive, :scope).merge(:value => value))
  end
end