Conflicting output for the same ruby code in irb and pry - ruby

I do the following in irb and have also tried out the same code in pry
class Number < Struct.new(:value)
end
class Number
def to_s
value.to_s
end
def inspect
"<<#{self}>>"
end
end
Now, if i do Number.new(2), it correctly returns <<2>> in irb, but in pry it incorrectly returns #<struct Number value=2> . Why is this so ?
Thank You

I'm not very familiar with pry (I've never used it until just now), but the obvious answer to your question is: because pry isn't calling inspect on your object. You can manually call it, and it works as expected:
Number.new(2).inspect
# => "<<2>>"
My question was: why isn't pry calling inspect, and what's it doing instead? Looking at the code, it looks like it calls pretty_inspect instead. There may be a smarter workaround, but the simplest thing that comes to mind for me is to just alias pretty_inspect to inspect for Number:
class Number
alias_method :pretty_inspect, :inspect
end
Number.new(2)
# => <<2>>

Related

Ruby 2.3.1 has a bug in `Module#alias` and `Module#alias_method`?

Consider the following code:
module M
def original ; puts __callee__ ; end
alias_method :aliased, :original
end
class A
include M
end
A.new.original
#⇒ original
A.new.aliased
#⇒ aliased
The above code runs perfectly fine in Ruby 2.1 and returns the actual method name, as it is supposed to be done by Kernel#__callee__.
Surprisingly enough, the code above does not work as expected in Ruby 2.3.1:
A.new.original
#⇒ original
A.new.aliased
#⇒ original
Is this a desired behaviour I failed to find in release notes, or is it a bug in MRI for 2.3? The same happens for alias.
PS I have created an issue https://bugs.ruby-lang.org/issues/12761

Check if a method is an alias to another method in rspec

Article#to_archive is an alias for Article#archived!:
class Article
alias to_archive archived!
end
I need to ensure this, so I wrote this test:
describe '#to_archive' do
it 'is an alias to #archived!' do
expect(subject.method(:to_archive)).to eq(subject.method(:archived!))
end
end
However, I receive an error
Failure/Error: expect(subject.method(:to_archive)).to eq(subject.method(:archived!))
expected: #<Method: Article(#<Module:0x00000005a7c240>)#archived!>
got: #<Method: Article(#<Module:0x00000005a7c240>)#to_archive(archived!)>
It used to work in ruby < 2.3 IIRC. I tried alias_method, but it didn't help.
The definition of Method#== is not clear and/or useful, so you shouldn't rely on it.
To check that it is an alias, you can do this:
expect(subject.method(:to_archive).original_name).to eq(:archived!)

attr_reader only working in some environments

This applies also to attr_writer and attr_accessor.
I've been playing with some simple Ruby code recently and the following snippet does not work in all environments I've run it:
class Human
attr_reader :name
def initialize(name)
#name = name
end
end
hank = Human.new("Hank")
hank.name
This should output "Hank", which it does in my command line irb. In Textmate2 and Aptana Studio 3, nothing outputs when I run this code. All three work as expected if I explicitly define the reader:
def name
puts #name
end
When I play in the Aptana terminal and my usual terminal and type:
$ ruby -v
They both appear to use the same version: ruby 2.0.0p451. What's going on?
attr_reader just doesn't do what you think it does.
try
puts hank.name
rather than
hank.name
and you'll see the output. irb is a special case, it shows you the return value of the last statement executed. ruby on its own won't do that, it only prints things you explicitly tell it to print.

How do you disable awesome_print once enabled in IRB or rails console?

I have awesome_print configured to be my default formatter in IRB (using AwesomePrint.irb! in my .irbrc) and while this is normally awesome, I want to turn it off sometimes. Anybody know how to from a running IRB/Rails console?
You can paste this in to you terminal to reset it back to what it was originally if you like:
IRB::Irb.class_eval do
def output_value # :nodoc:
printf #context.return_format, #context.inspect_last_value
end
end
or you can go whole hog and monkey patch AwesomePrint:
module AwesomePrint
def self.un_irb!
IRB::Irb.class_eval do
def output_value # :nodoc:
printf #context.return_format, #context.inspect_last_value
end
end
end
end
Then just call it whenever you want: AwesomePrint.un_irb!

Ruby methods at bottom of script?

I'm using ruby 1.8.7. I could have sworn that I've written my functions at the bottom of my script before and it worked fine.
Do I have to put them at the top? It seems to be the only way they work now. Not a big deal. I just prefer to have them at the bottom so I figured I'd ask.
You can do initializing code in one or more BEGIN-blocks (inherited from Perl, which inherited them from awk).
can_i_do_this? #=>yes
BEGIN {
def can_i_do_this?
puts "yes"
end
}
And for completeness, there are also END-blocks:
END {
can_i_do_this? #=> yes
}
def can_i_do_this?
puts "yes"
end
a
def a
puts "Hello world!"
end
Running this script in Ruby will give you:
script.rb:1:in `<main>': undefined local variable or method `a' for main:Object (NameError)
So no, you can't have them at the bottom. As Ruby is an interpreted language, any code is parsed and processed at runtime ONLY. Therefore, you can only run code (call methods, use variables...) that have already been defined prior to the actual reference.

Resources