Jump to content

The ultimate community for Ruby on Rails developers.


Photo

How to provide Custom Magic columns in ActiveRecord-4.1

ActiveRecord-4.1 magic columns monkey patch

  • Please log in to reply
No replies to this topic

#1 byrnejb

byrnejb

    Passenger

  • Members
  • 1 posts

Posted 05 August 2014 - 03:23 PM

We have a stand-alone ActiveRecord CLI application which has a magic column shim or monkey-patch to the AR create and update methods.  This worked with AR-3 and AR-4.0 but fails with AR-4.1.  This failure is apparently related to AR4.1 using autoload for its persistence library and thus the necessary methods are not available in ActiveRecord::Base to override during initialisation.

 

I am not sure how to fix this and am looking for suggestions on what is the best approach for 4.1.  It would be nice to have a solution that could backport to 4.0 as well but one that works just for 4.1 is good enough.

 

Basically our patch uses the alias_method_chain to intercept a call to either create or update methods.  It then checks for the existance of one or more columns from a list.  For each one found it calls a specific update method, writes the attribute and returns.  The technique we used is  similar to ARs default magic columns as implemented in the rails/timestamps module in Rails3.  In AR 3 and 4.0 the module was included in this fashion:

module  HLLAuditStamps

   .  .  .

  public
 
  def self.included( base )

    # create/update became create_record/update_record in Rails-4.0
    base.alias_method_chain( :create_record, :audit )
    base.alias_method_chain( :update_record, :audit )
   # for AR-3.2 use this instead
    #base.alias_method_chain( :create, :audit )
    #base.alias_method_chain( :update, :audit )

  end

end

class ActiveRecord::Base
  require( 'active_record/persistence' )
  include HLLAuditStamps
end

This was loaded using an initialiser with a full RoR stack or in the first call to AR in our CLI appliction.  There has to be a way to make this work since AR still supports timestamps.  However, the code has substancially changed from that similar to the above:

module ActiveRecord
  # Active Record automatically timestamps create and update operations if the table has fields
  # named created_at/created_on or updated_at/updated_on.
  #
  # Timestamping can be turned off by setting
  # <tt>ActiveRecord::Base.record_timestamps = false</tt>
  #
  # Timestamps are in the local timezone by default but you can use UTC by setting
  # <tt>ActiveRecord::Base.default_timezone = :utc</tt>
  module Timestamp
    def self.included(base) #:nodoc:
      base.alias_method_chain :create, :timestamps
      base.alias_method_chain :update, :timestamps


      base.class_inheritable_accessor :record_timestamps, :instance_writer => false
      base.record_timestamps = true
    end


    private

.  .  .

to this:

  module Timestamp

    extend ActiveSupport::Concern


    included do
      class_attribute :record_timestamps
      self.record_timestamps = true
    end


    def initialize_dup(other) # :nodoc:
      super
      clear_timestamp_attributes
    end


  private

What I need is some lucid explaination as to how the second form of implementation works in AR-4.1 and how one inserts ones own 'magic' columns into AR updates given the move to lazy library loading via autoload.  I have taken a look at UserStamp (https://github.com/d...tamp/stamper.rb) but they seem to use a similar technique to what I am doings - although they also seem to actually open ARs internal modules and have also run into a major problem with 4.1 compatiblity (https://github.com/delynn/userstamp/issues/24).

 

Suggestions anyone?  Does AR-4 provide a 'hook' to add ones own magic columns and their dependent processing?






0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users