Forum: Ruby Mixin a module method as a class method

Posted by Farrel Lifson (Guest)
on 2006-10-18 15:05
(Received via mailing list)
Is it possible to mix in a module method to become a class method? I'd
like to define the method_added method in a module and then mix it
into a class like so
 module Foo
   def self.method_added(method)
     puts "Added #{method}"
   end
 end

 class Bar
  include Foo
  def bar
  end
  def baz
  end
 end
So that I get
 Added bar
 Added baz
printed out. Is there any way to do this besides making Foo a class
and subclassing Foo from it?

Farrel
Posted by Jan Svitok (Guest)
on 2006-10-18 15:19
(Received via mailing list)
On 10/18/06, Farrel Lifson <farrel.lifson@gmail.com> wrote:
>   include Foo
>
> Farrel

See previous thread: 'Ruby for Rails p.462-464 - why include vs.
extend?' or api.rubyon rails and there *::*::ClassMethods

basicly something like this:

module A
 module M
  module ClassMethods
    def some_method
      #...
    end

  def included(c)
    c.extend(ClassMethods)
  end
 end
end

and then a class later that does this:

class B
 include A::M
end
Posted by Phrogz (Guest)
on 2006-10-18 15:42
(Received via mailing list)
Farrel Lifson wrote:
> Is it possible to mix in a module method to become a class method? I'd
> like to define the method_added method in a module and then mix it
> into a class like so
[...snip...]
> So that I get
>  Added bar
>  Added baz
> printed out.

module Foo
  def method_added(method)
    puts "Added #{method}"
  end
end
class Bar
  extend Foo
  def bar; end
  def baz; end
end
Posted by Phrogz (Guest)
on 2006-10-18 16:02
(Received via mailing list)
Jan Svitok wrote:
>  end
> end

The extra ClassMethods module is needed because self methods of a
module are never mixed into the lookup flow. See note #3 at
http://phrogz.net/RubyLibs/RubyMethodLookupFlow.png - using 'extend'
instead of 'include' causes the left end of the mixed-in module line to
come from the 'class methods' side of the extended class, but doesn't
change that the right end always points to the 'instance' methods of
the module.

(Right?)
Posted by Trans (Guest)
on 2006-10-18 16:50
(Received via mailing list)
Farrel Lifson wrote:
>   include Foo
>   def bar
>   end
>   def baz
>   end
>  end
> So that I get
>  Added bar
>  Added baz
> printed out. Is there any way to do this besides making Foo a class
> and subclassing Foo from it?

Search ruby-talk for #class_extension.

  require 'facet/module/calss_extension'

  module Foo
    class_extension {
      def method_added(method)
        puts "Added #{method}"
      end
    }
  end

T.
Posted by unknown (Guest)
on 2006-10-18 17:14
(Received via mailing list)
On Wed, 18 Oct 2006, Farrel Lifson wrote:

> include Foo
>
> Farrel

     harp:~ > cat a.rb
     module Foo
       #def self.method_added(method)
       def method_added(method)
         puts "Added #{method}"
       end
     end

     class Bar
       #include Foo
       extend Foo
       def bar
       end
       def baz
       end
     end

     harp:~ > ruby a.rb
     Added bar
     Added baz


if you need both instance and class methods to be in Foo, then you'll 
want:


     harp:~ > cat a.rb
     module Foo
       #def self.method_added(method)
       module ClassMethods
         def method_added(method)
           puts "Added #{method}"
         end
       end
       module InstanceMethods
         def foo() 42 end
       end
       def self.included other
         other.module_eval{
           extend ClassMethods
           include InstanceMethods
         }
       end
     end

     class Bar
       include Foo
       def bar
       end
       def baz
       end
     end

     p Bar.new.foo


     harp:~ > ruby a.rb
     Added bar
     Added baz
     42


-a
Posted by Verno Miller (verno)
on 2006-10-18 17:43
> Posted by Farrel Lifson (Guest) 
> on 18.10.2006 15:05 
> 
> Is it possible to mix in a module method to become a class method? 


Yet another approach:

http://redcorundum.blogspot.com/2006/06/mixing-in-class-methods.html
Posted by Rick Denatale (rdenatale)
on 2006-10-19 02:43
(Received via mailing list)
On 10/18/06, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:
> >
> > printed out. Is there any way to do this besides making Foo a class
>      end
>      harp:~ > ruby a.rb
>        module ClassMethods
>            include InstanceMethods
>      end
> -a
> --
> my religion is very simple.  my religion is kindness. -- the dalai lama

No need for the separate module for instance methods;

rick@frodo:/public/rubyscripts$ cat a1.rb
module Foo

  module ClassMethods
    def method_added(method)
      puts "Added #{method}"
    end
  end

  def self.included(other)
    other.extend ClassMethods
  end

  def foo
    42
  end
end

class Bar
  include Foo

  def bar
  end

  def baz
  end
end

p Bar.new.foo
rick@frodo:/public/rubyscripts$ ruby a1.rb
Added bar
Added baz
42


--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/
Posted by unknown (Guest)
on 2006-10-19 07:01
(Received via mailing list)
On Thu, 19 Oct 2006, Rick DeNatale wrote:

>
> No need for the separate module for instance methods;

no.  you are correct, it's just a convention which signifies to the
uninitiated what is happening.

regards.


-a
Posted by Trans (Guest)
on 2006-10-19 14:11
(Received via mailing list)
Verno Miller wrote:
> > Posted by Farrel Lifson (Guest)
> > on 18.10.2006 15:05
> >
> > Is it possible to mix in a module method to become a class method?
>
>
> Yet another approach:
>
> http://redcorundum.blogspot.com/2006/06/mixing-in-class-methods.html

This looks like much like #class_extension. How does this differ?

An interesting side note to this. I recetnly ran into the opposite case
wehere I wanted to prevent a class method (of a class) from being
inherited by the subclass. I had to use some method programming tricks
to undef the particular method. This further leads me to believe that
the best solution is to allow deignation of methods as inheritable or
not in much the same way we designate private/public. Classes' class
methods would be inheritable be default, module's not. This could also
be used for instance methods to create namespace local methods.

T.
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.