diff --git a/config/initializers/globalize2_patch.rb b/config/initializers/globalize2_patch.rb index 0a8ebbac00..b401676f45 100644 --- a/config/initializers/globalize2_patch.rb +++ b/config/initializers/globalize2_patch.rb @@ -1,88 +1,47 @@ - -module Globalize::ActiveRecord::ClassMethodsPatch - def self.included(base) - base.send(:include, ClassMethods) - end - - module ClassMethods - def validates_uniqueness_of(*attr_names) - configuration = { :case_sensitive => true } - configuration.update(attr_names.extract_options!) - - validates_each(attr_names,configuration) do |record, attr_name, value| - # The check for an existing value should be run from a class that - # isn't abstract. This means working down from the current class - # (self), to the first non-abstract class. Since classes don't know - # their subclasses, we have to build the hierarchy between self and - # the record's class. - class_hierarchy = [record.class] - while class_hierarchy.first != self - class_hierarchy.insert(0, class_hierarchy.first.superclass) - end - - # Now we can work our way down the tree to the first non-abstract - # class (which has a database table to query from). - finder_class = class_hierarchy.detect { |klass| !klass.abstract_class? } - is_translated_attribute = finder_class.translated_attribute_names.include?(attr_name) - translation_class = finder_class.translation_class if is_translated_attribute - - column = finder_class.columns_hash[attr_name.to_s] || translation_class.columns_hash[attr_name.to_s] - - if value.nil? - comparison_operator = "IS ?" - elsif column.text? - comparison_operator = "#{connection.case_sensitive_equality_operator} ?" - value = column.limit ? value.to_s.mb_chars[0, column.limit] : value.to_s - else - comparison_operator = "= ?" - end - - sql_attribute = is_translated_attribute ? - "#{translation_class.quoted_table_name}.#{connection.quote_column_name(attr_name)}" : - "#{record.class.quoted_table_name}.#{connection.quote_column_name(attr_name)}" - - if value.nil? || (configuration[:case_sensitive] || !column.text?) - condition_sql = "#{sql_attribute} #{comparison_operator}" - condition_params = [value] - else - condition_sql = "LOWER(#{sql_attribute}) #{comparison_operator}" - condition_params = [value.mb_chars.downcase] - end - - if scope = configuration[:scope] - Array(scope).map do |scope_item| - scope_value, scope_class = if scope_item == :locale - [ I18n.locale.to_s, - record.class.translation_class ] - elsif record.class.translated_attribute_names.include? scope_item.to_s - translation = record.translations.detect{ |t| t.locale == I18n.locale } - value = translation.send(scope_item) if translation.present? - - [ value, - record.class.translation_class ] - else - [ record.send(scope_item), - record.class ] - end - - condition_sql << " AND " << attribute_condition("#{scope_class.quoted_table_name}.#{scope_item}", scope_value) - condition_params << scope_value - end +# this is a pull request on globalize 3 +# https://github.com/svenfuchs/globalize3/pull/139 +# which is based on +# https://github.com/svenfuchs/globalize3/pull/121 +# does not work on rails 3.0 as it depends on build_relation but will on 3.1 + +require 'active_record/validations/uniqueness.rb' + +ActiveRecord::Validations::UniquenessValidator.class_eval do + def validate_each_with_translations(record, attribute, value) + klass = record.class + if klass.translates? && klass.translated?(attribute) + finder_class = klass.translation_class + table = finder_class.arel_table + + relation = build_relation(finder_class, table, attribute, value).and(table[:locale].eq(Globalize.locale)) + relation = relation.and(table[klass.reflect_on_association(:translations).foreign_key].not_eq(record.send(:id))) if record.persisted? + + translated_scopes = Array(options[:scope]) & klass.translated_attribute_names + untranslated_scopes = Array(options[:scope]) - translated_scopes + + untranslated_scopes.each do |scope_item| + scope_value = record.send(scope_item) + reflection = klass.reflect_on_association(scope_item) + if reflection + scope_value = record.send(reflection.foreign_key) + scope_item = reflection.foreign_key end + relation = relation.and(find_finder_class_for(record).arel_table[scope_item].eq(scope_value)) + end - unless record.new_record? - condition_sql << " AND #{record.class.quoted_table_name}.#{record.class.primary_key} <> ?" - condition_params << record.send(:id) - end + translated_scopes.each do |scope_item| + scope_value = record.send(scope_item) + relation = relation.and(table[scope_item].eq(scope_value)) + end - finder_class.with_exclusive_scope do - if finder_class.first(:conditions => [condition_sql, *condition_params], :include => :translations ).present? - record.errors.add(attr_name, :taken, :default => configuration[:message], :value => value) - end - end + if klass.unscoped.with_translations.where(relation).exists? + record.errors.add(attribute, :taken, options.except(:case_sensitive, :scope).merge(:value => value)) end + else + validate_each_without_translations(record, attribute, value) end end + alias_method_chain :validate_each, :translations end module Globalize @@ -132,8 +91,6 @@ module GlobalizePatch end end - -Globalize::ActiveRecord::ClassMethods.send(:include, Globalize::ActiveRecord::ClassMethodsPatch) Globalize.send(:include, GlobalizePatch) Globalize::ActiveRecord::Adapter.send(:include, Globalize::ActiveRecord::AdapterPatch)