save! not allowed after validates_uniqueness

I have this in a model

 validates_uniqueness_of :aspect, :scope => :user_id

In an instance method of the same model I have “save!” but I don’t touch

the :aspect attribute in that instance method at all.

Whenever that save! command is run however I get this error:

  ActiveRecord::RecordInvalid: Validation failed:  Aspect has

already been taken

I don’t understand. The validation should not skip the instance from

which the method is called. Please help. Thanks.

Posted via http://www.ruby-forum.com/.

What version of Rails are you using? Did you try this in Edge Rails?

-Conrad

Hi Conrad,

I am using Rails 2.3.2 and Ruby 1.8.7, the latest stable combination recommended by rubyonrails.org.

I am continuing to troubleshoot this. I have deleted all the sample data that I preloaded so that my database is empty. Now, the opposite is happening, it is letting me create records in violation of the uniqueness validation:

stat0 = Stat.new(:user_id => 1000, :aspect => "aspect0")

=> #<Stat id: nil, user_id: 1000, aspect: "aspect0">

stat0.save!

=> true

stat0 = Stat.new(:user_id => 1000, :aspect => "aspect0")

=> #<Stat id: nil, user_id: 1000, aspect: "aspect0">

stat0.save!

=> true

I check the database and yes it contains both of the above identical records. Only their :Stat_ids are different. Something wrong with my uniqueness validation?

   validates_uniqueness_of :aspect, :scope => :user_id

Thanks.

Can you post the model code and the db structure for this table please?

Colin

Colin:

Below are the relevant code. Thanks for your help.

class CreateStats < ActiveRecord::Migration

  def self.up     create_table :stats do |t|

      t.integer :user_id, :null => false       t.string :aspect, :null => false, :default => "default aspect"

      t.timestamps     end   end

  def self.down     drop_table :stats   end end

class Stat < ActiveRecord::Base

  belongs_to :user   validates_presence_of :user_id   validates_associated :user

  validates_uniqueness_of :aspect, :scope => :user_id

  attr_readonly :user_id, :aspect

end

I haven't been able to reproduce the issue that you have been having (on 2.3.2). I created a test suite for your model. Can you run that to see if you get the same problem.

http://gist.github.com/141740

Requires mocha, update references to fixtures and fields as required. It's based on the migration and model you provided.

HTH, Nicholas

Nicholas,

Thank you very much for working on this.

I ran the test suit but got errors. I modified the test suite: https://gist.github.com/4c009e230862d3a2e58a , using the users.yml: https://gist.github.com/1c282b5b006326cca497

Note that I changed the attribute name "aspect" to "score_aspect"

Below are the errors. Thank you for your help.

ruby test/unit/stat_test2.rb Loaded suite test/unit/stat_test2 Started E...EEEE Finished in 1.227252 seconds.

  1) Error: test_should_add_error_on_score_aspect_when_validating_with_the_same_score_aspect (StatTest): ActiveRecord::RecordInvalid: Validation failed: Score aspect has already been taken     test/unit/stat_test2.rb:33:in `test_should_add_error_on_score_aspect_when_validating_with_the_same_score_aspect'

  2) Error: test_should_not_add_error_on_score_aspect_when_validating_an_updated_stat (StatTest): ActiveRecord::RecordInvalid: Validation failed: Score aspect has already been taken     test/unit/stat_test2.rb:41:in `test_should_not_add_error_on_score_aspect_when_validating_an_updated_stat'

  3) Error: test_should_not_add_error_on_score_aspect_when_validating_with_a_different_score_aspect (StatTest): ActiveRecord::RecordInvalid: Validation failed: Score aspect has already been taken     test/unit/stat_test2.rb:25:in `test_should_not_add_error_on_score_aspect_when_validating_with_a_different_score_aspect'

  4) Error: test_should_score_aspect_be_read_only(StatTest): ActiveRecord::RecordInvalid: Validation failed: Score aspect has already been taken     test/unit/stat_test2.rb:49:in `test_should_score_aspect_be_read_only'

  5) Error: test_should_user_be_read_only(StatTest): ActiveRecord::RecordInvalid: Validation failed: Score aspect has already been taken     test/unit/stat_test2.rb:57:in `test_should_user_be_read_only'

8 tests, 3 assertions, 0 failures, 5 errors

Well you have me stumped, I ran your test suite against mine (after modifying the data structure) and it works. I'm assuming there is something in the mix that I'm not aware of. I'm not sure if it's much help, but you can download my test app to see if that runs for you.

http://files.me.com/nicholas.henry/0v2drf

Cheers, Nicholas