Can I invoke an instance method on a Ruby module without including it?
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
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:
- 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)
- Somehow include Usefulthings and only bring in some of it's methods
- I also don't know how/if this can be done
- 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.
- 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
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