class ActiveRecord::Base def to_summary respond_to?(:name) ? name : "to_summary unimplemented for #{self.class}" end def humanized_modified_attributes modified_attributes.keys.inject({}) do |hash, attribute| hash[attribute] = humanized_attribute(attribute, :read_original_attribute) hash end end # Turns an attribute into a human readable form: # - Converts a Date or Time into a string # - Displays the result of running to_summary on a belongs_to association def humanized_attribute(attr_name, method = :read_attribute) attr_name = attr_name.to_s value = send(method, attr_name) return nil if value.blank? if reflection = self.class.reflect_on_belongs_to_association_by_foreign_key(attr_name) # if the ids match, use the cached object cached_association = instance_variable_get("@#{reflection.name}") if cached_association and cached_association.id == value cached_association.to_summary else begin klass = if reflection.options[:polymorphic] self[attr_name.gsub(/_id$/, "_type")].constantize else reflection.klass end klass.find(value).to_summary rescue ActiveRecord::RecordNotFound end end else value.to_s end end class << self def reflect_on_belongs_to_association_by_foreign_key(foreign_key) reflections.values.find { |reflection| reflection.macro == :belongs_to && reflection.primary_key_name == foreign_key } end end end