Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 3206

Show
Ignore:
Timestamp:
12/02/05 04:30:46 (4 years ago)
Author:
marcel
Message:

Allow validate_uniqueness_of to be scoped by more than just one column. Closes #1559.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/activerecord/CHANGELOG

    r3205 r3206  
    11*SVN* 
     2 
     3* Allow validate_uniqueness_of to be scoped by more than just one column.  #1559. [jeremy@jthopple.com, Marcel Molina Jr.] 
    24 
    35* Firebird: active? and reconnect! methods for handling stale connections.  #428 [Ken Kunz <kennethkunz@gmail.com>] 
  • trunk/activerecord/lib/active_record/validations.rb

    r3142 r3206  
    472472      # 
    473473      #   class Person < ActiveRecord::Base 
    474       #     validates_uniqueness_of :user_name, :scope => "account_id" 
     474      #     validates_uniqueness_of :user_name, :scope => :account_id 
     475      #   end 
     476      # 
     477      # It can also validate whether the value of the specified attributes are unique based on multiple scope parameters.  For example, 
     478      # making sure that a teacher can only be on the schedule once per semester for a particular class.  
     479      # 
     480      #   class TeacherSchedule < ActiveRecord::Base 
     481      #     validates_uniqueness_of :teacher_id, :scope => [:semester_id, :class_id]  
    475482      #   end 
    476483      # 
     
    480487      # Configuration options: 
    481488      # * <tt>message</tt> - Specifies a custom error message (default is: "has already been taken") 
    482       # * <tt>scope</tt> - Ensures that the uniqueness is restricted to a condition of "scope = record.scope" 
    483       # * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should 
    484       # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }).  The 
    485       # method, proc or string should return or evaluate to a true or false value. 
     489      # * <tt>scope</tt> - One or more columns by which to limit the scope of the uniquness constraint. 
     490      # * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should 
     491      # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }).  The 
     492      # method, proc or string should return or evaluate to a true or false value. 
     493        
    486494      def validates_uniqueness_of(*attr_names) 
    487495        configuration = { :message => ActiveRecord::Errors.default_error_messages[:taken] } 
     
    492500          condition_params = [value] 
    493501          if scope = configuration[:scope] 
    494             scope_value = record.send(scope) 
    495             condition_sql << " AND #{scope} #{attribute_condition(scope_value)}" 
    496             condition_params << scope_value 
     502            Array(scope).map do |scope_item| 
     503              scope_value = record.send(scope_item) 
     504              condition_sql << " AND #{scope_item} #{attribute_condition(scope_value)}" 
     505              condition_params << scope_value 
     506            end 
    497507          end 
    498508          unless record.new_record? 
  • trunk/activerecord/test/validations_test.rb

    r2863 r3206  
    279279    r3 = t2.replies.create "title" => "r3", "content" => "hello world" 
    280280    assert r3.valid?, "Saving r3" 
     281  end 
     282 
     283  def test_validate_uniqueness_with_scope_array 
     284    Reply.validates_uniqueness_of(:author_name, :scope => [:author_email_address, :parent_id]) 
     285 
     286    t = Topic.create("title" => "The earth is actually flat!") 
     287  
     288    r1 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply" 
     289    assert r1.valid?, "Saving r1" 
     290     
     291    r2 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply again..." 
     292    assert !r2.valid?, "Saving r2. Double reply by same author."  
     293     
     294    r2.author_email_address = "jeremy_alt_email@rubyonrails.com" 
     295    assert r2.save, "Saving r2 the second time."  
     296     
     297    r3 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy_alt_email@rubyonrails.com", "title" => "You're wrong", "content" => "It's cubic" 
     298    assert !r3.valid?, "Saving r3" 
     299     
     300    r3.author_name = "jj" 
     301    assert r3.save, "Saving r3 the second time." 
     302     
     303    r3.author_name = "jeremy" 
     304    assert !r3.save, "Saving r3 the third time." 
    281305  end 
    282306