module DelegateAttributes def self.included(base) base.class_eval do extend ClassMethods end end module ClassMethods def delegate_or_override(*methods) options = methods.pop unless options.is_a?(Hash) && to = options[:to] raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate_or_override :hello, :to => :greeter)." end methods.each do |method| method_str = "" source_method, dest_method = *method dest_method ||= source_method method_str =<<-END_DEF def #{source_method}(*args, &block) if read_attribute(:#{source_method}) read_attribute(:#{source_method}) elsif #{to} #{to}.__send__(#{dest_method.inspect}, *args, &block) end end END_DEF file, line = caller[0].split(/:/) module_eval(method_str, file, line.to_i) end end end end ActiveRecord::Base.send(:include, DelegateAttributes)