Tracking record modifying users with merb and datamapper
## ------------------------------------------------------------ # In a model # ------------------------------------------------------------ # class MyModel # include DataMapper::Resource # include Trackable::Model # # # uses all default properties and associations # track_modifications # :user_model => "User" # :as_creator => :creator # :as_updater => :last_modifying_user # :timestamps => true # # uses the specified model and associations # track_modifications :user_model => "Account" # :as_creator => :creating_account # :as_updater => :updating_account # :timestamps => false # end # # ------------------------------------------------------------ # In a controller # ------------------------------------------------------------ # class MyController < Application # include Trackable::Controller # # # defaults to using :current_user # track_modifications # # specify explicitly which "current_user_getter" to use # track_modifications :using => :current_account # # def create # or any other action # # instead of calling # # @model.save OR # # @model.update_attributes(attributes) # # use these instance methods # # save_resource(@model) OR # # save_resource!(@model) OR # # update_resource(@model, attributes) OR # # update_resource!(@model, attributes) # end # end # ------------------------------------------------------------ module Trackable module Model def self.included(base) base.extend ClassMethods end module ClassMethods def track_modifications(options = {}) user_model = options[:user_model] || :user creator = options[:as_creator] || :creator modifier = options[:as_updater] || "last_modifying_#{user_model}" track_timestamps = options[:timestamps] || true class_eval do if track_timestamps include DataMapper::Timestamp end property :created_by, Integer, :nullable => false property :updated_by, Integer, :nullable => false belongs_to creator, :class_name => user_model.to_s.camel_case, :foreign_key => "created_by" belongs_to modifier, :class_name => user_model.to_s.camel_case, :foreign_key => "updated_by" end end end end module Controller def self.included(base) base.extend ClassMethods base.send :include, InstanceMethods end module ClassMethods def track_modifications(options = {}) user_getter = options[:using].to_sym || :current_user class_eval do alias :__current_user__ user_getter end end end module InstanceMethods def save_resource(resource, bang = false) if resource.new_record? if resource.respond_to? :created_by resource.created_by = send(__current_user__).id end else if resource.respond_to? :updated_by resource.updated_by = send(__current_user__).id end end bang ? resource.save! : resource.save end def save_resource!(resource) save_resource(resource, true) end def update_resource(resource, attributes, bang = false) if resource.new_record? if resource.respond_to? :created_by resource.created_by = send(__current_user__).id end else if resource.respond_to? :updated_by resource.updated_by = send(__current_user__).id end end if bang && resource.respond_to(:update_attributes!) resource.update_attributes!(attributes) else resource.update_attributes(attributes) end end def update_resource!(resource, attributes) update_resource(resource, attributes, true) end end end end