Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

use read_attribute to allow scoping by an aggregation's attribute value #5264

Closed
wants to merge 1 commit into from

4 participants

@jtcalhoun

The following error is produced in Arel when an aggregation is provided as the :scope parameter to validates_uniqueness_of:

TypeError: Cannot visit CustomClassWithoutRecognizedAncestors
    from /usr/local/Cellar/ruby/1.9.3-p125/lib/ruby/gems/1.9.1/gems/arel-3.0.2/lib/arel/visitors/visitor.rb:25:in `rescue in visit'
    from /usr/local/Cellar/ruby/1.9.3-p125/lib/ruby/gems/1.9.1/gems/arel-3.0.2/lib/arel/visitors/visitor.rb:19:in `visit'
    ...

ActiveRecord uses the aggregation's value object as the scope value instead of its actual attribute value.

The attached code resolves this issue by using the attribute value after type cast but before conversion.

@drogus
Collaborator
@isaacsanders

Is this still an issue?

@rafaelfranca

Closing this since #6743 was merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 4, 2012
  1. @jtcalhoun

    use read_attribute to allow scoping by an aggregation's attribute val…

    jtcalhoun authored
    …ue instead of its converted value object
This page is out of date. Refresh to see the latest.
View
2  activerecord/lib/active_record/validations/uniqueness.rb
@@ -26,7 +26,7 @@ def validate_each(record, attribute, value)
relation = relation.and(table[finder_class.primary_key.to_sym].not_eq(record.send(:id))) if record.persisted?
Array(options[:scope]).each do |scope_item|
- scope_value = record.send(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)
View
15 activerecord/test/cases/validations/uniqueness_validation_test.rb
@@ -25,7 +25,7 @@ class Thaumaturgist < IneptWizard
class UniquenessValidationTest < ActiveRecord::TestCase
fixtures :topics, 'warehouse-things', :developers
- repair_validations(Topic, Reply)
+ repair_validations(Topic, Reply, DeveloperWithAggregate)
def test_validate_uniqueness
Topic.validates_uniqueness_of(:title)
@@ -131,6 +131,19 @@ def test_validate_uniqueness_scoped_to_defining_class
assert r3.valid?, "Saving r3"
end
+ def test_validate_uniqueness_scoped_to_aggregation
+ DeveloperWithAggregate.validates_uniqueness_of(:name, :scope => :salary)
+
+ existing = developers(:jamis)
+ duplicate = DeveloperWithAggregate.new :name => existing.name, :salary => DeveloperSalary.new(existing.salary)
+
+ assert duplicate.invalid?
+
+ duplicate.salary = DeveloperSalary.new(existing.salary + 1)
+
+ assert duplicate.valid?
+ end
+
def test_validate_uniqueness_with_scope_array
Reply.validates_uniqueness_of(:author_name, :scope => [:author_email_address, :parent_id])
Something went wrong with that request. Please try again.