Differentiate between Module and Class - ruby

The following yields an error:
require 'test/unit'
Test::Unit.setup_argv(["tests"])
$ run_tests.rb:4: undefined method `setup_argv' for Test::Unit:Module (NoMethodError)
How can I make Ruby use the Test::Unit class instead of the Test::Unit module for the method call?
EDIT Ruby 1.8.7

The reason for the error is that setup_argv is not available in Ruby 1.8.7.
Test::Unit is always a module. There is no class.
See the 1.8.7 docs here for how to use:
http://apidock.com/ruby/v1_8_7_330/Test/Unit

Related

Where is SimpleDelegator in Ruby 2.7?

I have been using the SimpleDelegator class for various things. But I noticed, Ruby 2.7 (ArchLinux x86_64) doesn't come with the SimpleDelegator class (no Delegator either).
My program:
#!/usr/bin/ruby -w
class OutputDecorator < SimpleDelegator
def puts(*args)
STDOUT.write "Hello #{args.join}... It's Ruby #{RUBY_VERSION} #{RUBY_PLATFORM}\n"
end
end
$stdout = OutputDecorator.new($stdout)
$stdout.puts('Sourav')
$stdout = $stdout.__getobj__
$stdout.puts('Sourav')
Running with:
Ruby 2.4.6:
> ~/.rvm/rubies/ruby-2.4.6/bin/ruby p.rb
Hello Sourav... It's Ruby 2.4.6 x86_64-linux
Sourav
Ruby 2.5.5:
> ~/.rvm/rubies/ruby-2.5.5/bin/ruby p.rb
Hello Sourav... It's Ruby 2.5.5 x86_64-linux
Sourav
Ruby 2.6.3:
> ~/.rvm/rubies/ruby-2.6.3/bin/ruby p.rb
Hello Sourav... It's Ruby 2.6.3 x86_64-linux
Sourav
Ruby 2.7.0:
> ruby p.rb
Traceback (most recent call last):
p.rb:2:in `<main>': uninitialized constant SimpleDelegator (NameError)
Is there any new alternatives to SimpleDelegator in Ruby 2.7?
The Delegator and SimpleDelegator classes aren't core classes like Array or Mutex. They're part of the delegate standard library which needs to be loaded first: require 'delegate'.
It happened to work in older Ruby versions as they came with an older RubyGems version by default. RubyGems is automatically loaded since Ruby 1.9 and until 3.1.0 that meant delegate was loaded indirectly. Updating RubyGems or running ruby with --disable=gems should cause the exact same issue with Ruby <= 2.6 too. irb also loads several standard libraries: delegate but also timeout and many more.
Programming languages with a similar mechanism like C++ also have this issue: instead of load/require there's #include, including a standard library header might include another one, then a newer version might not include the other header anymore and user code relying on the old behavior fails to compile.

Time methods in Ruby

I'm trying to understand how method invocation works in Ruby objects. Ruby docs list a bunch of methods to execute on ruby objects. When I try one of them
puts RUBY_VERSION
puts Time.new(2008,6,21, 13,30,0, "+09:00").utc.seconds_since_midnight
I get the following output
1.9.3
bin/musor.rb:14:in `<main>': undefined method `seconds_since_midnight' for 2008-06-21 13:30:00 +0900:Time (NoMethodError)
What's wrong with the call I make?
seconds_since_midnight is Time extension added by rails. If you want to use it, you will need to add require 'activesupport/core_ext' and install activesupport gem first.

Ruby Integer and Fixnum unexpexted behavior

I want to use gcd function of the Integer class. Using the example from Ruby Doc as a test it fails:
irb(main):001:0> 72.gcd 168
NoMethodError: undefined method `gcd' for 72:Fixnum
from (irb):1
I have the windows one click installer ruby 1.8.6 (2008-08-11 patchlevel 287) [i386-mswin32]. On other PCs with the same version of ruby this works correctly.
Any ideas?
Try
require 'rubygems'
72.gcd 168
require 'rational'

Why doesn't each_slice work?

I am trying to use the Enumerable#each_slice. It doesn't work on my computer, stating that method is not found.
I am running ruby 1.8.6 (2008-08-11 patchlevel 287) [universal-darwin9.0]
API: http://ruby-doc.org/core/classes/Enumerable.html#M003142
Example:
(1..10).each_slice(3) {|a| p a} # I get NoMethodError: undefined method `each_slice' for 1..10:Range
What am I doing wrong?
In ruby 1.8.6 you have to require 'enumerator' (which is part of stdlib and has been merged into core in 1.8.7+) before using each_slice.
Sadly the ruby-doc lists methods that are added to core classes by stdlib without mentioning where the methods are from.
just compared 1.8.6 to 1.9 and it looks like
(1..10).respond_to? :each_slice
is true in 1.9 and false in 1.8.6. So, the doc you are using is not for 1.8.6. if you can upgrade to a newer version of Ruby easily it should give you that method on the Range.

undefined method ‘bytes’ for for String in Ruby

I am working with ruby 1.8.6 (2007-03-13 patchlevel 0) [x86_64-linux] and I get
undefined method `bytes' for #<String:0x2a95ec2268> (NoMethodError)
even though my code works on ruby 1.8.7. patchlevel 249
I saw somewhere that you need to add require "jcode" for a similar method not defined error with each_byte. I tried adding that but it still does not work. Any suggestions are very appreciated.
In Ruby 1.8.6, you can use my backports gem:
require 'backports/1.8.7/string/bytes'
Ta-da, you now have access to String#bytes.
You also have all the many other changes introduced in 1.8.7. And most of 1.9.1, and all of the upcoming 1.9.2, etc...
Ruby 1.8.6 doesn't have String#bytes. That's a 1.9 addition that was backported to 1.8.7.
You can roughly implement it yourself like this:
class String
require 'enumerator'
def bytes(&block)
return to_enum(:each_byte) unless block_given?
each_byte &block
end
end unless ''.respond_to?(:bytes)
[Note: I haven't checked whether this actually fulfills the contract of String#bytes 100%, but it is close enough for my use.]

Resources