Once again looking for my module methods

Gee. Once again I want my module methods inherited.

Trans wrote:

Gee. Once again I want my module methods inherited.

How are they not?

robert

On Mar 20, 2006, at 7:48 AM, Robert K. wrote:

Trans wrote:

Gee. Once again I want my module methods inherited.

How are they not?

module Example
def self.i_am_a_module_method
puts “Hello”
end
end
=> nil

include Example
=> Object

i_am_a_module_method
NameError: undefined local variable or method `i_am_a_module_method’
for main:Object
from (irb):10
from :0

James Edward G. II

Trans wrote:

Gee. Once again I want my module methods inherited.

I agree, I was actually going to look into it why it didn’t work for me,
but now I know it’s not my fault, but actually a problem with ruby :slight_smile: So
thanks for saving me a couple of minutes of frustration :slight_smile:

Hi –

On Tue, 21 Mar 2006, Iain D Broadfoot wrote:

module Foo
end
end

which works, but it’s far from perfect.

You’re taking the long road :slight_smile:

module Foo
def self.included(c)
def c.foo
:foo
end
end
#…
end

David


David A. Black ([email protected])
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

“Ruby for Rails” chapters now available
from Manning Early Access Program! Ruby for Rails

Edwin van Leeuwen said something:

Trans wrote:

Gee. Once again I want my module methods inherited.

I agree, I was actually going to look into it why it didn’t work for me,
but now I know it’s not my fault, but actually a problem with ruby :slight_smile: So
thanks for saving me a couple of minutes of frustration :slight_smile:

One naive and ugly solution is:

module Foo
def self.included c
c.instance_eval{
def self.foo
:foo
end

  def self.bar
    :bar
  end
}

end
end

which works, but it’s far from perfect.

iain

Actually, I have developed what is probably the most complete solution
out there. Check out Calibre’s

require ‘calibre/classinherit’

Even so, any solution is still an ugly hack and imperfect to the real
solution. Hint. Hint.

---- classinherit.rb

#:title: ClassInherit

This framework provides a very convenient way to have modules

pass along class methods in the inheritance chain.

Presently in Ruby the class/module methods of a module

are not inherited when a module is included --contrary to

the behavior of classes themselves when they are subclassed.

To achieve the same behavior with modules requires some clever

Ruby karate. ClassInherit provides a nice solution.

Simply place the class inheritable methods in the block

parameter of the special module method ClassInherit.

module Mix

def inst_meth

puts ‘inst_meth’

end

ClassInherit do

def class_meth

“Class Method!”

end

end

end

class X

include Mix

end

X.class_meth #=> “Class Method!”

ClassInherit is a capitalized method. This is used because it

indeed creates (or reopens) a ClassInherit module in which

the given block is evaluated, then the ClassInherit module

is extended against the current module.

The above is actually equivalent to putting the class/module

methods in a nested ClassInherit module and extending the

module manually, eg.

module Mix

def inst_meth

puts ‘inst_meth’

end

module ClassInherit

def class_meth

“Class Method!”

end

end

extend ClassInherit

end

class X

include Mix

end

X.class_meth #=> “Class Method!”

Lastly, #class_inherit is an available alias for #ClassInherit

if you prefer only lowercase methods.

== Notes

Just a quick comment on the need for this behavior.

A module is an encapsulation of code, hence when a module is included

(or extends), the module itself should have discretion over how it

effects the receiving class/module. That is the very embodiment of

encapsulation. Having it otherwise, as Ruby now does, stymies the

practice --and we end up with “hacks” like this to compensate.

Ruby would be much improved by making this bevaivor standard.

And making non-inheritance the exception, which is alwasy easy

enough to achieve: just put the code in a separate

(and thus uninherited) module.

== Author(s)

* Thomas S.

* Nobu Nakada

* Ulysses

class Module

alias_method :append_features_without_classinherit, :append_features

def append_features( base )
result = append_features_without_classinherit( base )
if const_defined?( :ClassInherit )
base.extend( self::ClassInherit )
unless base.is_a?( Class )
unless base.const_defined?( :ClassInherit )
base.const_set( :ClassInherit, Module.new )
end
my = self
base::ClassInherit.class_eval do
include my::ClassInherit
end
end
end
result
end

def ClassInherit( &yld )
if const_defined?( :ClassInherit )
self::ClassInherit.class_eval( &yld )
else
self.const_set( :ClassInherit, Module.new( &yld ) )
end
extend( self::ClassInherit )
self::ClassInherit
end

For compatibility with old rendition

alias_method :class_inherit, :ClassInherit

end

class Class
undef_method :ClassInherit
undef_method :class_inherit
end

[email protected] said something:

You’re taking the long road :slight_smile:

module Foo
def self.included©
def c.foo
:foo
end
end
#…
end

Ah, I made the classic mistake of simplifying working code to use as an
example. :slight_smile:

I do more than just create methods, so the instance_eval is useful for
me. (and I’m not refactoring my code for a while, so if I’ve missed
something reeeeealy simple don’t tell me!)

iain

There’s also Hyperextend:
http://redhanded.hobix.com/bits/hyperextended.html which is what I ended
up using :slight_smile:

Vag

On Mon, 2006-03-20 at 22:03 +0900, Trans wrote:

Gee. Once again I want my module methods inherited.

As usual, I have a feeling the answer is ‘no’, but doesn’t this take
care of it (maybe with improved ignorance of callback methods)?

module Foo
def self.included©
singleton_methods.reject { |e| e == ‘included’ }.each do |m|
mod = self
c.class_eval do
(class << self; self; end).class_eval do
define_method(m, &(mod.method(m)))
end
end
end
nil
end

def self.foo
:foo
end

def self.bar(baz)
baz
end

def joe
:joe
end
end

class Baz
include Foo
end

p Baz.foo

=> :foo

p Baz.bar(:bar)

=> :bar

p Baz.new.joe

=> :joe

On Tue, 21 Mar 2006, Trans wrote:

Actually, I have developed what is probably the most complete solution
out there. Check out Calibre’s

require ‘calibre/classinherit’

Even so, any solution is still an ugly hack and imperfect to the real
solution. Hint. Hint.

i just use this pattern:

 harp:~ > cat a.rb
 module M
   module ClassMethods
     def foo; "foo"; end
   end
   module InstanceMethods
     def bar; "bar"; end
   end

   recursive_inclusion = lambda { |other|
     other.module_eval {
       extend ClassMethods
       include InstanceMethods
       singleton_class = class << self; self; end
       singleton_class.module_eval {
         define_method "included", &recursive_inclusion
       }
       super
     }
   }

   singleton_class = class << self; self; end
   singleton_class.module_eval {
     define_method "included", &recursive_inclusion
   }
 end

 class C
   include M
 end
 class B < C
 end
 module N
   include M
 end
 class D
   include N
 end

 p C::foo
 p C::new.bar
 p B::foo
 p B::new.bar
 p D::foo
 p D::new.bar


 harp:~ > ruby a.rb
 "foo"
 "bar"
 "foo"
 "bar"
 "foo"
 "bar"

regards.

-a

On Tue, 2006-03-21 at 05:01 +0900, [email protected] wrote:

module Foo
def self.included©
singleton_methods.reject { |e| e == ‘included’ }.each do |m|
mod = self
c.class_eval do
(class << self; self; end).class_eval do

Is there any reason not to just do that as:

(class << c; self; end).class_eval

No, I don’t think so. I just missed it during refactoring :slight_smile:

BTW, There’s an RCP asking for this.

I know that a lot of people would really like this (myself included).
Has anyone voiced any serious reasons why not to make this the
default behavior?

Hi –

On Tue, 21 Mar 2006, Ross B. wrote:

 c.class_eval do
   (class << self; self; end).class_eval do

Is there any reason not to just do that as:

(class << c; self; end).class_eval

? (I’m not sure whether there’s some other hidden snag or not, as,
per your original question, but that leapt out at me.)

David


David A. Black ([email protected])
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

“Ruby for Rails” chapters now available
from Manning Early Access Program! Ruby for Rails

On Tue, 21 Mar 2006 [email protected] wrote:

I guess that means you don’t think the reasons given in the comment
section of the RCR are serious :slight_smile:

I don’t think it’s a good idea, because I see no reason to favor the
hypothesis that a module’s singleton methods are appropriate for a
class, just because the module’s instance methods are appropriate for
instances of the class. That’s one possible scenario (and it can
easily be done, already, though I think it’s not necessarily a sign of
optimal design), but I don’t see why it should be the starting point
and everything else a deviation from it. See the RCR site for more
comments from me and others.

indeed:

class B
end

module M
def M.new() B.new end
end

class C
include M
end

not least of which.

-a

Hi –

On Tue, 21 Mar 2006, [email protected] wrote:

BTW, There’s an RCP asking for this.

I know that a lot of people would really like this (myself included).
Has anyone voiced any serious reasons why not to make this the
default behavior?

I guess that means you don’t think the reasons given in the comment
section of the RCR are serious :slight_smile:

I don’t think it’s a good idea, because I see no reason to favor the
hypothesis that a module’s singleton methods are appropriate for a
class, just because the module’s instance methods are appropriate for
instances of the class. That’s one possible scenario (and it can
easily be done, already, though I think it’s not necessarily a sign of
optimal design), but I don’t see why it should be the starting point
and everything else a deviation from it. See the RCR site for more
comments from me and others.

David


David A. Black ([email protected])
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

“Ruby for Rails” chapters now available
from Manning Early Access Program! Ruby for Rails

[email protected] wrote:

not least of which.

Your example is misguided.

class B
end

class M
  def M.new() B.new end
end

class C < M
end

T.

I don’t think it’s a good idea, because I see no reason to favor the
hypothesis that a module’s singleton methods are appropriate
for a class

What “hypothesis”? It’s being used in practice.

According to your argument we should not have class method inheritance
either.

T.

I wonder if there’s a way to make several groups of people happy by
allowing this:
module Z
def method; end
end

class A < Z
end

…which would let modules act as abstract classes if necessary.

Hi –

On Wed, 22 Mar 2006, Wilson B. wrote:

I wonder if there’s a way to make several groups of people happy by
allowing this:
module Z
def method; end
end

class A < Z
end

…which would let modules act as abstract classes if necessary.

There’s definitely a school of thought that modules and classes should
be merged, though I am not of it and Matz isn’t either :slight_smile:

David

T.


David A. Black ([email protected])
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

“Ruby for Rails” chapters now available
from Manning Early Access Program! Ruby for Rails