# "include" versus "extend" - what's the difference

**URL:** <https://www.ruby-forum.com/t/include-versus-extend-whats-the-difference/67520>\
**Category:** Rails\
**Created:** [September 4, 2006, 10:38pm UTC](https://www.ruby-forum.com/t/include-versus-extend-whats-the-difference/67520 "2006-09-04T22:38:32Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [September 4, 2006, 10:38pm UTC](https://www.ruby-forum.com/t/include-versus-extend-whats-the-difference/67520/1 "2006-09-04T22:38:32Z")

</div>

Hi,

Just wondering when one would use “include” over “extend”? Both seem to  
bring in methods to the class no?

The context is I’m just trying to understand why both are used with the  
acts\_as\_audited plugin:

# Full extract from plugin (used within here):

# Copyright © 2006 Brandon K.

# 

# Permission is hereby granted, free of charge, to any person obtaining

# a copy of this software and associated documentation files (the

# “Software”), to deal in the Software without restriction, including

# without limitation the rights to use, copy, modify, merge, publish,

# distribute, sublicense, and/or sell copies of the Software, and to

# permit persons to whom the Software is furnished to do so, subject to

# the following conditions:

# 

# The above copyright notice and this permission notice shall be

# included in all copies or substantial portions of the Software.

# 

# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,

# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF

# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND

# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE

# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION

# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION

# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

module CollectiveIdea #:nodoc:  
module Acts #:nodoc:

# Specify this act if you want changes to your model to be saved in

an

# audit table. This assumes there is an audits table ready.

# 

# class User \< ActiveRecord::Base

# acts\_as\_audited

# end

# 

# See

CollectiveIdea::Acts::Audited::ClassMethods#acts\_as\_audited

# for configuration options

module Audited  
CALLBACKS = [:clear\_changed\_attributes, :audit\_create,  
:audit\_update, :audit\_destroy]

```
 def self.included(base) # :nodoc:
   base.extend ClassMethods
 end

 module ClassMethods
   # == Configuration options
   #
   # * <tt>except</tt> - Excludes fields from being saved in the

```

audit log.  
# By default, acts\_as\_audited will audit all but these fields:  
#  
# [self.primary\_key, inheritance\_column, ‘lock\_version’,  
‘created\_at’, ‘updated\_at’]  
#  
# You can add to those by passing one or an array of fields to  
skip.  
#  
# class User \< ActiveRecord::Base  
# acts\_as\_audited :except =\> :password  
# end  
#  
# \* user\_class\_name - specifiy the class name of the  
user class.  
# This defaults to “User”. Set to false to disable user  
auditing.  
#  
# \* user\_method - specify the method to call on  
:user\_class\_name  
# that returns the user that is performing the action. This  
defaults to  
# :current\_user.  
#  
# == Database Schema  
#  
def acts\_as\_audited(options = {})  
# don’t allow multiple calls  
return if  
self.included\_modules.include?(CollectiveIdea::Acts::Audited::InstanceMethods)

```
     include CollectiveIdea::Acts::Audited::InstanceMethods

     class_eval do
       extend CollectiveIdea::Acts::Audited::SingletonMethods

       cattr_accessor :non_audited_columns,

```

:audited\_user\_class\_name, :audited\_user\_method

```
       self.non_audited_columns = [self.primary_key,

```

inheritance\_column, ‘lock\_version’, ‘created\_at’, ‘updated\_at’]  
self.non\_audited\_columns |= options[:except].is\_a?(Array) ?  
options[:except].collect{|column| column.to\_s} :  
[options[:except].to\_s] if options[:except]  
self.audited\_user\_class\_name =  
options[:user\_class\_name].nil? ? “User” : options[:user\_class\_name]  
self.audited\_user\_method = options[:user\_method] ||  
:current\_user

```
       has_many :audits, :as => :auditable
       after_create :audit_create
       after_update :audit_update
       before_destroy :audit_destroy
       after_save :clear_changed_attributes
     end
   end
 end

 module InstanceMethods
   # Temporarily turns off auditing while saving.
   def save_without_auditing
     without_auditing do
       save
     end
   end

   # Returns an array of attribute keys that are audited. See

```

non\_audited\_columns  
def audited\_attributes  
self.attributes.keys.select { |k|  
!self.class.non\_audited\_columns.include?(k) }  
end

```
   # If called with no parameters, gets whether the current model

```

has changed.  
# If called with a single parameter, gets whether the parameter  
has changed.  
def changed?(attr\_name = nil)  
attr\_name.nil? ?  
(@changed\_attributes && @changed\_attributes.length \> 0) :  
(@changed\_attributes &&  
@changed\_attributes.include?(attr\_name.to\_s))  
end

```
   # Executes the block with the auditing callbacks disabled.
   #
   # @foo.without_auditing do
   # @foo.save
   # end
   #
   def without_auditing(&block)
     self.class.without_auditing(&block)
   end

   private
     # Creates a new record in the audits table if applicable
     def audit_create
                   logger.debug "ACTS AS: audit_create"
       write_audit(:create)
     end

     def audit_update
       write_audit(:update) if changed?
     end

     def audit_destroy
       write_audit(:destroy)
     end

     def write_audit(action = :update)
                   logger.debug "ACTS AS: write_audit"
               logger.debug "ACTS AS: self.audited_user_class_name =

```

#{self.audited\_user\_class\_name}"  
#logger.debug “ACTS AS:  
Object.const\_get(audited\_user\_class\_name) =  
#{Object.const\_get(audited\_user\_class\_name)}”  
logger.debug “ACTS AS: self.audited\_user\_method =  
#{self.audited\_user\_method}”  
user = self.audited\_user\_class\_name ?  
Object.const\_get(audited\_user\_class\_name).send(self.audited\_user\_method)  
: nil

```
       logger.debug "ACTS AS: user = #{user}"
                   audits.create(:changes => @changed_attributes, 

```

:action =\>  
action.to\_s,  
:user\_id =\> user ? user.id : nil)  
end

```
     # clears current changed attributes. Called after save.
     def clear_changed_attributes
       @changed_attributes = {}
     end

     # overload write_attribute to save changes to audited

```

attributes  
def write\_attribute(attr\_name, attr\_value)  
attr\_name = attr\_name.to\_s  
if audited\_attributes.include?(attr\_name)  
@changed\_attributes ||= {}  
# get original value  
old\_value = @changed\_attributes[attr\_name] ?  
@changed\_attributes[attr\_name].first : self[attr\_name]  
super(attr\_name, attr\_value)  
new\_value = self[attr\_name]

```
         @changed_attributes[attr_name] = [old_value, new_value] if

```

new\_value != old\_value  
else  
super(attr\_name, attr\_value)  
end  
end

```
     CALLBACKS.each do |attr_name|
       alias_method "orig_#{attr_name}".to_sym, attr_name
     end

     def empty_callback() end #:nodoc:

 end # InstanceMethods

 module SingletonMethods
   # Returns an array of columns that are audited. See

```

non\_audited\_columns  
def audited\_columns  
self.columns.select { |c|  
!non\_audited\_columns.include?(c.name) }  
end

```
   # Executes the block with the auditing callbacks disabled.
   #
   # Foo.without_auditing do
   # @foo.save
   # end
   #
   def without_auditing(&block)
     class_eval do
       CALLBACKS.each do |attr_name|
         alias_method attr_name, :empty_callback
       end
     end
     result = block.call
     class_eval do
       CALLBACKS.each do |attr_name|
         alias_method attr_name, "orig_#{attr_name}".to_sym
       end
     end
     result
   end
 end

```

end  
end  
end

ActiveRecord::Base.send :include, CollectiveIdea::Acts::Audited

==================================================

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [September 4, 2006, 11:24pm UTC](https://www.ruby-forum.com/t/include-versus-extend-whats-the-difference/67520/2 "2006-09-04T23:24:27Z")

</div>

Hi –

On Mon, 4 Sep 2006, Greg H. wrote:

> Hi,
> 
> Just wondering when one would use “include” over “extend”? Both seem to  
> bring in methods to the class no?

Neither of them actually brings methods into a class. They both have  
the effect of adding a module to a method lookup path. When you do  
this:

class C  
include M  
end

you’re adding M to the method lookup path of instances of C. When you  
do this:

c = C.new  
c.extend(M)

you’re adding M to the method lookup path of one particular instance  
of C. In other words, extend is a kind of object-specific version of  
include.

> The context is I’m just trying to understand why both are used with the  
> acts\_as\_audited plugin:

As with so many Ruby questions, it comes down to: classes are objects  
too 🙂 What you’re seeing, among other things, is a class being  
extended so that the class object itself will respond to a particular  
set of methods. This technique is used a lot in the Rails source.  
I’ve also got a detailed discussion of it in my book.

David

–  
David A. Black | removed\_email\_address@domain.invalid  
Author of “Ruby for Rails” [1] | Ruby/Rails training & consultancy [3]  
DABlog (DAB’s Weblog) [2] | Co-director, Ruby Central, Inc. [4]  
[1] [Ruby for Rails](http://www.manning.com/black) | [3] [http://www.rubypowerandlight.com](http://www.rubypowerandlight.com)  
[2] [http://dablog.rubypal.com](http://dablog.rubypal.com) | [4] [http://www.rubycentral.org](http://www.rubycentral.org)

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [September 5, 2006, 1:36pm UTC](https://www.ruby-forum.com/t/include-versus-extend-whats-the-difference/67520/3 "2006-09-05T13:36:08Z")

</div>

Thanks David - understand this, but still having a few troubles  
understanding this in context. Don’t suppose you/someone could clarify  
how  
things work in the following situation. Its code from acts\_as\_audited.  
Basically the cutback guts of it which I’m having trouble with is as  
follows. The cutback code is below. Questions I have include:

Q1) Is the acts\_as\_audited function in class Contact run when the  
“Contact”  
class is being read into the interpreter OR is it just actually carried  
out  
when a Contact class is instantiated?

Q2) Whenever acts\_as\_audited is run from Contact does the “include” line  
include the methods into the Contact object? (or was the Contact  
context  
really a class as opposed to instantiated object?)

Q3) I assume “class\_eval” is just included to somehow ensure things like  
the  
upcoming “extend” method is applied to the object which is calling (e.g.  
in  
this case the “contact” object)??? i.e. trying to understand why  
“class\_eval” was required here

Q4) When the “extend” line in then hit within “class\_eval” does it add  
these  
methods directly to the Contact object? (or was the Contact context  
really  
a class as opposed to instantiated object?)

Q5) I’m not sure if I should even ask about the last line  
“ActiveRecord::  
Base.send :include…” which is outside the modules, and when it is  
actually  
run and how it fits into things here ☹ … but if you do understand and  
your on a roll with these questions I’m really trying to understand this  
stuff 🙂

# contact.rb ======model========

class Contact \< ActiveRecord::Base  
acts\_as\_audited :user\_class\_name =\> ‘current\_user’, :user\_method =\>  
‘login’  
cattr\_accessor :current\_user  
# although I haven’t got the ‘current\_user’ part working yet I must  
admit  
end

#acts\_as\_audited.rb =======================================  
module CollectiveIdea #:nodoc:  
module Acts #:nodoc:  
module Audited  
CALLBACKS = [:clear\_changed\_attributes, :audit\_create,  
:audit\_update,  
:audit\_destroy]  
def self.included(base) # :nodoc:  
base.extend ClassMethods  
end  
module ClassMethods  
def acts\_as\_audited(options = {})  
return if self.included\_modules.include?  
(CollectiveIdea::Acts::Audited::InstanceMethods)  
include CollectiveIdea::Acts::Audited::InstanceMethods  
class\_eval do  
extend CollectiveIdea::Acts::Audited::SingletonMethods  
cattr\_accessor :non\_audited\_columns,  
:audited\_user\_class\_name,  
:audited\_user\_method  
.  
.  
.  
end  
end  
end

```
  module InstanceMethods
    . various def'ed methods
    .
    .
  end # InstanceMethods

  module SingletonMethods
  end
end

```

end  
end  
ActiveRecord::Base.send :include, CollectiveIdea::Acts::Audited  
#acts\_as\_audited.rb =======================================
