Augmenting the methods with `alias` keyword - ruby

Having reading through The Ruby programming language I found an example of using alias keyword for augmenting the methods.
def hello # A nice simple method
puts 'Hello world' # Suppose we want to augment it...
end
alias original_hello hello # Give the method a backup name
def hello # Now we define a new method with the old name
puts "Your attention please" # That does some stuff
original_hello # Then calls the original method
puts "This has been a test" # Then does some more stuff
end
Indeed original hello preserves the old behavior even after the method the it had been referencing to was redefined.
But, to my mind, this example hardly clarifies the real benefit of this technique. Cannot the same be achieved in traditional way (e.g. by providing the block)? Then why applying this idiom? Can anyone provide an example from the real world when augmenting with alias really makes sense?

Rails code is full of those. Imagine the original hello method does not belong to your code base. Somewhere in 3rd-party library there is do_stuff(stuff) method declared on the class Stuffer.
You want to e.g. debug this method. You reopen the class, define an alias and, voilà:
class Stuffer
alias original_do_stuff do_stuff
def do_stuff(stuff)
puts stuff.inspect
original_do_stuff(stuff)
end
end
Now all the code, including original 3rd party code you might be even not aware about, would print out the parameter passed to every single call to do_stuff.
Real-life example (don’t try this at home and in the school :)
class String
alias _inspect inspect
def inspect
puts "I am a string: “#{_inspect}”"
end
end
"abc".inspect
#⇒ I am a string: “"abc"”

Can anyone provide an example from the real world when augmenting with alias really makes sense?
Not really. Today, you would do this (example taken from #mudasobwa's answer):
module WeirdInspectRefinement
module WeirdInspectExtension
def inspect
"I am a string: “#{super}”"
end
end
refine String do
prepend WeirdInspectExtension
end
end
using WeirdInspectRefinement
p 'abc'.inspect
#⇒ 'I am a string: “"abc"”'
But even before Module#prepend and Refinements existed, there was never a reason to use alias for this, which leaves unused methods around polluting the namespace, and Rails abandoned it quite a while ago:
class String
old_inspect = instance_method(:inspect)
define_method(:inspect) do
"I am a string: “#{old_inspect.bind(self).()}”"
end
end
'abc'.inspect
#⇒ 'I am a string: “"abc"”'

Related

override namespaced puts only works after overriding Kernel.puts?

Sorry for the vague question title, but I have no clue what causes the following:
module Capistrano
class Configuration
def puts string
::Kernel.puts 'test'
end
end
end
Now when Capistrano calls puts, I don't see "test", but I see the original output.
However, when I also add this:
module Kernel
def puts string
::Kernel.puts 'what gives?'
end
end
Now, suddenly, puts actually returns "test", not "what gives?", not the original content, but "test".
Is there a reasonable explanation why this is happening (besides my limited understanding of the inner-workings of Ruby Kernel)?
Things that look off to me (but somehow "seem to work"):
I would expect the first block to return 'test', but it didn't
I would expect the combination of the two blocks to return 'what gives?', but it returns 'test'?
The way I override the Kernel.puts seems like a never-ending loop to me?
module Capistrano
class Configuration
def puts string
::Kernel.puts 'test'
end
def an_thing
puts "foo"
end
end
end
Capistrano::Configuration.new.an_thing
gives the output:
test
The second version also gives the same output. The reason is that you're defining an instance level method rather than a class level method (this post seems to do a good job explaining the differences). A slightly different version:
module Kernel
def self.puts string
::Kernel.puts 'what gives?'
end
end
does the following. Because it is causing infinite recursion, like you expected.
/tmp/foo.rb:14:in `puts': stack level too deep (SystemStackError)
from /tmp/foo.rb:14:in `puts'
from /tmp/foo.rb:4:in `puts'
from /tmp/foo.rb:7:in `an_thing'
from /tmp/foo.rb:18
shell returned 1
I use an answer rather than a comment because of its editing capabilities. You can edit it to add more information and I may delete it later.
Now when Capistrano calls puts, I don't see "test", but I see the
original output.
It's difficult to answer your question without seeing how Capistrano calls puts and which one. I would say it's normal if puts displays its parameter, using the original Kernel#puts (it is not clear what you call original output, I must suppose you mean the string given to puts).
I would expect the first block to return 'test', but it didn't
The only way I see to call the instance method puts defined in the class Configuration in the module Capistrano is :
Capistrano::Configuration.new.puts 'xxx'
or
my_inst_var = Capistrano::Configuration.new
and somewhere else
my_inst_var.puts 'xxx'
and of course it prints test. Again, without seeing the puts statement whose result surprises you, it's impossible to tell what's going on.
I would expect the combination of the two blocks to return 'what gives?', but it returns 'test'?
The second point is mysterious and I need to see the code calling puts, as well as the console output.

RSpec test for a module

I'm brand new to RSpec and TDD. I was wondering if someone might help me with creating a test well-suited for this Module:
module Kernel
# define new 'puts' which which appends "This will be appended!" to all puts output
def puts_with_append *args
puts_without_append args.map{|a| a + "This will be appended!"}
end
# back up name of old puts
alias_method :puts_without_append, :puts
# now set our version as new puts
alias_method :puts, :puts_with_append
end
I'd like for my test to check that the content from a 'puts' ends with "This will be appended!". Would that be a sufficient test? How would I do that?
The best tests test what you're trying to achieve, not how you achieve it... Tying tests to implementation makes your tests brittle.
So, what you're trying to achieve with this method is a change to "puts" whenever your extension is loaded. Testing the method puts_with_append doesn't achieve this goal... If you later accidentally re-alias that to something else, your desired puts change won't work.
However, testing this without using an implementation detail would be rather difficult, so instead, we can try to push the implementation details down to somewhere they won't change, like STDOUT.
Just the Test Content
$stdout.stub!(:write)
$stdout.should_receive(:write).with("OneThis will be appended!")
puts "One"
Full Test
I'm going to turn this into a blog post within the next day or so, but I think you should also consider that you've got a desired result for one and many arguments, and your tests should be easy to read. The ultimate structure I'd use is:
require "rspec"
require "./your_extention.rb"
describe Kernel do
describe "#puts (overridden)" do
context "with one argument" do
it "should append the appropriate string" do
$stdout.stub!(:write)
$stdout.should_receive(:write).with("OneThis will be appended!")
puts "One"
end
end
context "with more then one argument" do
it "should append the appropriate string to every arg" do
$stdout.stub!(:write)
$stdout.should_receive(:write).with("OneThis will be appended!")
$stdout.should_receive(:write).with("TwoThis will be appended!")
puts("One", "Two")
end
end
end
end

How do string literals in ruby bypass new/initialize, and is there a way to instrument this?

I was playing with an idea this afternoon, and stumbled into something I don't quite understand. Basically what I'm trying to achieve in this experiment is to somehow know every time a string is created (for later use, such as in some kind of DSL). The following works fine for any String that is created via String.new:
class ::String
class << self
alias_method :new_orig, :new
def new(*args)
o = new_orig(*args)
puts "newing '#{o}'"
o
end
end
alias_method :initialize_orig, :initialize
def initialize(*args)
initialize_orig(*args)
puts "initializing '#{self}'"
end
end
e.g.
irb > String.new("foo")
initializing 'foo'
newing 'foo'
=> "foo"
What I can't figure out is how a String object is created when you use a literal. For example, why does this not go through the same initialization and setup:
irb > "literal string"
=> "literal string"
I realize that the compiler is doing something or other differently when a string is literal, but doesn't it need to be initialized, simply to be a fully functional object? Are there any tricks that I could use to determine when a string is created using a literal, or is that impossible to do?
Thanks!
I think that from the discussion it follows, that hardly anyone here will give you genuine answer, unless Chris Heald wakes up and actually looks at that source code as he promised. But if, as you say in your comment to your question, the purpose is 'testing the boundaries of what the language can do to have some fun and learn something new', then let me introduce you - as much as I hate SlideShare - to this Ruby presentation by famous esoteric programmer Yusuke Endoh.

Ruby: export variable into local namespace

I want to programmatically insert a new variable into the local Ruby namespace. For example, I want to be able to write
label = 'some_name'
# some code equivalent to
# some_name = 3
# but using only 'label' to get the name.
puts some_name # returns 3
What do I put in the middle here to get this done?
I've answered another SO question similar to this. The short answer is this, if you specifically want to create a local variable with the name of it based on the value of another variable, then there is no way to do it. It you just want to make seem as though you've created a local but it is really ruby magic, then something like #mikong's answer is one way to go.
Note that if you relax your contraint and are happy to create an instance variable instead, then you can do it.
label = 'some_name'
self.instance_variable_set("#{label}", 3)
puts #some_name
You can even dynamically define an accessor and then you can get rid of the unsightly #, but once again you will simply have a method masquerading as a local rather than a real local variable.
The following is not exactly code between the 2 lines that you mentioned above:
class Example
attr_accessor :label
def method_missing(name, *args, &block)
return some_processing if name == label.to_sym
end
def some_processing
3 # of course, this can be something more complicated
end
def test
#label = 'some_name'
puts some_name
end
end
Nonetheless it seems to work with what you need. The mechanism has changed from what you gave (label is now an attribute). Also, technically, it's not a variable but a method with a dynamic name that returns what you need.
Personally, I think your requirements seem a little bit dangerous in that the "variable" name changes. I would probably not use the code in my example. I guess depending on the project requirements, I'll think of a different approach.
label = 'some_name'
eval "#{label} = 3"
puts eval "#{label}"
puts local_variables
Note that you would presumably never have an opportunity to execute...
puts some_name
...because if you knew what local variables you were going to create there would be no need to name them with run-time code. And that's good, because the interpreter will not be able to puts some_name directly because it never parsed an assignment for some_name. But it is there and it is a local, as puts local_variables is able to show.

Use cases for Ruby's EOB construct

I recently came across the Ruby EOB / -EOB construct within this context (from the Ruby id3 library) :
def initialize(...)
# ...
instance_eval <<-EOB
class << self
def parse
# ...
# Method code
# ...
end
EOB
self.parse # now we're using the just defined parsing routine
# ...
end
I understand that the code is used to generate a method on the fly, yet I would like to know if it would be possible to use the EOB snippet within a method. I would like to write a method which generates some other method code , which is to be included in yet another class. This sounds a bit confusing, I'll try to illustrate my intention with some simplified code samples :
# This class reads the code of another
# Ruby class and injects some methods
class ReadAndInject
# The method which defines another method
def get_code_to_be_injected
"\tdef self.foo\n"+
"\t\tputs 'bar'\n"+
"\tend\n"
end
# Main entry point, reads a generated Ruby Class
# and injects specific methods within it
def read_and_inject
# Assume placeholder for currently read line,
# add the generated code within
current_line += "\n#{get_code_to_be_injected}"
end
end # class ReadAndInject
This would work, since the method to be injected is added correctly. Yet I was wondering if using the EOB construct would yield some advantages (e.g. better visibility of the code, since no cumbersome tabs or string concatenations would have to be added.
To conclude, is this a good use case for EOB ?
It seems like a shady yet powerful construct, I've ducked it, googled and stackoverflow'd it yet no significant code samples other than one from RubyCocoa were returned. I've only recently started to use meta constructs in Ruby, so please be gentle :-)
Thanks in advance!
These are called "here documents", which are supported by several languages, and allow you to make a multi-line string. You can actually use any delimiter, not just EOB. Ruby has some extra features for heredocs: for example, the - in <<-EOB allows you to indent the delimiter.
You might use it like this:
def code_to_be_injected
<<-EOS
def self.foo
puts 'bar'
end
EOS
end
Some additional features in Ruby:
myvar = 42
<<EOS
variable: #{myvar}
EOS #=> "variable: 42"
<<'EOS'
variable: #{myvar}
EOS #=> "variable: #{myvar}"
print <<A, <<B
This will appear first
A
and this second
B

Resources