yegor256
yegor256

Reputation: 105133

How to decorate all similar methods in Ruby?

Here is my class:

class Book
  def read
     # something
  end
end

And another one:

class Magazine
  def read
     # something
  end
end

Now, I want to decorate both read methods in these two classes. I want them both to print "hello" right before they start working. How do I do that? I suspect, I need to use mixins, but can't figure out exactly how.

Upvotes: 1

Views: 285

Answers (2)

jarosluv
jarosluv

Reputation: 98

You can prepend module:

module Decorator
  def read
    puts "hello"
    super
  end
end

class Book
  prepend Decorator

  def read
    puts "bye"
  end
end

class Magazine
  prepend Decorator

  def read
    puts "cya"
  end
end

Book.new.read 
# "hello"
# "bye"

Magazine.new.read
# "hello"
# "cya"

As well there is more clean way to do this kind of modifications with refinements:

class Book
  def read
    puts "bye"
  end
end

class Magazine
  def read
    puts "cya"
  end
end

module Decorator
  def read
    puts "hello"
    super
  end
end

module DecoratedBook
  refine Book do
    prepend Decorator
  end
end

module DecoratedMagazine
  refine Magazine do
    prepend Decorator
  end
end

using DecoratedBook
using DecoratedMagazine

Book.new.read 
# "hello"
# "bye"

Magazine.new.read
# "hello"
# "cya"

Notice: this code may not run in irb.

Also you can do it right in the runtime:

module Decorator
  def read
    puts "hello"
    super
  end
end

[Book, Magazine].each do |klass|
  klass.prepend Decorator
end

Book.new.read 
# "hello"
# "bye"

Magazine.new.read
# "hello"
# "cya"

Upvotes: 4

vk26
vk26

Reputation: 365

May be you want something as:

class ReaderDecorator
  def initialize(obj)
    @obj = obj
  end

  def read
    puts 'Hello'
    @obj.read
  end
end

ReaderDecorator.new(Book.new).read
ReaderDecorator.new(Magazine.new).read

Upvotes: 1

Related Questions