Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Skipping :touch associations when saving an ActiveRecord object

Is there a way to skip updating associations with a :touch association when saving?

Setup:

class School < ActiveRecord::Base
  has_many :students
end

class Student < ActiveRecord::Base
  belongs_to :school, touch: true
end

I would like to be able to do something like the following where the touch is skipped.

@school = School.create
@student = Student.create(school_id: @school.id)
@student.name = "Trevor"
@student.save # Can I do this without touching the @school record?

Can you do this? Something like @student.save(skip_touch: true) would be fantastic but I haven't found anything like that.

I don't want to use something like update_column because I don't want to skip the AR callbacks.

like image 735
Andrew Hubbs Avatar asked Apr 25 '13 18:04

Andrew Hubbs


3 Answers

As of Rails v4.1.0.beta1, the proper way to do this would be:

@school = School.create
@student = Student.create(school_id: @school.id)

ActiveRecord::Base.no_touching do
  @student.name = "Trevor"
  @student.save
end
like image 108
jeffdill2 Avatar answered Nov 15 '22 23:11

jeffdill2


One option that avoids directly monkey patching is to override the method that gets created when you have a relation with a :touch attribute.

Given the setup from the OP:

class Student < ActiveRecord::Base
  belongs_to :school, touch: true

  attr_accessor :skip_touch

  def belongs_to_touch_after_save_or_destroy_for_school
    super unless skip_touch
  end

  after_commit :reset_skip_touch

  def reset_skip_touch
    skip_touch = false
  end
end

@student.skip_touch = true
@student.save # touch will be skipped for this save

This is obviously pretty hacky and depends on really specific internal implementation details in AR.

like image 35
Andrew Hubbs Avatar answered Nov 15 '22 22:11

Andrew Hubbs


Unfortunately, no. save doesn't provide such option.

Work around this would be to have another time stamp attribute that functions like updated_at but unlike updated_at, it updates only on certain situations for your liking.

like image 22
Jason Kim Avatar answered Nov 15 '22 22:11

Jason Kim