Can I invoke an instance method on a Ruby module without including it?

Background:

I have a module which declares a number of instance methods

module UsefulThings
  def get_file; ...
  def delete_file; ...

  def format_text(x); ...
end

And I want to call some of these methods from within a class. How you normally do this in ruby is like this:

class UsefulWorker
  include UsefulThings

  def do_work
    format_text("abc")
    ...
  end
end
Problem

include UsefulThings brings in all of the methods from UsefulThings. In this case I only want format_text and explicitly do not want get_file and delete_file.

I can see several possible solutions to this:

  1. Somehow invoke the method directly on the module without including it anywhere
    • I don't know how/if this can be done. (Hence this question)
  2. Somehow include Usefulthings and only bring in some of it's methods
    • I also don't know how/if this can be done
  3. Create a proxy class, include UsefulThings in that, then delegate format_text to that proxy instance
    • This would work, but anonymous proxy classes are a hack. Yuck.
  4. Split up the module into 2 or more smaller modules
    • This would also work, and is probably the best solution I can think of, but I'd prefer to avoid it as I'd end up with a proliferation of dozens and dozens of modules - managing this would be burdensome

Why are there lots of unrelated functions in a single module? It's ApplicationHelper from a rails app, which our team has de-facto decided on as the dumping ground for anything not specific enough to belong anywhere else. Mostly standalone utility methods that get used everywhere. I could break it up into seperate helpers, but there'd be 30 of them, all with 1 method each... this seems unproductive

Answers


If a method on a module is turned into a module function you can simply call it off of Mods as if it had been declared as

module Mods
  def self.foo
     puts "Mods.foo(self)"
  end
end

The module_function approach below will avoid breaking any classes which include all of Mods.

module Mods
  def foo
    puts "Mods.foo"
  end
end

class Includer
  include Mods
end

Includer.new.foo

Mods.module_eval do
  module_function(:foo)
  public :foo
end

Includer.new.foo # this would break without public :foo above

class Thing
  def bar
    Mods.foo
  end
end

Thing.new.bar

However, I'm curious why a set of unrelated functions are all contained within the same module in the first place?

Edited to show that includes still work if public :foo is called after module_function :foo


Need Your Help

insert MAX()+1 and other values

c# asp.net ms-access insert max

I'm very new to C# and trying to insert multiple values to an access database, one of which will increment by 1. I cannot use auto-number in access because the entries start at 99001 and I will nee...

CSS overflow: auto for mobile browsers

css mobile-website

I am developing a site for mobile browsers, but I am not sure if css overflow:auto works on most of them.

Hi all , I need to remotely shutdown a linux machine from a windows machine through java program

java windows

I need to remotely shutdown a linux machine from a windows server machine through java program . Is there any direct command to do that.