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.
ruby
add a comment |
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
2
Ah, it's a pity that your bot is not giving out rewards here :)
– Sergio Tulentsev
Nov 21 '18 at 13:51
add a comment |
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
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
ruby
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
add a comment |
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
add a comment |
2 Answers
2
active
oldest
votes
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"
You probably want to callsuper
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 doklass.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
add a comment |
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
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, withclass 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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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"
You probably want to callsuper
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 doklass.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
add a comment |
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"
You probably want to callsuper
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 doklass.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
add a comment |
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"
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"
edited Nov 21 '18 at 14:17
answered Nov 21 '18 at 13:37
jarosluvjarosluv
885
885
You probably want to callsuper
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 doklass.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
add a comment |
You probably want to callsuper
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 doklass.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
add a comment |
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
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, withclass 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
add a comment |
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
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, withclass 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
add a comment |
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
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
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, withclass 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
add a comment |
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, withclass 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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
2
Ah, it's a pity that your bot is not giving out rewards here :)
– Sergio Tulentsev
Nov 21 '18 at 13:51