How to dynamically open a method in Ruby
I want to dynamically open a method and return a value based on the input field. I am trying to ask what I want with an example here. If I could succeed this example, I would do what I want.
Assume I have a class called Greetings which has a method called greet() which takes message as argument.
class Greetings
def self.greet(message)
return "good morning" if message=="gm"
return "evening" if message=="ge"
return "good afternoon" if message=="ga"
end
end
When I do a Greetings.greet("ge")
, I get "evening" as the output. I want to change this behavior without changing the above Greetings class (obvious reason is that its an external library).
My question here is simple. What should I do when say I call Greetings.greet("ge")
should retu开发者_如何学JAVArn me "A Very Good Evening" and for all the other inputs, it should return what the original class returns. I know something about dynamically opening a class in Ruby but how would I delegate the method to parent for the other cases?
And I would be writing this inside the config/initializers folder since I am using Rails.
Method aliasing
You can alias your old method as old_greet
for example, and redefine with your own:
class Greetings
class << self
alias_method :old_greet, :greet
def greet(message)
(message == "ge") ? "A Very Good Evening" : old_greet(message)
end
end
end
and then you can:
puts Greetings.greet("ge")
Method chaining
With the Rails alias_method_chain
feature:
class Greetings
class << self
def greet_with_modifications(message)
(message == "ge") ? "A Very Good Evening" : greet_without_modifications(message)
end
alias_method_chain :greet, :modifications
end
end
and then you can:
puts Greetings.greet("ge")
Extending class
You can create your own class which extends the original like this:
module My
class Greetings < ::Greetings
def self.greet(message)
case message
when "ge"
"A Very Good Evening"
else
super(message)
end
end
end
end
and then you can:
puts My::Greetings.greet("ge")
You could do something like this to reopen the class in your code:
Greetings.class_eval do
class << self
alias :old_greet :greet
end
def self.greet(message)
return "a very good evening" if message == "ge"
old_greet(message)
end
end
You could do something like
class Greetings
class << self
alias :old_greet :greet
end
def self.greet(message)
return "A very good evening" if message == 'ge'
old_greet(message)
end
end
What about this, simply?
class Greetings
def self.greet(message)
return "good morning" if message=="gm"
return "evening" if message=="ge"
return "good afternoon" if message=="ga"
end
end
class GreetingsOverloaded < Greetings
def self.greet(message)
return "A Very Good Evenin" if message=="ge"
super
end
end
puts Greetings.greet("ge")
puts GreetingsOverloaded.greet("ge")
精彩评论