Skip to content

Calling build_association twice with touch: true triggers a touch #38219

@benjaminwols

Description

@benjaminwols

Steps to reproduce

Calling post.build_comment twice, triggers a touch on post.
It might have something to do with inverse_of, because if I remove inverse_of, the bug does not occur.

D, [2020-01-11T23:16:40.293485 #82802] DEBUG -- :    (0.1ms)  begin transaction
D, [2020-01-11T23:16:40.293801 #82802] DEBUG -- :   Post Create (0.1ms)  INSERT INTO "posts" ("created_at", "updated_at") VALUES (?, ?)  [["created_at", "2020-01-11 22:16:40.293038"], ["updated_at", "2020-01-11 22:16:40.293038"]]
D, [2020-01-11T23:16:40.294097 #82802] DEBUG -- :    (0.0ms)  commit transaction
D, [2020-01-11T23:16:40.310185 #82802] DEBUG -- :   Comment Load (0.1ms)  SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = ? LIMIT ?  [["post_id", 1], ["LIMIT", 1]]
D, [2020-01-11T23:16:42.315497 #82802] DEBUG -- :    (0.1ms)  begin transaction
D, [2020-01-11T23:16:42.315905 #82802] DEBUG -- :   Post Update (0.2ms)  UPDATE "posts" SET "updated_at" = ? WHERE "posts"."id" = ?  [["updated_at", "2020-01-11 22:16:42.314796"], ["id", 1]]
D, [2020-01-11T23:16:42.316145 #82802] DEBUG -- :    (0.1ms)  commit transaction

Reproducible code

require 'bundler/inline'

gemfile(true) do
  source 'https://rubygems.org'

  git_source(:github) { |repo| "https://github.com/#{repo}.git" }

  gem 'rails', '~> 6.0.2.1'
  gem 'sqlite3'
  gem 'byebug'
end

require 'active_record'
require 'minitest/autorun'
require 'logger'

# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table :posts, force: true do |t|
    t.timestamps
  end

  create_table :comments, force: true do |t|
    t.integer :post_id

    t.timestamps
  end
end

class Post < ActiveRecord::Base
  has_one :comment, inverse_of: :post, dependent: :destroy
end

class Comment < ActiveRecord::Base
  belongs_to :post, inverse_of: :comment, touch: true
end

class BugTest < Minitest::Test
  def test_association_stuff
    post = Post.create!
    updated_at = post.updated_at
    post.build_comment
    sleep 2
    post.build_comment

    assert_equal updated_at, post.updated_at
  end
end

Failure:
BugTest#test_association_stuff [bug_report_build_with_touch.rb:51]:
Expected: 2020-01-11 22:16:40 UTC
Actual: 2020-01-11 22:16:42 UTC

Expected behavior

No database queries

Actual behavior

updated_at gets updated in database

System configuration

Rails version: 6.0.2.1

Ruby version: 2.6.3

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions