2

Consider:

module A
  def self.a; puts "a"; end;
  def aa; A.a; end;
end
include A
aa
a

aa works but not a. Is there a trick to get A.a available as is a just as include Math makes log available as Math.log? I suspect the way is to write an a method for each self.a method, but is there's a trick to avoid that?

sawa
  • 165,429
  • 45
  • 277
  • 381
user1494787
  • 193
  • 1
  • 7

3 Answers3

1

Might you be looking for extend self?

module A
  def a; puts "a"; end;
  extend self
end

A.a

include A
a
Denis de Bernardy
  • 75,850
  • 13
  • 131
  • 154
  • Yes, but see [here](http://stackoverflow.com/questions/156362/what-is-the-difference-between-include-and-extend-in-ruby). – Linuxios Jun 08 '13 at 15:39
  • This would be perfect if it took the class methods up to the instance instead... but really nice trick to know just the same. Thanks! – user1494787 Jun 08 '13 at 15:47
  • I'm pretty sure you can do that by defining class methods and using `include self`. I just prefer it the other way around, personally. :-) – Denis de Bernardy Jun 08 '13 at 16:12
  • Linuxios, @Denis: Thanks, both your answers steered me into what I was looking for. – user1494787 Jun 08 '13 at 16:55
1

Based on other people's answers, I think what I want is:

module A
  module Functions
    def a
      puts 'a'
    end
  end
  extend Functions
end
# a is a module function of A
A.a
# Explicitly include these functions into one's instance
include A::Functions
a

Now one can include A without polluting their instance space with methods... unless explicitly doing so with include A::Functions.

user1494787
  • 193
  • 1
  • 7
0

There is a trick if you have access to the modules source, and there's still a trick if you don't. If you do, this would be the module A:

module A
  def a
    puts 'a!'
  end
  module_function :a
end

All of these will call a:

A.a
include A; a

Even if you don't have access to the module's source, this is still possible with a little (lot) of metaprogramming:

SomeMod.instance_methods(false).each {|method| SomeMod.__send__(:module_function, method.to_sym)}

This only works if the methods are defined as instance methods only in the original module.

If you want do define them as class methods and only make the instance when included:

module A
  def self.a
    puts 'a'
  end
  def self.included(klass)
    A.singleton_class.instance_methods(false).each do |m|
      klass.__send__(:define_method, m.to_sym) do |*args|
        A.__send__(m.to_sym, *args)
      end
    end
  end
end
Linuxios
  • 34,849
  • 13
  • 91
  • 116
  • This is close to what I need. I'm writing module functions, and by request of whoever wants to include the functions I want them to be able to just give the function name without using it's full name. Because the functions are not instance methods, I don't want to defined them that way. – user1494787 Jun 08 '13 at 15:54
  • @user1494787: There isn't a very good way to go from class to instance. Math uses the module_func approach ( I think), and it might be easier to just do this. Or.. hold on a sec... – Linuxios Jun 08 '13 at 15:56