How to decorate all similar methods in Ruby?












1















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.










share|improve this question


















  • 2





    Ah, it's a pity that your bot is not giving out rewards here :)

    – Sergio Tulentsev
    Nov 21 '18 at 13:51
















1















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.










share|improve this question


















  • 2





    Ah, it's a pity that your bot is not giving out rewards here :)

    – Sergio Tulentsev
    Nov 21 '18 at 13:51














1












1








1








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.










share|improve this question














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.







ruby






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 21 '18 at 13:07









yegor256yegor256

56k87365508




56k87365508








  • 2





    Ah, it's a pity that your bot is not giving out rewards here :)

    – Sergio Tulentsev
    Nov 21 '18 at 13:51














  • 2





    Ah, it's a pity that your bot is not giving out rewards here :)

    – Sergio Tulentsev
    Nov 21 '18 at 13:51








2




2





Ah, it's a pity that your bot is not giving out rewards here :)

– Sergio Tulentsev
Nov 21 '18 at 13:51





Ah, it's a pity that your bot is not giving out rewards here :)

– Sergio Tulentsev
Nov 21 '18 at 13:51












2 Answers
2






active

oldest

votes


















4














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"





share|improve this answer


























  • You probably want to call super in that decorator

    – Sergio Tulentsev
    Nov 21 '18 at 13:39











  • You're right. I've got the original question wrong before. Thank you.

    – jarosluv
    Nov 21 '18 at 13:45






  • 1





    Also why class_eval? Can simply do klass.prepend Decorator

    – Sergio Tulentsev
    Nov 21 '18 at 13:50






  • 1





    This is stale part of code from my previous version of answer, that I've just fixed. Generally you're totally right again. Thank you :)

    – jarosluv
    Nov 21 '18 at 14:22



















1














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





share|improve this answer
























  • I think this is the correct example of "decorator pattern".

    – Kimmo Lehto
    Nov 21 '18 at 13:49






  • 1





    @KimmoLehto: depends. For one thing, other methods are not proxied here (original object's API, if it were specified, is not reflected fully). And some clients may do type checks, so you might want your decorated object still be_a? the same type.

    – Sergio Tulentsev
    Nov 21 '18 at 13:55













  • @SergioTulentsev yes, with class ReaderDecorator < SimpleDelegator it would be better. The question does have the keyword "decorate", so an answer with an actual "decorator" is fitting.

    – Kimmo Lehto
    Nov 22 '18 at 7:12











  • @KimmoLehto "actual" as in "as described by gang of four"? Their decorator implements the interface (maintains both api surface and type checks). Anyway, what I was trying to say is there are flavors of decorators. Who's to say which one of them is the "real" one? :)

    – Sergio Tulentsev
    Nov 22 '18 at 17:03













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53412735%2fhow-to-decorate-all-similar-methods-in-ruby%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









4














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"





share|improve this answer


























  • You probably want to call super in that decorator

    – Sergio Tulentsev
    Nov 21 '18 at 13:39











  • You're right. I've got the original question wrong before. Thank you.

    – jarosluv
    Nov 21 '18 at 13:45






  • 1





    Also why class_eval? Can simply do klass.prepend Decorator

    – Sergio Tulentsev
    Nov 21 '18 at 13:50






  • 1





    This is stale part of code from my previous version of answer, that I've just fixed. Generally you're totally right again. Thank you :)

    – jarosluv
    Nov 21 '18 at 14:22
















4














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"





share|improve this answer


























  • You probably want to call super in that decorator

    – Sergio Tulentsev
    Nov 21 '18 at 13:39











  • You're right. I've got the original question wrong before. Thank you.

    – jarosluv
    Nov 21 '18 at 13:45






  • 1





    Also why class_eval? Can simply do klass.prepend Decorator

    – Sergio Tulentsev
    Nov 21 '18 at 13:50






  • 1





    This is stale part of code from my previous version of answer, that I've just fixed. Generally you're totally right again. Thank you :)

    – jarosluv
    Nov 21 '18 at 14:22














4












4








4







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"





share|improve this answer















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"






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 21 '18 at 14:17

























answered Nov 21 '18 at 13:37









jarosluvjarosluv

885




885













  • You probably want to call super in that decorator

    – Sergio Tulentsev
    Nov 21 '18 at 13:39











  • You're right. I've got the original question wrong before. Thank you.

    – jarosluv
    Nov 21 '18 at 13:45






  • 1





    Also why class_eval? Can simply do klass.prepend Decorator

    – Sergio Tulentsev
    Nov 21 '18 at 13:50






  • 1





    This is stale part of code from my previous version of answer, that I've just fixed. Generally you're totally right again. Thank you :)

    – jarosluv
    Nov 21 '18 at 14:22



















  • You probably want to call super in that decorator

    – Sergio Tulentsev
    Nov 21 '18 at 13:39











  • You're right. I've got the original question wrong before. Thank you.

    – jarosluv
    Nov 21 '18 at 13:45






  • 1





    Also why class_eval? Can simply do klass.prepend Decorator

    – Sergio Tulentsev
    Nov 21 '18 at 13:50






  • 1





    This is stale part of code from my previous version of answer, that I've just fixed. Generally you're totally right again. Thank you :)

    – jarosluv
    Nov 21 '18 at 14:22

















You probably want to call super in that decorator

– Sergio Tulentsev
Nov 21 '18 at 13:39





You probably want to call super in that decorator

– Sergio Tulentsev
Nov 21 '18 at 13:39













You're right. I've got the original question wrong before. Thank you.

– jarosluv
Nov 21 '18 at 13:45





You're right. I've got the original question wrong before. Thank you.

– jarosluv
Nov 21 '18 at 13:45




1




1





Also why class_eval? Can simply do klass.prepend Decorator

– Sergio Tulentsev
Nov 21 '18 at 13:50





Also why class_eval? Can simply do klass.prepend Decorator

– Sergio Tulentsev
Nov 21 '18 at 13:50




1




1





This is stale part of code from my previous version of answer, that I've just fixed. Generally you're totally right again. Thank you :)

– jarosluv
Nov 21 '18 at 14:22





This is stale part of code from my previous version of answer, that I've just fixed. Generally you're totally right again. Thank you :)

– jarosluv
Nov 21 '18 at 14:22













1














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





share|improve this answer
























  • I think this is the correct example of "decorator pattern".

    – Kimmo Lehto
    Nov 21 '18 at 13:49






  • 1





    @KimmoLehto: depends. For one thing, other methods are not proxied here (original object's API, if it were specified, is not reflected fully). And some clients may do type checks, so you might want your decorated object still be_a? the same type.

    – Sergio Tulentsev
    Nov 21 '18 at 13:55













  • @SergioTulentsev yes, with class ReaderDecorator < SimpleDelegator it would be better. The question does have the keyword "decorate", so an answer with an actual "decorator" is fitting.

    – Kimmo Lehto
    Nov 22 '18 at 7:12











  • @KimmoLehto "actual" as in "as described by gang of four"? Their decorator implements the interface (maintains both api surface and type checks). Anyway, what I was trying to say is there are flavors of decorators. Who's to say which one of them is the "real" one? :)

    – Sergio Tulentsev
    Nov 22 '18 at 17:03


















1














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





share|improve this answer
























  • I think this is the correct example of "decorator pattern".

    – Kimmo Lehto
    Nov 21 '18 at 13:49






  • 1





    @KimmoLehto: depends. For one thing, other methods are not proxied here (original object's API, if it were specified, is not reflected fully). And some clients may do type checks, so you might want your decorated object still be_a? the same type.

    – Sergio Tulentsev
    Nov 21 '18 at 13:55













  • @SergioTulentsev yes, with class ReaderDecorator < SimpleDelegator it would be better. The question does have the keyword "decorate", so an answer with an actual "decorator" is fitting.

    – Kimmo Lehto
    Nov 22 '18 at 7:12











  • @KimmoLehto "actual" as in "as described by gang of four"? Their decorator implements the interface (maintains both api surface and type checks). Anyway, what I was trying to say is there are flavors of decorators. Who's to say which one of them is the "real" one? :)

    – Sergio Tulentsev
    Nov 22 '18 at 17:03
















1












1








1







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





share|improve this answer













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






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 21 '18 at 13:39









vk26vk26

585




585













  • I think this is the correct example of "decorator pattern".

    – Kimmo Lehto
    Nov 21 '18 at 13:49






  • 1





    @KimmoLehto: depends. For one thing, other methods are not proxied here (original object's API, if it were specified, is not reflected fully). And some clients may do type checks, so you might want your decorated object still be_a? the same type.

    – Sergio Tulentsev
    Nov 21 '18 at 13:55













  • @SergioTulentsev yes, with class ReaderDecorator < SimpleDelegator it would be better. The question does have the keyword "decorate", so an answer with an actual "decorator" is fitting.

    – Kimmo Lehto
    Nov 22 '18 at 7:12











  • @KimmoLehto "actual" as in "as described by gang of four"? Their decorator implements the interface (maintains both api surface and type checks). Anyway, what I was trying to say is there are flavors of decorators. Who's to say which one of them is the "real" one? :)

    – Sergio Tulentsev
    Nov 22 '18 at 17:03





















  • I think this is the correct example of "decorator pattern".

    – Kimmo Lehto
    Nov 21 '18 at 13:49






  • 1





    @KimmoLehto: depends. For one thing, other methods are not proxied here (original object's API, if it were specified, is not reflected fully). And some clients may do type checks, so you might want your decorated object still be_a? the same type.

    – Sergio Tulentsev
    Nov 21 '18 at 13:55













  • @SergioTulentsev yes, with class ReaderDecorator < SimpleDelegator it would be better. The question does have the keyword "decorate", so an answer with an actual "decorator" is fitting.

    – Kimmo Lehto
    Nov 22 '18 at 7:12











  • @KimmoLehto "actual" as in "as described by gang of four"? Their decorator implements the interface (maintains both api surface and type checks). Anyway, what I was trying to say is there are flavors of decorators. Who's to say which one of them is the "real" one? :)

    – Sergio Tulentsev
    Nov 22 '18 at 17:03



















I think this is the correct example of "decorator pattern".

– Kimmo Lehto
Nov 21 '18 at 13:49





I think this is the correct example of "decorator pattern".

– Kimmo Lehto
Nov 21 '18 at 13:49




1




1





@KimmoLehto: depends. For one thing, other methods are not proxied here (original object's API, if it were specified, is not reflected fully). And some clients may do type checks, so you might want your decorated object still be_a? the same type.

– Sergio Tulentsev
Nov 21 '18 at 13:55







@KimmoLehto: depends. For one thing, other methods are not proxied here (original object's API, if it were specified, is not reflected fully). And some clients may do type checks, so you might want your decorated object still be_a? the same type.

– Sergio Tulentsev
Nov 21 '18 at 13:55















@SergioTulentsev yes, with class ReaderDecorator < SimpleDelegator it would be better. The question does have the keyword "decorate", so an answer with an actual "decorator" is fitting.

– Kimmo Lehto
Nov 22 '18 at 7:12





@SergioTulentsev yes, with class ReaderDecorator < SimpleDelegator it would be better. The question does have the keyword "decorate", so an answer with an actual "decorator" is fitting.

– Kimmo Lehto
Nov 22 '18 at 7:12













@KimmoLehto "actual" as in "as described by gang of four"? Their decorator implements the interface (maintains both api surface and type checks). Anyway, what I was trying to say is there are flavors of decorators. Who's to say which one of them is the "real" one? :)

– Sergio Tulentsev
Nov 22 '18 at 17:03







@KimmoLehto "actual" as in "as described by gang of four"? Their decorator implements the interface (maintains both api surface and type checks). Anyway, what I was trying to say is there are flavors of decorators. Who's to say which one of them is the "real" one? :)

– Sergio Tulentsev
Nov 22 '18 at 17:03




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53412735%2fhow-to-decorate-all-similar-methods-in-ruby%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

MongoDB - Not Authorized To Execute Command

in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith

Npm cannot find a required file even through it is in the searched directory