Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

accepts_nested_attributes_for not updating correctly with validates_uniqueness_of

#6566

If I create a Team and add two users to it through UsersTeam, one with a position of "leader" and another with a position of "follower", I receive a uniqueness validation error when I swap the positions on a Team form with UsersTeams nested.

class User 
has_many :users_teams
end

class Team
has_many :users_teams
accepts_nested_attributes_for :users_teams
end

class UsersTeam
belongs_to :user
belongs_to :team

validates_presence_of :position
validates_uniqueness_of :position, :scope => :team_id #Two users with the same position cannot be on the same team
end

Reported by Joey · March 12th, 2011 @ 06:25 AM

State: new
Milestone: none
Assigned to: nobody
Importance: none

Activity

  1. Dan Pickett
    Dan Pickett

    Joey,

    Can you provide a failing test that verifies this errant behavior?

    March 12th, 2011 @ 04:27 PM

  2. Joey
    Joey

    I'm not to good with creating test cases. I pushed an app to github with the following instructions to reproduce the bug.

    https://github.com/joeytheman/Rails3-Bug6566

    How to reproduce Rails Lighthouse Bug [#6566](/projects/8994/tickets/6566 "Ticket #6566")
    
    1. Download source from git://github.com/joeytheman/Rails3-Bug6566.git .
    
    2. Run "bundle install".
    
    3. Run "rake db:schema:load".
    
    4. Navigate to "/users" and create 2 users.
    
    5. Navigate to "/team" and create a new team with 2 teammates with the following parameters
        -Teammate 1
        -- User => 1
        -- Team => nil
        -- Position => "C"
    
        -Teammate 2
        -- User => 2
        -- Team => nil
        -- Position => "A"
    
    6. Navigate to "/team/1/edit".
    
    7. Set the position of player 1 to "A" and the position of player 2 to "C".
    
    8. Attempt to save.
    

    March 19th, 2011 @ 10:37 AM

  3. Pablo
    Pablo

    Hello, I've downloaded to mac the app in Github, follow steps but didn't reproduce the bug, it changed correctly from one value to the other.
    I'll try later to do the same on windows, I think you are using Windows, don't you?
    Regards,

    March 24th, 2011 @ 09:00 PM

  4. Joey
    Joey

    I checked my repo and realized I had the validation commented out from testing in users_team.rb. If you pull the repo again you can verify the bug. And I'm using windows 7 x64, Ruby 1.9.2p180, and rails 3.0.5. Sorry for the inconvenience.

    March 24th, 2011 @ 09:18 PM

  5. Pablo
    Pablo

    Hi. Now I can reproduce it. It even fails when doing in a transaction, ie:

    https://gist.github.com/887397

    ActiveRecord::RecordInvalid: Validation failed: Position has already been taken

    The problem is that the SQLs run before updating the database so you get:

    UsersTeam Load (0.2ms) SELECT "users_teams"."id" FROM "users_teams" WHERE "users_teams"."team_id" = 1 AND ("users_teams"."position" = 'p2') AND ("users_teams".id <> 1) LIMIT 1

    AREL (0.8ms) UPDATE "users_teams" SET "position" = 'p2', "updated_at" = '2011-03-25 19:10:46.892606' WHERE "users_teams"."id" = 1

    March 25th, 2011 @ 11:32 PM

  6. Pablo
    Pablo

    Ok, here is a test that fails:

    May add it to test/cases/validations/uniqueness_validation_test.rb

    def test_validate_uniqueness_when_swapping_values_within_transaction

    Event.new( title:'E1').save!
    Event.new( title:'E2').save!
    ActiveRecord::Base.transaction do
      e1 = Event.find(1)
      e2 = Event.find(2)
      e1.title = 'E2'
      e2.title = 'E1'
      e2.save
      e1.save
    end
    assert_equal Event.find(1).title, 'E2'
    assert_equal Event.find(2).title, 'E1'
    

    end

    March 28th, 2011 @ 12:57 AM