Why does Date exist in Ruby before it is required? - ruby

In Ruby, I'd expect that a class which has not been required would raise an "uninitialized constant" error. This is the case with CSV, for instance.
However, Date behaves strangely: it is available, but apparently does not work, until it is required.
~: irb
>> Date.new(2012,7,24)
ArgumentError: wrong number of arguments(3 for 0)
>> require 'date'
=> true
>> Date.new(2012,7,24)
=> #<Date: 2012-07-24 ((2456133j,0s,0n),+0s,2299161j)>
What explains this behavior?

I believe that date doesn't come from irb, but from rubygems, specifically the file where Gem::Specification is defined:
class Date; end # for ruby_code if date.rb wasn't required
I believe they needed any Date class defined so that the interpreter doesn't complain further down in the Specification class.

Similar to this question. irb loads a Date class by default, but Ruby itself doesn't (try e.g. puts Date.new in a file).
It seems that the Date class that irb loads is different to the distribution class, as you have pointed out. Furthermore this only seems to be the case in Ruby 1.9 -- if I try it in 1.8, I get the same class methods before and after the require.

Partial answer: it seems that the incomplete Date class comes from irb, not from ruby.

Related

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!)

Conflicting output for the same ruby code in irb and pry

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>>

JRuby String Class Methods Not Available

I can't seem to call any of Java's string methods from within JRuby. The same style of syntax work for the Math class though. What am I doing wrong?
#! /usr/bin/env jruby
require 'rubygems'
require 'java'
puts java.lang.Math::max(1000,200)
puts java.lang.Math::PI
# this doesn't work
puts java.lang.String::toUpperCase("we, the people")
# this doesn't work either
JString = java.lang.String
puts JString.toUpperCase('We, the people')
#toUpperCase exists though, see below
puts java.lang.String.java_class.declarSed_instance_methods
I think this is what you are trying to do:
java.lang.String.new("we, the people").toUpperCase
As mentioned by #Jesper, toUpperCase is an instance method with the String class. Using it as a static method will not work.
Also note, the class returned is of native Ruby type.

Ruby / IRB environment issue on MacOSX

I have a ruby script that is failing due to my environment, I think it is demonstrated by this strange behaviour in irb ( I am also using rvm but don't think that is the problem)
>> ruby -v
ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin9.8.0]
>> irb
>> FileUtils.mkdir_p('tmp')
NameError: uninitialized constant FileUtils
from (irb):1
>> help
=> nil
>> FileUtils.mkdir_p('tmp')
=> "tmp"
The FileUtils command initially fails but then after typing Help (which also fails) it seems to work.
I have tried require 'rubygems' and require 'FileUtils' - which does fix the problem - but would like to understand whats happening here.
I didn't know there was a "help" command, but apparently it has dependency on FileUtils, probably to load help files. "help" is loading its requirements into the IRB session.
>> before = ObjectSpace.each_object.map { |i| i.class }.uniq
=> [Regexp, String, Array, Class, Hash, Module, Proc, MatchData, File, Binding, NoMemoryError, Float, SystemStackError, fatal, Bignum, Object, IO, Thread, ThreadGroup, IRB::Locale, IRB::Notifier::LeveledNotifier, IRB::Notifier::CompositeNotifier, IRB::StdioOutputMethod, IRB::Notifier::NoMsgNotifier, Enumerable::Enumerator, RubyToken::TkNL, RubyToken::TkEND, RubyToken::TkBITOR, RubyToken::TkIDENTIFIER, RubyToken::TkDOT, RubyToken::TkRBRACE, RubyToken::TkSPACE, RubyToken::TkfLBRACE, RubyToken::TkCONSTANT, RubyToken::TkASSIGN, IRB::SLex::Node, IRB::SLex, RubyLex, IRB::ReadlineInputMethod, IRB::WorkSpace, IRB::Context, IRB::Irb]
>> help
=> nil
>> after = ObjectSpace.each_object.map { |i| i.class }.uniq
=> [Regexp, String, MatchData, Array, Class, RI::ClassEntry, RI::MethodEntry, Hash, Module, Dir, Proc, File, Binding, NoMemoryError, Float, SystemStackError, fatal, Bignum, Object, IO, Thread, ThreadGroup, IRB::Locale, Range, IRB::Notifier::LeveledNotifier, IRB::Notifier::CompositeNotifier, IRB::StdioOutputMethod, IRB::Notifier::NoMsgNotifier, YAML::Syck::Resolver, Gem::ConfigFile, RubyToken::TkNL, RubyToken::TkIDENTIFIER, IRB::SLex::Node, IRB::SLex, RubyLex, IRB::ReadlineInputMethod, IRB::WorkSpace, IRB::Context, IRB::Irb, RI::TopLevelEntry, RI::RiReader, GetoptLong, RI::RiCache, RI::Options, RiDriver, Rational, Date::Infinity, Enumerable::Enumerator, RubyToken::TkRBRACE, DefaultDisplay, RI::TextFormatter]
>> after == before
=> false
>> after - before
=> [RI::ClassEntry, RI::MethodEntry, Dir, Range, YAML::Syck::Resolver, Gem::ConfigFile, RI::TopLevelEntry, RI::RiReader, GetoptLong, RI::RiCache, RI::Options, RiDriver, Rational, Date::Infinity, DefaultDisplay, RI::TextFormatter]
It loads the classes in after - before. Where is FileUtils you say? I think its a module that is part of Dir, but I am not 100% on that.
You need to require 'fileutils':
require 'fileutils'
FileUtils.pwd # => "/"
It is not included by the interpreter by default, which is why IRB doesn't preload it. Because IRB is interactive, it has to do some things on-the-fly that the interpreter will not, such as load help files. That it does so in response to your request isn't anything unexpected to me, it's just what it was programmed to do. I'm sure if you looked at its code you'd be able to trace it easily enough.
So, basically, all you are seeing is IRB respond correctly to your syntax error, then do what it was told to do in response to your "help" command.
If you absolutely have to know what it's doing, you can figure it out by asking IRB to trace its processing:
echo help | irb -f --trace > irb.out
will generate a tracing of what IRB does when "help" is entered. Searching through the file shows:
#0:/Users/greg/.rvm/rubies/ruby-1.9.2-p136/lib/ruby/1.9.1/rdoc/ri/store.rb:2::-: require 'fileutils'
being required by store.rb as IRB loads 'ri'.
FileUtils is part of the Ruby standard library, so it is bundled with the interpreter, but not included automatically when the interpreter starts, like Dir and File. It is completely standalone, not a part of Dir.

Why am I getting NoMethodError from IRB for my own Module and method

I have taken this example exactly from the Ruby Cookbook. Unfortunately for me, like a whole lot of the examples in that book, this one does not work:
my file (Find.rb - saved both locally and to Ruby\bin):
require 'find'
module Find
def match(*paths)
matched=[]
find(*paths) { |path| matched << path if yield path }
return matched
end
module_function :match
end
I try to call it this way from IRB, according to the example the book provides:
irb(main):002:0> require 'Find'
=> false
irb(main):003:0> Find.match("./") { |p| ext = p[-4...p.size]; ext && ext.downcase == "mp3" }
It SHOULD return a list of mp3 files in my recursive directory. Instead, it does this:
NoMethodError: undefined method `match' for Find:Module
from (irb):3
from C:/Ruby192/bin/irb:12:in `<main>'
What gives? I'm new at this (although I MUST say that I'm farther along with Python, and much better at it!).
How can I get IRB to use my method?
I ran into this with irb on a Mac running Snow Leopard while using the default version of ruby (and irb of course) installed with OS X. I was able to get past it by including the module in IRB after loading the module or in the file after the module definition.
include module_name
I'm not sure if this is a defect or known behavior.
The only explanation is that the code you posted is not the code you are running, since both carefully reading it and simply cut&paste&running it shows absolutely no problems whatsoever.
What directory are you calling IRB from? Try calling it from the directory where your find.rb file is located. Also, I don't know if it makes any difference but convention is to name the file the lowercase version of the module / class. So the module would be Find and the file name would be find.rb. You shouldn't need the require call in the file itself.
So, start your command prompt window, cd into the directory that contains find.rb and run irb. In IRB you should be able to require "find" and it should return true. From there you should be able to call Find.match.
I know this question is already 3 years old, but since this is the first hit on google for the problem, and I had been banging my head against the wall all afternoon with the same problem doing the tutorial here: http://ruby.learncodethehardway.org/book/ex25.html, here goes: the function definition in the module should read
module Find
def Find.match(*paths)
...
end
end

Resources