Ruby 1.9.1 with rspec "can't modify frozen object" - ruby

I just updated to Ruby 1.9.1 and nearly all my rspec are broken giving me a "can't modify frozen object". Even the Rspec sample code from a generate rspec_controller fails.
RuntimeError in 'DownloadsController should use DownloadsController'
can't modify frozen object
/usr/local/lib/ruby19/1.9.1/timeout.rb:44:in `timeout'
Generated by the following code:
it "should use DownloadsController" do
controller.should be_an_instance_of(DownloadsController)
end
Can anyone help ?

Are you use you aren't trying to stub something that is nil.
In 1.8 nil wasn't frozen. It is however frozen in ruby 1.9.

Try opening /usr/local/lib/ruby19/1.9.1/timeout.rb and replace line 44 with the following:
begin
return yield(sec) if sec == nil or sec.zero?
rescue => e
puts e.backtrace.join("\n")
raise e
end
Though this seems odd, in some cases I've found that this gives me more detailed information on the actual source of the problem. If you still don't know how to fix the problem, paste your results here and maybe it will help us track down the issue.

Related

#inspect on BasicObject oddity

The following happens when inheriting from BasicObject:
class Test < BasicObject
def inspect
"foobar"
end
end
test = Test.new
test.inspect
# => "foobar"
test
(Object doesn't support #inspect)
=>
Is it possible to implement inspect in a way for it to behave normally in IRB?
It's a bug in IRb, or more precisely, in IRB::ColorPrinter#pp:
def pp(obj)
if obj.is_a?(String)
# Avoid calling Ruby 2.4+ String#pretty_print that splits a string by "\n"
text(obj.inspect)
else
super
end
end
BasicObject does not have is_a?, so this will raise a NoMethodError exception. Any exception raised by an IRb Inspector, in turn, is treated the same, regardless of cause and origin:
# Proc to call when the input is evaluated and output in irb.
def inspect_value(v)
#inspect.call(v)
rescue
puts "(Object doesn't support #inspect)"
''
end
This is a combination of two anti-patterns: explicit inheritance checking and Pokemon exception handling. Hey, nobody ever claimed the Ruby standard library is an example of good code. (And nobody ever claimed IRb is a good REPL either.)
The fact that this error-swallowing behavior is misleading was already filed as a bug a month ago:
It seems like IRB::Inspector#inspect_value can swallow errors and then only provides a misleading and unhelpful message (Object doesn't support #inspect).
There is actually a Pull Request which addresses this bug report and improves this very error message and would have immediately told you what is going wrong. In fact, the example the Bug Report and the Pull Request uses to motivate the change is literally your problem: an object that doesn't respond to is_a?:
Before
irb(main):001:0> c = Cat.new "foo"
(Object doesn't support #inspect)
After
irb(main):001:0> c = Cat.new "foo"
An error occurred when inspecting the object: #<NoMethodError: > undefined method `is_a?' for foo:Cat
if obj.is_a?(String)
^^^^^^>
Result of Kernel#inspect: #<Cat:0x0000000109090d80 #name="foo">
However, the Bug Report and the Pull Request are only about the error message, they do not address the error itself, which could be addressed by using Module#=== instead of Object#is_a?.

Implied exception class difference between version of ruby

Sorry for the strange title, I'm not really sure how to classify this issue. I'm in the process of updating some ruby code to 1.9.3, and am seeing some strange behavior. Distilling the issue, I get:
def convert(exception)
raise exception.message
end
begin
convert(StandardError.new(StandardError))
rescue => e
puts e.class
end
In 1.9.2, the output is
StandardError
and in 1.9.3, te output is
RuntimeError
Looking though the ruby docs and release notes hasn't really given me any clues as to what could be going on here, and any help is appreciated!
The issue seems to be that prior to 1.9.3, Exception#message returned an object of class Class, not String, which causes weird things to happen and it ends up raising an exception with an unexpected class (i.e., not RuntimeError).
This bug was fixed in this commit, and it is present in the 1.9.3 changelog.
Ultimately, you do want to raise exception, not raise exception.message.

Require an unknown constant and continue

I'm trying to create "autorequire" for a package, namely if Ruby encounters an unknown constant it tries to require it, and continues where it left off if the require succeeds. Now I have something like this:
def autoload(&block)
yield
rescue NameError => e
if e.message[/constant/]
require e.name.to_s.downcase rescue LoadError raise
retry
end
raise
end
So if I use this like
autoload {
print "Hello, "
x = ArrayFields.new
x << "World!"
puts x[0]
}
As expected, it will print Hello, Hello, World!. So it handles the requiring of the constant, but executes the entire given block from the beginning. So how do I skip to where the fail occurred? This is mostly for academic interest, so I'm also interested in any dangers in attempts like this.
It is not possible to jump back to the point right before the exception from a rescue-clause. A more feasible approach to do what you want would be to override const_missing.
Ruby has autoload, which will exist in Ruby 2.0 at least.

Does IronRuby have an issue with each_for_index?

I'm working on some stuff in IronRuby, but I've run into a bit of a snag. This chunk of code:
def func
b = #b
b.each_with_index do |element, index|
<some stuff in here>
end
end
gives the following error:
./myfile.rb:<line number>:in 'func': wrong number of arguments (0 for 1) (ArgumentError)
from IronRuby.Libraries:0:in '<EachWithIndex>b__9'
from IronRuby.Libraries:0:in 'each'
from IronRuby.Libraries:0:in 'Each'
from ./myfile.rb:<line number>:in 'each_with_index'
from ./myfile.rb:<line number>:in 'func'
Am I doing anything wrong here? I'm using IronRuby 1.0 (the .NET 2.0 version). It's probably something ridiculously obvious, but I just haven't been able to find the answer.
As a note: I've thrown a bunch of puts statements in there, and b is definitely an Array, so it's not like I'm trying to do this on something it shouldn't work on.
Ah, I figured it out, IronRuby targets Ruby 1.8.6, and apparently each_for_index didn't return an enumerator in 1.8.6. I've changed it to:
require 'enumerator'
b.enum_for(:each_with_index) do |element, index|
and it seems to work fine.

Ruby Koan: test_nil_is_an_object

I have recently tried sharpening my rails skills with this tool:
http://github.com/edgecase/ruby_koans
but I am having trouble passing some tests. Also I am not sure if I'm doing some things correctly since the objective is just to pass the test, there are a lot of ways in passing it and I may be doing something that isn't up to standards.
Is there a way to confirm if I'm doing things right?
a specific example:
in about_nil,
def test_nil_is_an_object
assert_equal __, nil.is_a?(Object), "Unlike NULL in other languages"
end
so is it telling me to check if that second clause is equal to an object(so i can say nil is an object) or just put assert_equal true, nil.is_a?(Object) because the statement is true?
and the next test:
def test_you_dont_get_null_pointer_errors_when_calling_methods_on_nil
# What happens when you call a method that doesn't exist. The
# following begin/rescue/end code block captures the exception and
# make some assertions about it.
begin
nil.some_method_nil_doesnt_know_about
rescue Exception => ex
# What exception has been caught?
assert_equal __, ex.class
# What message was attached to the exception?
# (HINT: replace __ with part of the error message.)
assert_match(/__/, ex.message)
end
end
Im guessing I should put a "No method error" string in the assert_match, but what about the assert_equal?
assert_equal true, nil.is_a?(Object) is indeed the correct solution. The question is "Are nils in Ruby objects or not?", and in Ruby's case, they are. Thus, in order to pass the assertion, you should assert the truth of that test.
In the second example, when you call an undefined method on nil, you get NoMethodError: undefined method 'foo' for nil:NilClass. Thus, the exception class is NoMethodError, and the message is undefined method 'foo' for nil:NilClass. Test the failing behavior in a console, and see what you get from it, and then apply that knowledge to the test.
Are you running
ruby path_to_enlightenment.rb
at the command prompt after you correct each test? It will give you lots of help.
Also "remember that silence is sometimes the best answer" -- if you are stumped don't put in anything and the tool will help you.
Well, in holding with the typical TDD motto of Red-Green-Refactor, you should run the test (probably with rake in a separate console) and see the failure happen. From there, they have provided you a few pieces of information about what was expected.
As for style, the koans aren't really teaching that. You should just find and read some code written in ruby to get a feel for the typical conventions and idioms of the ruby community.
Simplicity is the key with Ruby Koans - when I started it I thought it must be harder than what it is, but it's not! Just ask IRB the question Koans is asking you, and after a few you get a feel for it. I've written a blog piece about it to help others, too:
Ruby Koans Answers
I remember when I did this that I tried to out think the test and tried to put in
<Answer> and <"Answer">
The thing to remember is that the actual class doesn't have to be in a string or something.
So the answer is NOT
ex.class, ex.class
As suggested above, put the code into irb and execute it.
(1..5).class == Range
is a big hint

Resources