Skip to content

Instantly share code, notes, and snippets.

@mperrando
Created May 2, 2013 15:43
Show Gist options
  • Save mperrando/5503126 to your computer and use it in GitHub Desktop.
Save mperrando/5503126 to your computer and use it in GitHub Desktop.
Quick&drty monkey patch to fix the https://github.com/rails/rails/issues/4321 issue in the 3.2 branch.
# https://github.com/rails/rails/issues/4321
#
# https://github.com/rails/rails/pull/4370/files
#
raise "delete me" if ActiveModel::VERSION::MAJOR >= 4
module ActiveRecord
module Validations
class UniquenessValidator < ActiveModel::EachValidator
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]
if value && coder
value = coder.dump value
end
relation = build_relation(finder_class, table, attribute, value)
relation = relation.and(table[finder_class.primary_key.to_sym].not_eq(record.send(:id))) if record.persisted?
Array.wrap(options[:scope]).each do |scope_item|
scope_value = record.read_attribute(scope_item)
reflection = record.class.reflect_on_association(scope_item)
if reflection
scope_value = record.send(reflection.foreign_key)
scope_item = reflection.foreign_key
end
relation = relation.and(table[scope_item].eq(scope_value))
end
if finder_class.unscoped.where(relation).exists?
record.errors.add(attribute, :taken, options.except(:case_sensitive, :scope).merge(:value => value))
end
end
protected
def build_relation(klass, table, attribute, value) #:nodoc:
reflection = klass.reflect_on_association(attribute)
column = nil
if(reflection)
column = klass.columns_hash[reflection.foreign_key]
attribute = reflection.foreign_key
value = value.attributes[reflection.primary_key_column.name]
else
column = klass.columns_hash[attribute.to_s]
end
value = column.limit ? value.to_s.mb_chars[0, column.limit] : value.to_s if value && column.text?
if !options[:case_sensitive] && value && column.text?
# will use SQL LOWER function before comparison, unless it detects a case insensitive collation
relation = klass.connection.case_insensitive_comparison(table, attribute, column, value)
else
value = klass.connection.case_sensitive_modifier(value) if value
relation = table[attribute].eq(value)
end
relation
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment