touch + autosave + accessing association causes updated_at to be overwritten by Rails #3083

Closed
pepawel opened this Issue Sep 20, 2011 · 7 comments

Projects

None yet

6 participants

pepawel commented Sep 20, 2011

Hi,

Sometimes I need to update fields in record without updating its timestamp (updated_at). To acomplish this, after modifying the object I call object.updated_at_will_change! and then object.save which causes updated_at to remain the same in database.
But in certain circumstances it is not possible.

In one-to-one association scenario when one side has :autosave => true and other has :touch => true accessing association then saving record causes updated_at to be overwritten with current timestamp.

Assuming we have these two models:

class Firm < ActiveRecord::Base
  has_one :user, :autosave => true
end

class User < ActiveRecord::Base
  belongs_to :firm, :touch => true
end

Following code:

# Create firm and user
f = Firm.new
f.build_user
f.save!
f.user.save!

# Set updated_at and save
time = Time.mktime 1, 1, 1
f = find f.id
f.updated_at = time # in my code I use f.updated_at_will_change! but here I want timestamp difference to be more visible
f.user
f.save

# Compare updated at with value with value which was set earlier
f.reload.updated_at == time

returns false. It means f.updated_at was set to current time, not to user specified value. In logs, two consecutive updates can be seen.

Now try to execute above code, but without accessing user (comment out f.user line). Observe that updated_at was set correctly.
Now uncomment f.user line back and remove :touch => true. Once again, updated_at is being set correctly.
Now restore :touch => true and remove :autosave => true. This time updated_at is also correct.

So the bug can be observed if every three of the conditions are met:

  1. has_one has :autosave => true
  2. belongs_to has :touch => true
  3. association belonging to main object is accessed

I don't know what the expected bahaviour should be. But I think that accessing association without modifing it shouldn't update main object timestamp.

Tested on Rails 3.1.0 and 3.0.5.

Contributor
jeremyf commented Apr 28, 2012

Do you test code to verify this is broken?

pepawel commented Apr 30, 2012

I don't have automated tests -- only manual test pasted in issue text.

Member

Does this still happen on 3.2 and/or master?

radeno commented Nov 19, 2012

Maybe it is very similar with my experience. When is touch defined in association within has_one, updated_at is always changed to current timestamp even when child object is not changed. If is association defined as has_many this behaviour is correct, and updated_at is not changed.

Have two models

class Place < ActiveRecord::Base
  has_one     :location,        inverse_of: :place, dependent: :destroy
  attr_accessible :location_attributes
  accepts_nested_attributes_for :location
end

class Location < ActiveRecord::Base
  belongs_to :place, inverse_of: :location, touch: true
  attr_accessible :place_id
end

When is Place opened to edit, no changes in Place nor Location. Saved to update -> updated_at in Place is always changed.

If is association changed to has_many :locations .... And do same event: Open place, no changes, click on update. updated_at is not changed as i exepted.

I don't find any documentation about changes between touch behaviour in has_many and has_one.

Tested with rails_admin

Member

Please submit a gist following the templates metoned at https://gist.github.com/neerajdotname/5187216 so that I could look into it.

Contributor
parndt commented May 1, 2013

This should honestly just be closed.

Member

Yes, the more I look at this, the more it feels like expected behavior. touch + autosave will update updated_at, that's kind of the whole point of touch.

If you can provide a concise example (via the template @neerajdotname suggested) demonstrating why there's an actual bug somewhere in Rails, we can re-open. But for now, I think this is because you're fighting expected behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment