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

Is it possible to load a partial view via string replacement in a controller in asp.net MVC 5

c# asp.net-mvc asp.net-mvc-5 asp.net-mvc-partialview

In web forms I could load a user control via a string replace when parsing data from the database.

Get div from external page, then delete an another div from it

php xml xpath domdocument domxpath

I need a little help, with getting content from external webpages.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.