The behavior of String#squeeze and String#squeeze! changes from 1.8 to 1.9. You can see the difference in the two code samples below.
irb(main):009:0> `ruby -v`
=> "ruby 1.8.7 (2011-06-30 patchlevel 352) [i686-darwin11.1.0]\n"
irb(main):010:0> s = '--subbookkeeper--'
=> "--subbookkeeper--"
irb(main):011:0> s.squeeze 'z-a'
=> "--subbookkeeper--"
irb(main):012:0> s.squeeze! 'z-a'
=> nil
irb(main):001:0> `ruby -v`
=> "ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-darwin11.1.0]\n"
irb(main):002:0> s = '--subbookkeeper--'
=> "--subbookkeeper--"
irb(main):003:0> s.squeeze 'z-a'
ArgumentError: invalid range "z-a" in string transliteration
from (irb):3:in `squeeze'
from (irb):3
from /Users/charlietanksley/.rbenv/versions/1.9.2-p290/bin/irb:12:in `<main>'
irb(main):004:0> s.squeeze! 'z-a'
ArgumentError: invalid range "z-a" in string transliteration
from (irb):4:in `squeeze!'
from (irb):4
from /Users/charlietanksley/.rbenv/versions/1.9.2-p290/bin/irb:12:in `<main>'
Rubinius, of course, works like 1.8:
irb(main):008:0> `ruby -v`
=> "rubinius 1.2.4 (1.8.7 release 2011-07-05 JI) [x86_64-apple-darwin11.1.0]\n"
irb(main):009:0> s = '--subbookkeeper--'
=> "--subbookkeeper--"
irb(main):010:0> s.squeeze 'z-a'
=> "--subbookkeeper--"
irb(main):011:0> s.squeeze! 'z-a'
=> nil
irb(main):004:0> `ruby -v`
=> "rubinius 2.0.0dev (1.8.7 6d095fd3 yyyy-mm-dd JI) [x86_64-apple-darwin11.1.0]\n"
irb(main):005:0> s.squeeze 'z-a'
=> "--subbookkeeper--"
irb(main):006:0> s.squeeze! 'z-a'
=> nil
Now here is the puzzling thing. I added a pair of specs to make sure String#squeeze! worked right in 1.8 and 1.9:
ruby_version_is "1.8" ... "1.9" do
it "returns nil when the parameter is out of sequence" do
s = "--subbookkeeper--"
s.squeeze!("e-b").should == nil
s.squeeze!("^e-b").should == nil
end
end
ruby_version_is "1.9" do
it "raises an error when the parameter is out of sequence" do
s = "--subbookkeeper--"
lambda { s.squeeze!("e-b") }.should raise_error(ArgumentError)
lambda { s.squeeze!("^e-b") }.should raise_error(ArgumentError)
end
end
The 1.9 test passes, as it should:
$ bin/mspec -tx19 spec/ruby/core/string/squeeze_spec.rb
rubinius 2.0.0dev (1.9.2 9fe902c0 yyyy-mm-dd JI) [x86_64-apple-darwin11.1.0]
.............
Finished in 0.143006 seconds
1 file, 13 examples, 48 expectations, 0 failures, 0 errors
But the 1.8 test fails:
$ bin/mspec spec/ruby/core/string/squeeze_spec.rb
rubinius 2.0.0dev (1.8.7 9fe902c0 yyyy-mm-dd JI) [x86_64-apple-darwin11.1.0]
...........F.
1)
String#squeeze! returns nil when the parameter is out of sequence FAILED
Expected "-subokeper-"
to equal nil
/expectations.rb:15
{ } in Object#__script__ at spec/ruby/core/string/squeeze_spec.rb:111
Kernel(Object)#instance_eval at kernel/common/eval18.rb:43
{ } in Enumerable(Array)#all? at kernel/common/enumerable.rb:235
Array#each at kernel/bootstrap/array.rb:66
Enumerable(Array)#all? at kernel/common/enumerable.rb:235
Array#each at kernel/bootstrap/array.rb:66
Object#__script__ at spec/ruby/core/string/squeeze_spec.rb:93
Kernel.load at kernel/common/kernel.rb:687
Kernel(Object)#instance_eval at kernel/common/eval18.rb:43
Array#each at kernel/bootstrap/array.rb:66
Rubinius::CodeLoader#load_script at kernel/delta/codeloader.rb:65
Rubinius::CodeLoader.load_script at kernel/delta/codeloader.rb:107
Rubinius::Loader#script at kernel/loader.rb:618
Rubinius::Loader#main at kernel/loader.rb:772
Finished in 0.076269 seconds
1 file, 13 examples, 48 expectations, 1 failure, 0 errors
So in irb '--subbookkeeper--'.squeeze! 'z-a'
returns nil
, as it should. But in the test it returns "-subokeper-"
. This is doubly confusing to me because the spec for 1.8 says the non-bang String#squeeze with a backward range should simply return the string with no changes, and that test passes, even though the bang method is used to define the non-bang method.