tags:

views:

85

answers:

3

I am currently working through the Gregory Brown Ruby Best Practices book. Early on, he is talking about refactoring some functionality from helper methods on a related class, to some methods on module, then had the module extend self.

Hadn't seen that before, after a quick google, found out that extend self on a module lets methods defined on the module see each other, which makes sense.

Now, my question is when would you do something like this

module StyleParser
  extend self

  def process(text)
    ...
  end

  def style_tag?(text)
    ...
  end
end

and then refer to it in tests with

@parser = Prawn::Document::Text::StyleParser

as opposed to something like this?

class StyleParser

  def self.process(text)
    ...
  end

  def self.style_tag?(text)
    ...
  end
end 

is it so that you can use it as a mixin? or are there other reasons I'm not seeing?

A: 

If it's something you want to instantiate, use a class. The rest of your question needs more context to make sense.

Azeem.Butt
+2  A: 

A class should be used for functionality that will require instantiation or that needs to keep track of state. A module can be used either as a way to mix functionality into multiple classes, or as a way to provide one-off features that don't need to be instantiated or to keep track of state. A class method could also be used for the latter.

With that in mind, I think the distinction lies in whether or not you really need a class. A class method seems more appropriate when you have an existing class that needs some singleton functionality. If what you're making consists only of singleton methods, it makes more sense to implement it as a module and access it through the module directly.

Jimmy Cuadra
Exactly what I was looking for :-)
Matt Briggs
+1  A: 

In this particular case I would probably user neither a class nor a module.

A class is a factory for objects (note the plural). If you don't want to create multiple instances of the class, there is no need for it to exist.

A module is a container for methods, shared among multiple objects. If you don't mix in the module into multiple objects, there is no need for it to exist.

In this case, it looks like you just want an object. So use one:

def (StyleParser = Object.new).process(text)
  ...
end

def StyleParser.style_tag?(text)
  ...
end

Or alternatively:

class << (StyleParser = Object.new)
  def process(text)
    ...
  end

  def style_tag?(text)
    ...
  end
end

But as @Azeem already wrote: for a proper decision, you need more context. I am not familiar enough with the internals of Prawn to know why Gregory made that particular decision.

Jörg W Mittag