Skip to content

autosave calls invalid validations - regression #14106

Closed
dnagir opened this Issue Feb 19, 2014 · 5 comments

4 participants

@dnagir
dnagir commented Feb 19, 2014
gem 'activerecord', '4.1.0.rc1'
require 'active_record'
require 'minitest/autorun'
require 'logger'

ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Base.establish_connection(
  :adapter  => 'postgresql',
  :database => 'x'
)

ActiveRecord::Schema.define do
  create_table :users, :force => true do |t|
    t.string :name
  end
  create_table :blogs, :force => true do |t|
    t.integer :user_id
  end
end

class User < ActiveRecord::Base
  validate :should_be_cool, :on => :create

  private

  def should_be_cool
    unless self.name == 'cool'
      errors.add :name, "not cool"
    end
  end
end

class Blog < ActiveRecord::Base
  belongs_to :user, autosave: true
end


class TestMe < MiniTest::Unit::TestCase
  def test_validations
    u = User.create!(name: 'cool')
    u.update_attributes!(name: 'nah') # still valid because validation only applies on 'create'
    assert_equal true, Blog.create!(user: u).persisted?
  end
end

Output:

-- create_table(:users, {:force=>true})
D, [2014-02-19T15:38:03.412525 #73127] DEBUG -- :    (1.8ms)  DROP TABLE "users"
D, [2014-02-19T15:38:03.415127 #73127] DEBUG -- :    (2.4ms)  CREATE TABLE "users" ("id" serial primary key, "name" character varying(255)) 
   -> 0.0389s
-- create_table(:blogs, {:force=>true})
D, [2014-02-19T15:38:03.417138 #73127] DEBUG -- :    (0.9ms)  DROP TABLE "blogs"
D, [2014-02-19T15:38:03.418682 #73127] DEBUG -- :    (1.4ms)  CREATE TABLE "blogs" ("id" serial primary key, "user_id" integer) 
   -> 0.0035s
MiniTest::Unit::TestCase is now Minitest::Test. From tmp/a.rb:38:in `<main>'
Run options: --seed 11923

# Running:

D, [2014-02-19T15:38:03.485645 #73127] DEBUG -- :    (0.1ms)  BEGIN
D, [2014-02-19T15:38:03.489362 #73127] DEBUG -- :   SQL (1.0ms)  INSERT INTO "users" ("name") VALUES ($1) RETURNING "id"  [["name", "cool"]]
D, [2014-02-19T15:38:03.489861 #73127] DEBUG -- :    (0.1ms)  COMMIT
D, [2014-02-19T15:38:03.490090 #73127] DEBUG -- :    (0.1ms)  BEGIN
D, [2014-02-19T15:38:03.491132 #73127] DEBUG -- :   SQL (0.2ms)  UPDATE "users" SET "name" = $1 WHERE "users"."id" = 1  [["name", "nah"]]
D, [2014-02-19T15:38:03.491303 #73127] DEBUG -- :    (0.1ms)  COMMIT
D, [2014-02-19T15:38:03.496097 #73127] DEBUG -- :    (0.1ms)  BEGIN
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
D, [2014-02-19T15:38:03.505042 #73127] DEBUG -- :    (0.1ms)  ROLLBACK
E

Finished in 0.025973s, 38.5015 runs/s, 0.0000 assertions/s.

  1) Error:
TestMe#test_validations:
ActiveRecord::RecordInvalid: Validation failed: User name not cool
    /Users/dnagir/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.1.0.rc1/lib/active_record/validations.rb:57:in `save!'
    /Users/dnagir/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.1.0.rc1/lib/active_record/attribute_methods/dirty.rb:29:in `save!'
    /Users/dnagir/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.1.0.rc1/lib/active_record/transactions.rb:273:in `block in save!'
    /Users/dnagir/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.1.0.rc1/lib/active_record/transactions.rb:329:in `block in with_transaction_returning_status'
    /Users/dnagir/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.1.0.rc1/lib/active_record/connection_adapters/abstract/database_statements.rb:211:in `block in transaction'
    /Users/dnagir/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.1.0.rc1/lib/active_record/connection_adapters/abstract/database_statements.rb:219:in `within_new_transaction'
    /Users/dnagir/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.1.0.rc1/lib/active_record/connection_adapters/abstract/database_statements.rb:211:in `transaction'
    /Users/dnagir/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.1.0.rc1/lib/active_record/transactions.rb:208:in `transaction'
    /Users/dnagir/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.1.0.rc1/lib/active_record/transactions.rb:326:in `with_transaction_returning_status'
    /Users/dnagir/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.1.0.rc1/lib/active_record/transactions.rb:273:in `save!'
    /Users/dnagir/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.1.0.rc1/lib/active_record/validations.rb:41:in `create!'
    tmp/a.rb:42:in `test_validations'

1 runs, 0 assertions, 0 failures, 1 errors, 0 skips

Expected: the test should pass. The validation on User model should NOT be called when creating a Blog entry because the User's validation is marked as :on => :create only.

Actual: The validation marked as :on => :create on already persisted model is executed when it should not.

Workarounds: Remove autosave or downgrade to 4.1.0.beta1 (the example above will pass with 4.0.1).

Reproducible: In 4.1.0.rc1 and maybe 4.1.0.beta2 (not tested).

@pftg
pftg commented Feb 19, 2014

This bug confirmed only for 4.1.0.rc1, 4-1-stable and master, for 4.1.0.beta2 and 4.0.x is not reproduced.

@seanwalbran

Looks like this is coming from PR #13978 -- reverting this commit appears to fix the repro script: 5e3d466

@pftg
pftg commented Feb 19, 2014
@tenderlove
Ruby on Rails member

Ok, I'll revert #13978 for now /cc @Fortisque

@tenderlove
Ruby on Rails member

This should be fixed in 4-1-stable now. I added a regression test in 95bacbe

@tenderlove tenderlove closed this Feb 20, 2014
@tenderlove tenderlove added a commit that referenced this issue Feb 20, 2014
@tenderlove tenderlove adding a test for #14106 7eaebd8
@tenderlove tenderlove added a commit that referenced this issue Feb 20, 2014
@tenderlove tenderlove adding a test for #14106 95bacbe
@ttosch ttosch pushed a commit that referenced this issue Jan 19, 2015
@tenderlove tenderlove adding a test for #14106 c877c9c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.