ben
ben

Reputation: 29777

How do I use the Enumerable mixin in my class?

I have a class called Note, which includes an instance variable called time_spent. I want to be able to do something like this:

current_user.notes.inject{|total_time_spent,note| total_time_spent + note.time_spent}

Is this possible by mixing in the Enumerable module? I know you are supposed to do add include Enumerable to the class and then define an each method, but should the each method be a class or instance method? What goes in the each method?

I'm using Ruby 1.9.2

Upvotes: 58

Views: 32119

Answers (3)

Artur INTECH
Artur INTECH

Reputation: 7276

each must be an instance method. It might look like this:

class Users
  include Enumerable

  def each(&block)
    users = %w[john bruce]
    users.each(&block)
  end
end

users = Users.new
users.each do |user|
  puts user
end

Outputs:

john
bruce

Upvotes: 0

Michael Kohl
Michael Kohl

Reputation: 66837

It's easy, just include the Enumerable module and define an each instance method, which more often than not will just use some other class's each method. Here's a really simplified example:

class ATeam
  include Enumerable

  def initialize(*members)
    @members = members
  end

  def each(&block)
    @members.each do |member|
      block.call(member)
    end
    # or
    # @members.each(&block)
  end
end

ateam = ATeam.new("Face", "B.A. Barracus", "Murdoch", "Hannibal")
#use any Enumerable method from here on
p ateam.map(&:downcase)

For further info, I recommend the following article: Ruby Enumerable Magic: The Basics.

In the context of your question, if what you expose through an accessor already is a collection, you probably don't need to bother with including Enumerable.

Upvotes: 101

3limin4t0r
3limin4t0r

Reputation: 21110

The Enumerable documentations says the following:

The Enumerable mixin provides collection classes with several traversal and searching methods, and with the ability to sort. The class must provide a method each, which yields successive members of the collection. If Enumerable#max, #min, or #sort is used, the objects in the collection must also implement a meaningful <=> operator, as these methods rely on an ordering between members of the collection.

This means implementing each on the collection. If you're interested in using #max, #min or #sort you should implement <=> on its members.

See: Enumerable

Upvotes: 6

Related Questions