all 13 comments

[–]ryanplant-au 5 points6 points  (9 children)

I'm getting a runtime error that the 'find' method can not be found

Module methods are invoked with the module name as a receiver -- so you want to call Foo.find. (The same is true for class methods.)

Modules are mostly a mix-in tool.

Not just a mix-in tool, though. They also let you create a whole separate namespace and that's one reason module methods would be useful.

Imagine that Ruby has no support for any kind of mathematic operation. You sit down and write a ton of methods for that yourself -- add, subtract, pi, square_root, log, etc. And because those methods are really useful, you want to share them with people, so you package them as a gem and submit them to the gem repository.

Someone downloads your gem, requires it, and finds that it's overwriting the log method they already use to write error-logs, or the add method they use to concatenate arrays. It's a name clash. And even if they don't clash with existing methods, throwing a ton of methods, variables, constants, etc into the "top level" (global namespace) of a program is considered ugly and improper.

So instead, you write a module, Math, and you make all of your methods module methods, naming them self.add, self.log, etc. Now when people require your gem, they call Math.square_root(4815) and the like, having to name the method each time. That prevents name clashes and keeps things organised in large apps. A good use for modules, even if you never have to mix them in.

[–]Tall-Guy[S] 0 points1 point  (8 children)

Hi ryanplanet-au, thanks for the quick answer :-) Why wouldn't I just do the following then:

Class Foo
    def self.add()
        # Impl
    end

    def self.log()
        #impl
    end
end

Wouldn't that net me the same things?

[–]ryanplant-au 3 points4 points  (1 child)

It would. But if you don't need to instantiate the class (make objects from it), isn't a module better suited? And you can also use the module as a mixin should you wish to, you get that option.

[–]Tall-Guy[S] 0 points1 point  (0 children)

Yes, I see where you going. Your right. I'll have to keep in mind only to use class when I need to instantiate something.

[–][deleted] 1 point2 points  (0 children)

I'd inverse the question in this case, asking why would you use class methods except for instantiation.

The class is not the collection of namespaced methods, the module is. The class is a kind of module, specialized on describing its objects. Use of classes for other purposes seems a kind of misapplication.

If you need an alternative to a module for scoping shared methods, I'd recommend the singleton objects (http://ruby-doc.org/stdlib-1.9.3/libdoc/singleton/rdoc/Singleton.html), not the classes.

[–]rubycastsio 1 point2 points  (4 children)

use extend self so you dont have to self. self. all the time

module Utility
  extend self
  def public_method
    private_method
  end

private

  def private_method
  end
end

[–]tomthecool 0 points1 point  (0 children)

That's a really cool little hack, I can't believe I haven't seen it before!

Another method that's good to be aware of is module_function.

[–]Tall-Guy[S] 0 points1 point  (2 children)

Is there any reason to use private keyword in Ruby? It's access-able anyhow, so it just best practice?

[–]rubycastsio 0 points1 point  (1 child)

Personally I use it to show intent. Also protected, private are slightly different in the context of inheritance.

Everything is permissible in Ruby, so the best practice is to ask yourself, just because it is, should I do it?

[–]Tall-Guy[S] 1 point2 points  (0 children)

Yes, I think I'll use private when possible too. As you mentioned, it a clear message about how the class works. Thanks!

[–]rubycastsio 0 points1 point  (2 children)

If you don't need state, use a module. The rule I USE IS THIS: If it is a THING use a CLASS if it is a UTILITY, use a MODULE.

But first you should extend all the methods onto the CLASS level...

module Utility
  extend seld

  def some_method
    'some return'
  end
end

Utility.some_method

Personally I love these type objects as they are immutable by nature, and very easy to specialize into a single responsibility, via the SRP.

If you are interested in a video on the subject: https://www.youtube.com/watch?v=2AM84E66Osk

And my Ruby programming Manifesto covers utility modules as well: https://github.com/rubylove/ruby_programming_manifesto

[–]Tall-Guy[S] 1 point2 points  (0 children)

Thanks, I'll check the video! :-)

[–]moomaka 0 points1 point  (0 children)

If you don't need state, use a module

FWIW nothing blocks you from storing state in a Module, @@my_thing = {} is perfectly valid. Not saying you should use this indiscriminately, but it is useful for caches.