Searches sep or pattern (regexp) in the string and returns the part before it, the match, and the part after it. If it is not found, returns two empty strings and str.
"hello".partition("l") #=> ["he", "l", "lo"] "hello".partition("x") #=> ["hello", "", ""] "hello".partition(/.l/) #=> ["h", "el", "lo"]
Returns two arrays, the first containing the elements of enum for which the block evaluates to true, the second containing the rest.
If no block is given, an enumerator is returned instead.
(1..6).partition { |v| v.even? } #=> [[2, 4, 6], [1, 3, 5]]
Continuation
objects are generated by Kernel#callcc
, after having +require+d continuation. They hold a return address and execution context, allowing a nonlocal return to the end of the callcc
block from anywhere within a program. Continuations are somewhat analogous to a structured version of C’s setjmp/longjmp
(although they contain more state, so you might consider them closer to threads).
For instance:
require "continuation" arr = [ "Freddie", "Herbie", "Ron", "Max", "Ringo" ] callcc{|cc| $cc = cc} puts(message = arr.shift) $cc.call unless message =~ /Max/
produces:
Freddie Herbie Ron Max
Also you can call callcc in other methods:
require "continuation" def g arr = [ "Freddie", "Herbie", "Ron", "Max", "Ringo" ] cc = callcc { |cc| cc } puts arr.shift return cc, arr.size end def f c, size = g c.call(c) if size > 1 end f
This (somewhat contrived) example allows the inner loop to abandon processing early:
require "continuation" callcc {|cont| for i in 0..4 print "\n#{i}: " for j in i*5...(i+1)*5 cont.call() if j == 17 printf "%3d", j end end } puts
produces:
0: 0 1 2 3 4 1: 5 6 7 8 9 2: 10 11 12 13 14 3: 15 16
ConditionVariable
objects augment class Mutex. Using condition variables, it is possible to suspend while in the middle of a critical section until a resource becomes available.
Example:
require 'thread' mutex = Mutex.new resource = ConditionVariable.new a = Thread.new { mutex.synchronize { # Thread 'a' now needs the resource resource.wait(mutex) # 'a' can now have the resource } } b = Thread.new { mutex.synchronize { # Thread 'b' has finished using the resource resource.signal } }
Raised to stop the iteration, in particular by Enumerator#next
. It is rescued by Kernel#loop
.
loop do puts "Hello" raise StopIteration puts "World" end puts "Done!"
produces:
Hello Done!
Descendants of class Exception
are used to communicate between Kernel#raise
and rescue
statements in begin ... end
blocks. Exception
objects carry information about the exception – its type (the exception’s class name), an optional descriptive string, and optional traceback information. Exception
subclasses may add additional information like NameError#name
.
Programs may make subclasses of Exception
, typically of StandardError
or RuntimeError
, to provide custom classes and add additional information. See the subclass list below for defaults for raise
and rescue
.
When an exception has been raised but not yet handled (in rescue
, ensure
, at_exit
and END
blocks) the global variable $!
will contain the current exception and $@
contains the current exception’s backtrace.
It is recommended that a library should have one subclass of StandardError
or RuntimeError
and have specific exception types inherit from it. This allows the user to rescue a generic exception type to catch all exceptions the library may raise even if future versions of the library add new exception subclasses.
For example:
class MyLibrary class Error < RuntimeError end class WidgetError < Error end class FrobError < Error end end
To handle both WidgetError and FrobError the library user can rescue MyLibrary::Error.
The built-in subclasses of Exception
are:
StandardError
– default for rescue
fatal – impossible to rescue
Raised when a signal is received.
begin Process.kill('HUP',Process.pid) sleep # wait for receiver to handle signal sent by Process.kill rescue SignalException => e puts "received Exception #{e}" end
produces:
received Exception SIGHUP
BigDecimal
extends the native Rational
class to provide the to_d
method.
When you require BigDecimal
in your application, this method will be available on Rational
objects.
A rational number can be represented as a paired integer number; a/b (b>0). Where a is numerator and b is denominator. Integer
a equals rational a/1 mathematically.
In ruby, you can create rational object with Rational
, to_r
, rationalize method or suffixing r to a literal. The return values will be irreducible.
Rational(1) #=> (1/1) Rational(2, 3) #=> (2/3) Rational(4, -6) #=> (-2/3) 3.to_r #=> (3/1) 2/3r #=> (2/3)
You can also create rational object from floating-point numbers or strings.
Rational(0.3) #=> (5404319552844595/18014398509481984) Rational('0.3') #=> (3/10) Rational('2/3') #=> (2/3) 0.3.to_r #=> (5404319552844595/18014398509481984) '0.3'.to_r #=> (3/10) '2/3'.to_r #=> (2/3) 0.3.rationalize #=> (3/10)
A rational object is an exact number, which helps you to write program without any rounding errors.
10.times.inject(0){|t,| t + 0.1} #=> 0.9999999999999999 10.times.inject(0){|t,| t + Rational('0.1')} #=> (1/1)
However, when an expression has inexact factor (numerical value or operation), will produce an inexact result.
Rational(10) / 3 #=> (10/3) Rational(10) / 3.0 #=> 3.3333333333333335 Rational(-8) ** Rational(1, 3) #=> (1.0000000000000002+1.7320508075688772i)
Helper module for easily defining exceptions with predefined messages.
1.
class Foo extend Exception2MessageMapper def_e2message ExistingExceptionClass, "message..." def_exception :NewExceptionClass, "message..."[, superclass] ... end
2.
module Error extend Exception2MessageMapper def_e2message ExistingExceptionClass, "message..." def_exception :NewExceptionClass, "message..."[, superclass] ... end class Foo include Error ... end foo = Foo.new foo.Fail ....
3.
module Error extend Exception2MessageMapper def_e2message ExistingExceptionClass, "message..." def_exception :NewExceptionClass, "message..."[, superclass] ... end class Foo extend Exception2MessageMapper include Error ... end Foo.Fail NewExceptionClass, arg... Foo.Fail ExistingExceptionClass, arg...
Potentially raised when a specification is validated.
FIXME: This isn’t documented in Nutshell.
Since MonitorMixin.new_cond
returns a ConditionVariable
, and the example above calls while_wait and signal, this class should be documented.
POP3
authentication error.
Represents an SMTP
authentication error.
Raised when a feature is not implemented on the current platform. For example, methods depending on the fsync
or fork
system calls may raise this exception if the underlying operating system or Ruby runtime does not support them.
Note that if fork
raises a NotImplementedError
, then respond_to?(:fork)
returns false
.
A generic error class raised when an invalid operation is attempted.
[1, 2, 3].freeze << 4
raises the exception:
RuntimeError: can't modify frozen Array
Kernel.raise
will raise a RuntimeError
if no Exception
class is specified.
raise "ouch"
raises the exception:
RuntimeError: ouch
DateTime
A subclass of Date
that easily handles date, hour, minute, second and offset.
DateTime
does not consider any leap seconds, does not track any summer time rules.
DateTime
object is created with DateTime::new
, DateTime::jd
, DateTime::ordinal
, DateTime::commercial
, DateTime::parse
, DateTime::strptime
, DateTime::now
, Time#to_datetime
or etc.
require 'date' DateTime.new(2001,2,3,4,5,6) #=> #<DateTime: 2001-02-03T04:05:06+00:00 ...>
The last element of day, hour, minute or second can be fractional number. The fractional number’s precision is assumed at most nanosecond.
DateTime.new(2001,2,3.5) #=> #<DateTime: 2001-02-03T12:00:00+00:00 ...>
An optional argument the offset indicates the difference between the local time and UTC. For example, Rational(3,24)
represents ahead of 3 hours of UTC, Rational(-5,24)
represents behind of 5 hours of UTC. The offset should be -1 to +1, and its precision is assumed at most second. The default value is zero(equals to UTC).
DateTime.new(2001,2,3,4,5,6,Rational(3,24)) #=> #<DateTime: 2001-02-03T04:05:06+03:00 ...>
also accepts string form.
DateTime.new(2001,2,3,4,5,6,'+03:00') #=> #<DateTime: 2001-02-03T04:05:06+03:00 ...>
An optional argument the day of calendar reform (start) denotes a Julian day number, which should be 2298874 to 2426355 or -/+oo. The default value is Date::ITALY
(2299161=1582-10-15).
DateTime
object has various methods. See each reference.
d = DateTime.parse('3rd Feb 2001 04:05:06+03:30') #=> #<DateTime: 2001-02-03T04:05:06+03:30 ...> d.hour #=> 4 d.min #=> 5 d.sec #=> 6 d.offset #=> (7/48) d.zone #=> "+03:30" d += Rational('1.5') #=> #<DateTime: 2001-02-04%16:05:06+03:30 ...> d = d.new_offset('+09:00') #=> #<DateTime: 2001-02-04%21:35:06+09:00 ...> d.strftime('%I:%M:%S %p') #=> "09:35:06 PM" d > DateTime.new(1999) #=> true
DateTime
and when should you use Time
? It’s a common misconception that William Shakespeare and Miguel de Cervantes died on the same day in history - so much so that UNESCO named April 23 as World Book Day because of this fact. However because England hadn’t yet adopted Gregorian Calendar Reform (and wouldn’t until 1752) their deaths are actually 10 days apart. Since Ruby’s Time
class implements a proleptic Gregorian calendar and has no concept of calendar reform then there’s no way to express this. This is where DateTime
steps in:
shakespeare = DateTime.iso8601('1616-04-23', Date::ENGLAND) #=> Tue, 23 Apr 1616 00:00:00 +0000 cervantes = DateTime.iso8601('1616-04-23', Date::ITALY) #=> Sat, 23 Apr 1616 00:00:00 +0000
Already you can see something’s weird - the days of the week are different, taking this further:
cervantes == shakespeare #=> false (shakespeare - cervantes).to_i #=> 10
This shows that in fact they died 10 days apart (in reality 11 days since Cervantes died a day earlier but was buried on the 23rd). We can see the actual date of Shakespeare’s death by using the gregorian
method to convert it:
shakespeare.gregorian #=> Tue, 03 May 1616 00:00:00 +0000
So there’s an argument that all the celebrations that take place on the 23rd April in Stratford-upon-Avon are actually the wrong date since England is now using the Gregorian calendar. You can see why when we transition across the reform date boundary:
# start off with the anniversary of Shakespeare's birth in 1751 shakespeare = DateTime.iso8601('1751-04-23', Date::ENGLAND) #=> Tue, 23 Apr 1751 00:00:00 +0000 # add 366 days since 1752 is a leap year and April 23 is after February 29 shakespeare + 366 #=> Thu, 23 Apr 1752 00:00:00 +0000 # add another 365 days to take us to the anniversary in 1753 shakespeare + 366 + 365 #=> Fri, 04 May 1753 00:00:00 +0000
As you can see, if we’re accurately tracking the number of solar years since Shakespeare’s birthday then the correct anniversary date would be the 4th May and not the 23rd April.
So when should you use DateTime
in Ruby and when should you use Time
? Almost certainly you’ll want to use Time
since your app is probably dealing with current dates and times. However, if you need to deal with dates and times in a historical context you’ll want to use DateTime
to avoid making the same mistakes as UNESCO. If you also have to deal with timezones then best of luck - just bear in mind that you’ll probably be dealing with local solar times, since it wasn’t until the 19th century that the introduction of the railways necessitated the need for Standard Time and eventually timezones.
When ‘time’ is required, Time
is extended with additional methods for parsing and converting Times.
This library extends the Time
class with the following conversions between date strings and Time
objects:
date-time defined by RFC 2822
HTTP-date defined by RFC 2616
various formats handled by Date._parse
custom formats handled by Date._strptime
All examples assume you have loaded Time
with:
require 'time'
All of these examples were done using the EST timezone which is GMT-5.
t = Time.now t.iso8601 # => "2011-10-05T22:26:12-04:00" t.rfc2822 # => "Wed, 05 Oct 2011 22:26:12 -0400" t.httpdate # => "Thu, 06 Oct 2011 02:26:12 GMT"
Time.parse
parse takes a string representation of a Time
and attempts to parse it using a heuristic.
Time.parse("2010-10-31") #=> 2010-10-31 00:00:00 -0500
Any missing pieces of the date are inferred based on the current date.
# assuming the current date is "2011-10-31" Time.parse("12:00") #=> 2011-10-31 12:00:00 -0500
We can change the date used to infer our missing elements by passing a second object that responds to mon
, day
and year
, such as Date
, Time
or DateTime
. We can also use our own object.
class MyDate attr_reader :mon, :day, :year def initialize(mon, day, year) @mon, @day, @year = mon, day, year end end d = Date.parse("2010-10-28") t = Time.parse("2010-10-29") dt = DateTime.parse("2010-10-30") md = MyDate.new(10,31,2010) Time.parse("12:00", d) #=> 2010-10-28 12:00:00 -0500 Time.parse("12:00", t) #=> 2010-10-29 12:00:00 -0500 Time.parse("12:00", dt) #=> 2010-10-30 12:00:00 -0500 Time.parse("12:00", md) #=> 2010-10-31 12:00:00 -0500
parse also accepts an optional block. You can use this block to specify how to handle the year component of the date. This is specifically designed for handling two digit years. For example, if you wanted to treat all two digit years prior to 70 as the year 2000+ you could write this:
Time.parse("01-10-31") {|year| year + (year < 70 ? 2000 : 1900)} #=> 2001-10-31 00:00:00 -0500 Time.parse("70-10-31") {|year| year + (year < 70 ? 2000 : 1900)} #=> 1970-10-31 00:00:00 -0500
Time.strptime
strptime works similar to parse
except that instead of using a heuristic to detect the format of the input string, you provide a second argument that describes the format of the string. For example:
Time.strptime("2000-10-31", "%Y-%m-%d") #=> 2000-10-31 00:00:00 -0500
Time
is an abstraction of dates and times. Time
is stored internally as the number of seconds with fraction since the Epoch, January 1, 1970 00:00 UTC. Also see the library module Date
. The Time
class treats GMT (Greenwich Mean Time
) and UTC (Coordinated Universal Time
) as equivalent. GMT is the older way of referring to these baseline times but persists in the names of calls on POSIX systems.
All times may have fraction. Be aware of this fact when comparing times with each other – times that are apparently equal when displayed may be different when compared.
Since Ruby 1.9.2, Time
implementation uses a signed 63 bit integer, Bignum
or Rational
. The integer is a number of nanoseconds since the Epoch which can represent 1823-11-12 to 2116-02-20. When Bignum
or Rational
is used (before 1823, after 2116, under nanosecond), Time
works slower as when integer is used.
All of these examples were done using the EST timezone which is GMT-5.
Time
instance You can create a new instance of Time
with Time::new
. This will use the current system time. Time::now
is an alias for this. You can also pass parts of the time to Time::new
such as year, month, minute, etc. When you want to construct a time this way you must pass at least a year. If you pass the year with nothing else time will default to January 1 of that year at 00:00:00 with the current system timezone. Here are some examples:
Time.new(2002) #=> 2002-01-01 00:00:00 -0500 Time.new(2002, 10) #=> 2002-10-01 00:00:00 -0500 Time.new(2002, 10, 31) #=> 2002-10-31 00:00:00 -0500 Time.new(2002, 10, 31, 2, 2, 2, "+02:00") #=> 2002-10-31 02:02:02 +0200
You can also use gm
, local and utc
to infer GMT, local and UTC timezones instead of using the current system setting.
You can also create a new time using Time::at
which takes the number of seconds (or fraction of seconds) since the Unix Epoch.
Time.at(628232400) #=> 1989-11-28 00:00:00 -0500
Time
Once you have an instance of Time
there is a multitude of things you can do with it. Below are some examples. For all of the following examples, we will work on the assumption that you have done the following:
t = Time.new(1993, 02, 24, 12, 0, 0, "+09:00")
Was that a monday?
t.monday? #=> false
What year was that again?
t.year #=> 1993
Was is daylight savings at the time?
t.dst? #=> false
What’s the day a year later?
t + (60*60*24*365) #=> 1994-02-24 12:00:00 +0900
How many seconds was that since the Unix Epoch?
t.to_i #=> 730522800
You can also do standard functions like compare two times.
t1 = Time.new(2010) t2 = Time.new(2011) t1 == t2 #=> false t1 == t1 #=> true t1 < t2 #=> true t1 > t2 #=> false Time.new(2010,10,31).between?(t1, t2) #=> true
Raised when OLE processing failed.
EX:
obj = WIN32OLE.new("NonExistProgID")
raises the exception:
WIN32OLERuntimeError: unknown OLE server: `NonExistProgID' HRESULT error code:0x800401f3 Invalid class string
Use the Monitor
class when you want to have a lock object for blocks with mutual exclusion.
require 'monitor' lock = Monitor.new lock.synchronize do # exclusive access end