Created
February 11, 2015 18:26
-
-
Save jeremy/84134ad08f2a137aa1ef to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'active_support/concern' | |
module Touchless | |
module TouchLater | |
extend ActiveSupport::Concern | |
included do | |
# Preserve immediate touch behavior as touch_now | |
alias_method :touch, :touch_now | |
alias_method :touch_later, :touch | |
# TODO: only want this callback registered if touch was called, | |
# so untouched records needn't be tracked by the transaction. | |
before_commit :defer_touch_until_commit | |
end | |
# Defer touch until just before the db transaction commits. Rely on | |
# after_touch callbacks to fire and bubble touches (also deferred until | |
# transaction commit) up to parents. | |
def touch_later(*names) | |
raise ActiveRecordError, "cannot touch on a new record object" unless persisted? | |
# Mark the usual suspects plus the attrs requested for later touching | |
@_touch_attrs ||= timestamp_attributes_for_update_in_model | |
@_touch_attrs |= names | |
# Update this record's timestamps, but don't mark them as changed so | |
# this record doesn't get sucked in to a belongs_to autosave. | |
surreptiously_touch attrs | |
connection.add_transaction_record self | |
end | |
# Touch these attributes, but pretend like nothing changed so they don't | |
# get swept up and automatically saved when the associated record saves. | |
private def surreptiously_touch(attrs) | |
@_touch_time = current_time_from_proper_timezone | |
attrs.each { |attr| write_attribute attr, @_touch_time } | |
clear_attribute_changes attrs.keys | |
end | |
private def defer_touch_until_commit | |
if @_touch_attrs.present? | |
# TODO: accept an optional time: argument rather than always using | |
# the current time. | |
touch_now *@_touch_attrs, time: @_touch_time | |
end | |
end | |
end | |
end | |
# Wire up Active Record when it's available. | |
require 'activesupport/lazy_load_hooks' | |
ActiveSupport.on_load :active_record do | |
include ::Touchless::TouchLater | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment