module ActiveRecord::AttributeMethods::ClassMethods

def attribute_method_suffix(*suffixes)

person.name_changed? # => true
person.name = 'Hubert'
person.name_changed? # => false
person = Person.find(1)

end
end
...
def attribute_changed?(attr)
private

attribute_method_suffix '_changed?'
class Person < ActiveRecord::Base

For example:

the +attr+ argument.
An attribute#{suffix} instance method must exist and accept at least

attribute#{suffix}(#{attr}, *args, &block)

to

#{attr}#{suffix}(*args, &block)

Uses +method_missing+ and respond_to? to rewrite the method
Declares a method available for all attributes with the given suffix.
def attribute_method_suffix(*suffixes)
  attribute_method_suffixes.concat suffixes
  rebuild_attribute_method_regexp
end

def attribute_method_suffixes

Default to =, ?, _before_type_cast
def attribute_method_suffixes
  @@attribute_method_suffixes ||= []
end

def cache_attribute?(attr_name)

Returns +true+ if the provided attribute is being cached.
def cache_attribute?(attr_name)
  cached_attributes.include?(attr_name)
end

def cache_attributes(*attribute_names)

methods, like time related columns (e.g. +created_at+, +updated_at+).
be cached. Usually caching only pays off for attributes with expensive conversion
+cache_attributes+ allows you to declare which converted attribute values should
def cache_attributes(*attribute_names)
  attribute_names.each {|attr| cached_attributes << attr.to_s}
end

def cached_attributes

with datatype :datetime, :timestamp, :time, :date are cached.
Returns the attributes which are cached. By default time related columns
def cached_attributes
  @cached_attributes ||=
    columns.select{|c| attribute_types_cached_by_default.include?(c.type)}.map(&:name).to_set
end

def create_time_zone_conversion_attribute?(name, column)

def create_time_zone_conversion_attribute?(name, column)
  time_zone_aware_attributes && !skip_time_zone_conversion_for_attributes.include?(name.to_sym) && [:datetime, :timestamp].include?(column.type)
end

def define_attribute_methods

accessors, mutators and query methods.
Generates all the attribute related methods for columns in the database
def define_attribute_methods
  return if generated_methods?
  columns_hash.each do |name, column|
    unless instance_method_already_implemented?(name)
      if self.serialized_attributes[name]
        define_read_method_for_serialized_attribute(name)
      elsif create_time_zone_conversion_attribute?(name, column)
        define_read_method_for_time_zone_conversion(name)
      else
        define_read_method(name.to_sym, name, column)
      end
    end
    unless instance_method_already_implemented?("#{name}=")
      if create_time_zone_conversion_attribute?(name, column)
        define_write_method_for_time_zone_conversion(name)
      else  
        define_write_method(name.to_sym)
      end
    end
    unless instance_method_already_implemented?("#{name}?")
      define_question_method(name)
    end
  end
end

def define_question_method(attr_name)

Defines a predicate method attr_name?.
def define_question_method(attr_name)
  evaluate_attribute_method attr_name, "def #{attr_name}?; query_attribute('#{attr_name}'); end", "#{attr_name}?"
end

def define_read_method(symbol, attr_name, column)

Define an attribute reader method. Cope with nil column.
def define_read_method(symbol, attr_name, column)
  cast_code = column.type_cast_code('v') if column
  access_code = cast_code ? "(v=@attributes['#{attr_name}']) && #{cast_code}" : "@attributes['#{attr_name}']"
  unless attr_name.to_s == self.primary_key.to_s
    access_code = access_code.insert(0, "missing_attribute('#{attr_name}', caller) unless @attributes.has_key?('#{attr_name}'); ")
  end
  
  if cache_attribute?(attr_name)
    access_code = "@attributes_cache['#{attr_name}'] ||= (#{access_code})"
  end
  evaluate_attribute_method attr_name, "def #{symbol}; #{access_code}; end"
end

def define_read_method_for_serialized_attribute(attr_name)

Define read method for serialized attribute.
def define_read_method_for_serialized_attribute(attr_name)
  evaluate_attribute_method attr_name, "def #{attr_name}; unserialize_attribute('#{attr_name}'); end"
end

def define_read_method_for_time_zone_conversion(attr_name)

This enhanced read method automatically converts the UTC time stored in the database to the time zone stored in Time.zone.
Defined for all +datetime+ and +timestamp+ attributes when +time_zone_aware_attributes+ are enabled.
def define_read_method_for_time_zone_conversion(attr_name)
  method_body = <<-EOV
    def #{attr_name}(reload = false)
      cached = @attributes_cache['#{attr_name}']
      return cached if cached && !reload
      time = read_attribute('#{attr_name}')
      @attributes_cache['#{attr_name}'] = time.acts_like?(:time) ? time.in_time_zone : time
    end
  EOV
  evaluate_attribute_method attr_name, method_body
end

def define_write_method(attr_name)

def define_write_method(attr_name)
  evaluate_attribute_method attr_name, "def #{attr_name}=(new_value);write_attribute('#{attr_name}', new_value);end", "#{attr_name}="
end

def define_write_method_for_time_zone_conversion(attr_name)

This enhanced write method will automatically convert the time passed to it to the zone stored in Time.zone.
Defined for all +datetime+ and +timestamp+ attributes when +time_zone_aware_attributes+ are enabled.
def define_write_method_for_time_zone_conversion(attr_name)
  method_body = <<-EOV
    def #{attr_name}=(time)
      unless time.acts_like?(:time)
        time = time.is_a?(String) ? Time.zone.parse(time) : time.to_time rescue time
      end
      time = time.in_time_zone rescue nil if time
      write_attribute(:#{attr_name}, time)
    end
  EOV
  evaluate_attribute_method attr_name, method_body, "#{attr_name}="
end

def evaluate_attribute_method(attr_name, method_definition, method_name=attr_name)

Evaluate the definition for an attribute related method
def evaluate_attribute_method(attr_name, method_definition, method_name=attr_name)
  unless method_name.to_s == primary_key.to_s
    generated_methods << method_name
  end
  begin
    class_eval(method_definition, __FILE__)
  rescue SyntaxError => err
    generated_methods.delete(attr_name)
    if logger
      logger.warn "Exception occurred during reader method compilation."
      logger.warn "Maybe #{attr_name} is not a valid Ruby identifier?"
      logger.warn err.message
    end
  end
end

def generated_methods #:nodoc:

:nodoc:
Contains the names of the generated attribute methods.
def generated_methods #:nodoc:
  @generated_methods ||= Set.new
end

def generated_methods?

def generated_methods?
  !generated_methods.empty?
end

def instance_method_already_implemented?(method_name)

method is defined by Active Record though.
that also derive from Active Record. Raises DangerousAttributeError if the
Checks whether the method is defined in the model or any of its subclasses
def instance_method_already_implemented?(method_name)
  method_name = method_name.to_s
  return true if method_name =~ /^id(=$|\?$|$)/
  @_defined_class_methods         ||= ancestors.first(ancestors.index(ActiveRecord::Base)).sum([]) { |m| m.public_instance_methods(false) | m.private_instance_methods(false) | m.protected_instance_methods(false) }.map(&:to_s).to_set
  @@_defined_activerecord_methods ||= (ActiveRecord::Base.public_instance_methods(false) | ActiveRecord::Base.private_instance_methods(false) | ActiveRecord::Base.protected_instance_methods(false)).map(&:to_s).to_set
  raise DangerousAttributeError, "#{method_name} is defined by ActiveRecord" if @@_defined_activerecord_methods.include?(method_name)
  @_defined_class_methods.include?(method_name)
end

def match_attribute_method?(method_name)

Returns MatchData if method_name is an attribute method.
def match_attribute_method?(method_name)
  rebuild_attribute_method_regexp unless defined?(@@attribute_method_regexp) && @@attribute_method_regexp
  @@attribute_method_regexp.match(method_name)
end

def rebuild_attribute_method_regexp

Suffixes a, ?, c become regexp /(a|\?|c)$/
def rebuild_attribute_method_regexp
  suffixes = attribute_method_suffixes.map { |s| Regexp.escape(s) }
  @@attribute_method_regexp = /(#{suffixes.join('|')})$/.freeze
end