Do you use the alias method in order to add more ways to call methods (like length and size) or is there another use for it?
The alias_method call is also useful for re-implementing something but preserving the original version. There's also alias_method_chain from Rails which makes that kind of thing even easier.
alias_method also comes in handy when you have a number of behaviors that are initially identical but might diverge in the future, where you can at least rough them in to start.
def handle_default_situation
nil
end
%w[ poll push foo ].each do |type|
alias_method :"handle_#{type}_situation", :handle_default_situation
end
Yes.
It is often used to preserve a handle to existing methods before overriding them. (contrived example)
Given a class like this:
class Foo
def do_something
puts "something"
end
end
You could see code that adds new behaviour like so:
class Foo
def do_something_with_logging
puts "started doing something"
do_something_without_logging # call original implementation
puts "stopped doing something"
end
alias_method :do_something_without_logging, :do_something
alias_method :do_something, :do_something_with_logging
end
(this is exactly how alias_method_chain works)
However, for this use case it't often more appropriate to use inheritance and modules to your advantage.
Still, alias_method is a useful tool to have, if you absolutely need to redefine behaviour in an existing class (or if you wanted to implement something like alias_method_chain)
Related
I've made a constructor like this:
class Foo
def initialize(p1, p2, opts={})
#...Initialize p1 and p2
opts.each do |k, v|
instance_variable_set("##{k}", v)
end
end
end
I'm wondering if it's a good practice to dynamically set instance variables like this or if I should better set them manually one by one as in most of the libs, and why.
Diagnosing the problem
What you're doing here is a fairly simple example of metaprogramming, i.e. dynamically generating code based on some input. Metaprogramming often reduces the amount of code you need to write, but makes the code harder to understand.
In this particular case, it also introduces some coupling concerns: the public interface of the class is directly related to the internal state in a way that makes it hard to change one without changing the other.
Refactoring the example
Consider a slightly longer example, where we make use of one of the instance variables:
class Foo
def initialize(opts={})
opts.each do |k, v|
instance_variable_set("##{k}", v)
end
end
def greet(name)
greeting = #greeting || "Hello"
puts "#{greeting}, name"
end
end
Foo.new(greeting: "Hi").greet
In this case, if someone wanted to rename the #greeting instance variable to something else, they'd possibly have a hard time understanding how to do that. It's clear that #greeting is used by the greet method, but searching the code for #greeting wouldn't help them find where it was first set. Even worse, to change this bit of internal state they'd also have to change any calls to Foo.new, because the approach we've taken ties the internal state to the public interface.
Remove the metaprogramming
Let's look at an alternative, where we just store all of the opts and treat them as state:
class Foo
def initialize(opts={})
#opts = opts
end
def greet(name)
greeting = #opts.fetch(:greeting, "Hello")
puts "#{greeting}, name"
end
end
Foo.new(greeting: "Hi").greet
By removing the metaprogramming, this clarifies the situation slightly. A new team member who's looking to change this code for the first time is going to have a slightly easier time of things, because they can use editor features (like find-and-replace) to rename the internal ivars, and the relationship between the arguments passed to the initialiser and the internal state is a bit more explicit.
Reduce the coupling
We can go even further, and decouple the internals from the interface:
class Foo
def initialize(opts={})
#greeting = opts.fetch(:greeting, "Hello")
end
def greet(name)
puts "#{#greeting}, name"
end
end
Foo.new(greeting: "Hi").greet
In my opinion, this is the best implementation we've looked at:
There's no metaprogramming, which means we can find explicit references to variables being set and used, e.g. with an editor's search features, grep, git log -S, etc.
We can change the internals of the class without changing the interface, and vice-versa.
By calling opts.fetch in the initialiser, we're making it clear to future readers of our class what the opts argument should look like, without making them read the whole class.
When to use metaprogramming
Metaprogramming can sometimes be useful, but those situations are rare. As a rough guide, I'd be more likely to use metaprogramming in framework or library code which typically needs to be more generic (e.g. the ActiveModel::AttributeAssignment module in Rails), and to avoid it in application code, which is typically more specific to a particular problem or domain.
Even in library code, I'd prefer the clarity of a few lines of repetition.
Answers to this question are always going to be based on someone's personal opinion so here's mine.
Clarity v Brevity
If you cannot know the set of options ahead of time then you have no real choice but to do as you have. However if the options are drawn from a known set then I would favour clarity over brevity and have explicit methods to set the options. These would also be a good place to add any rdoc etc.
Safety
From a safety perspective, having methods to handle the setting of an option would allow you to perform validation as required.
When you need to do such thing, the inventory of the parameters varies. In such case, there is already a handy structure within Ruby (as well as most modern languages): array and hash. In this case, you should just save the entire option as a single hash. That would make things simpler.
Instead of creating instance variables dynamically, you could use attr_accessor to declare the available instance variables and just call the setters dynamically:
class Foo
attr_accessor :bar, :baz, :qux
def initialize(opts = {})
opts.each do |k, v|
public_send("#{k}=", v)
end
end
end
Foo.new(bar: 1, baz: 2) #=> #<Foo:0x007fa8250a31e0 #bar=1, #baz=2>
Foo.new(qux: 3) #=> #<Foo:0x007facbc06ed50 #qux=3>
This approach also shows an error if an unknown option is passed:
Foo.new(quux: 4) #=> undefined method `quux=' for #<Foo:0x007fd71483aa20> (NoMethodError)
I have a basic structure like this
class Automobile
def some_method
# this code sets up structure for child classes... I want to test this
end
end
class Car < Automobile
def some_method
super
# code specific to Car... it's tested elsewhere so I don't want to test this now
end
end
class CompactCar < Car
def some_method
super
# code specific to CompactCar... I want to test this
end
end
What is the recommended way to test CompactCar and Automobile without running the code from Car? Automobile#some_method provides the structure that is required by child classes, so I want to always test that, but Car's functionality is tested elsewhere and I don't want to duplicate efforts.
One solution is to use class_eval to overwrite Car#some_method, but this isn't ideal because the overwritten method stays in place for the duration of my testing (unless I re-load the original library file with setup/teardown methods... kind of an ugly solution). Also, simply stubbing the call to Car#some_method does not seem to work.
Is there a cleaner/more generally accepted way of doing this?
Just put the specific code into a separate method. You don't appear to be using anything from super. Unless you are?
class CompactCar < Car
def some_method
super
compact_car_specific_code
end
# Test this method in isolation.
def compact_car_specific_code
# code specific to CompactCar... I want to test this
end
end
In the code below, method roar is not defined in class Lion, but still can be called using method_missing.
class Lion
def method_missing(name, *args)
puts "Lion will #{name}: #{args[0]}"
end
end
lion = Lion.new
lion.roar("ROAR!!!") # => Lion will roar: ROAR!!!
In which situations and how should I use this method_missing? And is it safe to use?
It's entirely safe to use provided you use it in expected ways and don't get carried away. Not everything you can do is worth doing, after all.
The advantage of method_missing is you can respond to all kinds of things in unique ways.
The disadvantage is you don't advertise your capabilities. Other objects that expect you to respond_to? something will not get confirmation and might treat your custom object in ways you don't intend.
For building Domain Specific Languages and providing very loose glue between components, this sort of thing is invaluable.
A great example of where this is a good fit is the Ruby OpenStruct class.
Summary: When to use? When it will make your life easier and not complicate others' lives.
Here's one example that pops to mind. It's from redis_failover gem.
# Dispatches redis operations to master/slaves.
def method_missing(method, *args, &block)
if redis_operation?(method)
dispatch(method, *args, &block)
else
super
end
end
Here we check if the method called is actually a command of redis connection. If so, we delegate it to underlying connection(s). If not, relay to super.
Another famous example of method_missing application is ActiveRecord finders.
User.find_by_email_and_age('me#example.com', 20)
There's not, of course, a method find_by_email_and_age. Instead, the method_missing breaks the name, analyzes the parts and invokes find with proper parameters.
Here's a favorite of mine
class Hash
def method_missing(sym,*args)
fetch(sym){fetch(sym.to_s){super}}
end
end
Which lets me access values of a hash as if they were attributes. This is particular handy when working with JSON data.
So for example, rather than having to write tweets.collect{|each|each['text']} I can just write tweets.collect(&:text) which is much shorter. Or also, rather than tweets.first['author'] I can just write tweets.first.author which feels much more natural. Actually, it gives you Javascript-style access to values of a hash.
NB, I'm expecting the monkey patching police at my door any minuteā¦
First and foremost, stick to Sergio Tulentsev's summary.
Apart from that, I think looking at examples is the best way to get a feeling for right and wrong situations for method_missing; so here is another simple example:
I recently made use of method_missing in a Null Object.
The Null Object was a replacement for a Order model.
The Order stores different prices for different currencies.
Without method_missing it looks like this:
class NullOrder
def price_euro
0.0
end
def price_usd
0.0
end
# ...
# repeat for all other currencies
end
With method_missing, I can shorten it to:
class NullOrder
def method_missing(m, *args, &block)
m.to_s =~ /price_/ ? 0.0 : super
end
end
With the added benefit of not having to (remember to) update the NullOrder when I add new price_xxx attributes to Order.
I also found a blog post from (Paolo Perrotta) where it demonstrated when to use method_missing:
class InformationDesk
def emergency
# Call emergency...
"emergency() called"
end
def flights
# Provide flight information...
"flights() called"
end
# ...even more methods
end
Check if a service has been asked during lunch time.
class DoNotDisturb
def initialize
#desk = InformationDesk.new
end
def method_missing(name, *args)
unless name.to_s == "emergency"
hour = Time.now.hour
raise "Out for lunch" if hour >= 12 && hour < 14
end
#desk.send(name, *args)
end
end
# At 12:30...
DoNotDisturb.new.emergency # => "emergency() called"
DoNotDisturb.new.flights # ~> -:37:in `method_missing': Out for lunch (RuntimeError)
Here's the situation:
I have a User model, and two modules for authentication: Oauth and Openid. Both of them override ActiveRecord#save, and have a fair share of implementation logic.
Given that I can tell when the user is trying to login via Oauth vs. Openid, but that both of them have overridden save, how do "finally" override save such that I can conditionally call one of the modules' implementations of it?
Here is the base structure of what I'm describing:
module UsesOauth
def self.included(base)
base.class_eval do
def save
puts "Saving with Oauth!"
end
def save_with_oauth
save
end
end
end
end
module UsesOpenid
def self.included(base)
base.class_eval do
def save
puts "Saving with OpenID!"
end
def save_with_openid
save
end
end
end
end
module Sequencer
def save
if using_oauth?
save_with_oauth
elsif using_openid?
save_with_openid
else
super
end
end
end
class User < ActiveRecord::Base
include UsesOauth
include UsesOpenid
include Sequencer
end
I was thinking about using alias_method like so, but that got too complicated, because I might have 1 or 2 more similar modules. I also tried using those save_with_oauth methods (shown above), which almost works. The only thing that's missing is that I also need to call ActiveRecord::Base#save (the super method), so something like this:
def save_with_oauth
# do this and that
super.save
# the rest
end
But I'm not allowed to do that in ruby.
Any ideas for a clever solution to this?
Is that what alias_method_chain would do? I've avoided that because people seemed to say it was a bad idea.
(Finding things as I go):
Alias Method Chain the Ruby Way
Yes alias method chain would help you in this situation.
But consider using delegate pattern. Original save method would trigger a callback on special delegate object (which can be as well nil) and it would do whatever needs to be done when saving user.
Also there is simliar pattern supported directly by actve record called Observer, try to read somethng about it maybe that's a good solution too.
I'm not saying this chaining methods is wrong, but there are cleaner ways to achieve what you want.
John Nunemaker recently blogged about the various ways to define class methods in Ruby, giving these three alternatives:
# Way 1
class Foo
def self.bar
puts 'class method'
end
end
# Way 2
class Foo
class << self
def bar
puts 'class method'
end
end
end
# Way 3
class Foo; end
def Foo.bar
puts 'class method'
end
What's your preferred way to do this?
Do you prefer something other than those above?
If you use more than one way, under what circumstances do you use them?
I consistently use Way 1:
class Foo
def self.bar
puts 'class method'
end
end
It's not verbose, and it keeps the method in the same context of the class.
I generally prefer def self.foo for single methods, and class << self for long stretches of class methods. I feel it makes the distinction between the class method part and the instance method part of the class definition.
I prefer Way 1 as it isn't context sensitive. I dislike jumping into the middle of a file and then having to scroll up or down to see if the indentation means I'm in a class << self block or if it's just a nested module.
Agree with most of the users. I tend to use primarily the
# Way 1
class Foo
def self.bar
puts 'class method'
end
end
There are some small differences, if I recall correctly, that are shown on the Pragmatic Programmers Metaprogramming talks (which I recommend), which relate to how the class code is called and executed.
They were quite small, though and mostly things we won't have to deal with on a normal basis. Will see if I can check them out and post it.
I view << for adding a method as too unusual (though I happily use << with strings and IO).
I avoid Foo.bar because it means repeating yourself.
I use Way #3, but I think Way #1 is great also. It depends on your usage. If you want your code to be "cut/pastable" into other modules and classes, then Way #1 is better. I use Way #3 to actually make it more of pain to cut/paste code, b/c Ruby's mantra is "don't repeat yourself" so you shouldn't cut/paste code very often..