Does Ruby 1.8 have an equivalent to 1.9's __callee__? - ruby

I need to grab the name of the lexically enclosing method in Ruby 1.8; e.g.
def foo
this_method = __callee__ # => 'foo'
end
The above code is valid in Ruby 1.9, but fails in 1.8, since __callee__ was introduced in 1.9.
Any suggestions for doing this in 1.8? Kernel#caller looked promising, but seems to give me the call stack starting with the caller of the method, not the method itself.
I guess I could throw an exception, catch it, and grab the first element in the Exception#backtrace array, but my gut tells me that will be slow.

On Ruby 1.8.7 there is the __method__, not sure about 1.8.6.
Anyway, You can monkey patch the Kernel module:
module Kernel
# Defined in ruby 1.9
unless defined?(__callee__)
def __callee__
caller[0] =~ /`([^']*)'/ and $1
end
end
end

Have you checked whether the "backports" gem has it?

Related

Disable did_you_mean gem from within a script

I read that you can disable the did_you_mean gem (which is enabled by default) via the Ruby command line like so:
ruby --disable-did_you_mean script.rb
Is there a way to the same from within script.rb instead of the command line parameter?
The gem works by monkey patching NameError, and prepending DidYouMean::Correctable to its ancestors.
NameError.ancestors
#=> [DidYouMean::Correctable, NameError, StandardError, Exception, Object, Kernel, BasicObject]
You can work around this by redefining DidYouMean::Correctable#to_s as Wand Maker suggested, or you can remove the method from the module altogether:
module DidYouMean::Correctable
remove_method :to_s
end
which has the same outcome.
You can undo the module definition of DidYouMean by re-implementing in your script.rb, wherein you delegate the error handler to original Ruby implementation.
# Beginning of script.rb
module DidYouMean
module Correctable
prepend_features NameError
def to_s
super
end
end
end
ary = [1,2]
ary.att(0)
#=> undefined method `att' for [1, 2]:Array
# (repl):15:in `<main>'

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

Array#to_s in Ruby 2.1 broke my code

This code broke on Ruby 2.1
class Test
def to_s()
"hi"
end
end
puts [Test.new(), Test.new()].to_s
Ruby 1.9.3:
$ ruby --version
ruby 1.9.3p484 (2013-11-22 revision 43786) [x86_64-linux]
$ /opt/chef/embedded/bin/ruby test.rb
[hi, hi]
Ruby 2.1:
$ ruby --version
ruby 2.1.4p265 (2014-10-27 revision 48166) [x86_64-linux]
$ ruby test.rb
[#<Test:0x000000022ac400>, #<Test:0x000000022ac3d8>]
Is this documented somewhere? How can the old behavior be preserved?
Your code:
puts [Test.new(), Test.new()].to_s
is a questionable use of Array.to_s. Instead I'd use:
puts [Test.new(), Test.new()].map(&:to_s)
While I can see that the first use makes sense, the second use makes more sense and should work in any version of Ruby.
On ruby 2.1.5:
class Test
def to_s
"hi"
end
alias inspect to_s # add this line
end
puts [Test.new, Test.new].to_s
#=> [hi, hi]
This seems like a bug to me. If it is intended behavior, that is really annoying.
You don't need to_s. puts does the work for you
puts [Test.new(), Test.new()]
# hi
# hi
If you want the brackets, that's what inspect is for (in which case it makes sense that you would need to define Test#inspect).

Does an equivalent to prepend method exist in ruby 1.9.3?

I need to use the prepend method, introduced in ruby 2.0, in ruby 1.9.3, where this method is not supported. Is there an equivalent method in ruby 1.9.3?
UPDATE
I need this working with ruby 1.9.3
module ActiveAdmin::Views::Pages::BaseExtension
def add_classes_to_body
super
#body.set_attribute "ng-app", "MyApp" #I need to add this line
end
end
class ActiveAdmin::Views::Pages::Base
prepend ActiveAdmin::Views::Pages::BaseExtension
end
prepend changes the core Ruby object model, specifically the way messages are dispatched, there is no way to do this in pure Ruby, therefore, there is no way to backport the prepend functionality.
In the bad old days before prepend we used to do this instead:
class ActiveAdmin::Views::Pages::Base
orig = instance_method(:add_classes_to_body)
define_method(:add_classes_to_body) do
orig.bind(self).()
#body.set_attribute "ng-app", "MyApp"
end
end
I could make it work using alias_method
class ActiveAdmin::Views::Pages::Base
alias_method :old_add_classes_to_body, :add_classes_to_body
def add_classes_to_body
old_add_classes_to_body
#body.set_attribute "ng-app", "MyApp"
end
end

Why begin/rescue/else behaves differently on 1.9.2 and 1.8.7

I am working with the method mm. In ruby 1.9.2 it behaves weird, instead of the expected result 1.9.2=>10 I am getting
ELSE **
1.9.2=>8
Any idea of what is going on?
class A
def mm(data)
begin
send_len = data
return send_len
rescue Exception
STDOUT.write("Rescue *#{$!}*\n")
else
STDOUT.write("ELSE *#{$!}*\n")
end
end
end # class A
a = A.new
print "#{RUBY_VERSION}=>#{a.mm(10)}\n"
With 1.8.7 I get the expected result:
1.8.7=>10
It's an open bug in Ruby. There is a discussion, though, whether it should behave like it behaved in 1.8 or as it does in 1.9.
Matz, the author of Ruby, believes that it should behave as in 1.8.

Resources