A complex number can be represented as a paired real number with imaginary unit; a+bi. Where a is real part, b is imaginary part and i is imaginary unit. Real a equals complex a+0i mathematically.
Complex
object can be created as literal, and also by using Kernel#Complex
, Complex::rect
, Complex::polar
or to_c
method.
2+1i #=> (2+1i) Complex(1) #=> (1+0i) Complex(2, 3) #=> (2+3i) Complex.polar(2, 3) #=> (-1.9799849932008908+0.2822400161197344i) 3.to_c #=> (3+0i)
You can also create complex object from floating-point numbers or strings.
Complex(0.3) #=> (0.3+0i) Complex('0.3-0.5i') #=> (0.3-0.5i) Complex('2/3+3/4i') #=> ((2/3)+(3/4)*i) Complex('1@2') #=> (-0.4161468365471424+0.9092974268256817i) 0.3.to_c #=> (0.3+0i) '0.3-0.5i'.to_c #=> (0.3-0.5i) '2/3+3/4i'.to_c #=> ((2/3)+(3/4)*i) '1@2'.to_c #=> (-0.4161468365471424+0.9092974268256817i)
A complex object is either an exact or an inexact number.
Complex(1, 1) / 2 #=> ((1/2)+(1/2)*i) Complex(1, 1) / 2.0 #=> (0.5+0.5i)
A File
is an abstraction of any file object accessible by the program and is closely associated with class IO
. File
includes the methods of module FileTest
as class methods, allowing you to write (for example) File.exist?("foo")
.
In the description of File
methods, permission bits are a platform-specific set of bits that indicate permissions of a file. On Unix-based systems, permissions are viewed as a set of three octets, for the owner, the group, and the rest of the world. For each of these entities, permissions may be set to read, write, or execute the file:
The permission bits 0644
(in octal) would thus be interpreted as read/write for owner, and read-only for group and other. Higher-order bits may also be used to indicate the type of file (plain, directory, pipe, socket, and so on) and various other special features. If the permissions are for a directory, the meaning of the execute bit changes; when set the directory can be searched.
On non-Posix operating systems, there may be only the ability to make a file read-only or read-write. In this case, the remaining permission bits will be synthesized to resemble typical values. For instance, on Windows NT the default permission bits are 0644
, which means read/write for owner, read-only for all others. The only change that can be made is to make the file read-only, which is reported as 0444
.
Various constants for the methods in File
can be found in File::Constants
.
Raised when a method is called on a receiver which doesn’t have it defined and also fails to respond with method_missing
.
"hello".to_ary
raises the exception:
NoMethodError: undefined method `to_ary' for "hello":String
Raised when memory allocation fails.
SystemCallError
is the base class for all low-level platform-dependent errors.
The errors available on the current platform are subclasses of SystemCallError
and are defined in the Errno
module.
File.open("does/not/exist")
raises the exception:
Errno::ENOENT: No such file or directory - does/not/exist
OLEProperty
helper class of Property with arguments.
WIN32OLE
objects represent OLE Automation object in Ruby.
By using WIN32OLE
, you can access OLE server like VBScript.
Here is sample script.
require 'win32ole' excel = WIN32OLE.new('Excel.Application') excel.visible = true workbook = excel.Workbooks.Add(); worksheet = workbook.Worksheets(1); worksheet.Range("A1:D1").value = ["North","South","East","West"]; worksheet.Range("A2:B2").value = [5.2, 10]; worksheet.Range("C2").value = 8; worksheet.Range("D2").value = 20; range = worksheet.Range("A1:D2"); range.select chart = workbook.Charts.Add; workbook.saved = true; excel.ActiveWorkbook.Close(0); excel.Quit();
Unfortunately, Win32OLE doesn’t support the argument passed by reference directly. Instead, Win32OLE provides WIN32OLE::ARGV
or WIN32OLE_VARIANT
object. If you want to get the result value of argument passed by reference, you can use WIN32OLE::ARGV
or WIN32OLE_VARIANT
.
oleobj.method(arg1, arg2, refargv3) puts WIN32OLE::ARGV[2] # the value of refargv3 after called oleobj.method
or
refargv3 = WIN32OLE_VARIANT.new(XXX, WIN32OLE::VARIANT::VT_BYREF|WIN32OLE::VARIANT::VT_XXX) oleobj.method(arg1, arg2, refargv3) p refargv3.value # the value of refargv3 after called oleobj.method.
This library provides three different ways to delegate method calls to an object. The easiest to use is SimpleDelegator
. Pass an object to the constructor and all methods supported by the object will be delegated. This object can be changed later.
Going a step further, the top level DelegateClass method allows you to easily setup delegation through class inheritance. This is considerably more flexible and thus probably the most common use for this library.
Finally, if you need full control over the delegation scheme, you can inherit from the abstract class Delegator
and customize as needed. (If you find yourself needing this control, have a look at Forwardable which is also in the standard library. It may suit your needs better.)
SimpleDelegator’s implementation serves as a nice example of the use of Delegator:
class SimpleDelegator < Delegator def __getobj__ @delegate_sd_obj # return object we are delegating to, required end def __setobj__(obj) @delegate_sd_obj = obj # change delegation object, # a feature we're providing end end
Be advised, RDoc
will not detect delegated methods.
A utility class for managing temporary files. When you create a Tempfile
object, it will create a temporary file with a unique filename. A Tempfile
objects behaves just like a File
object, and you can perform all the usual file operations on it: reading data, writing data, changing its permissions, etc. So although this class does not explicitly document all instance methods supported by File
, you can in fact call any File
instance method on a Tempfile
object.
require 'tempfile' file = Tempfile.new('foo') file.path # => A unique filename in the OS's temp directory, # e.g.: "/tmp/foo.24722.0" # This filename contains 'foo' in its basename. file.write("hello world") file.rewind file.read # => "hello world" file.close file.unlink # deletes the temp file
When a Tempfile
object is garbage collected, or when the Ruby interpreter exits, its associated temporary file is automatically deleted. This means that’s it’s unnecessary to explicitly delete a Tempfile
after use, though it’s good practice to do so: not explicitly deleting unused Tempfiles can potentially leave behind large amounts of tempfiles on the filesystem until they’re garbage collected. The existence of these temp files can make it harder to determine a new Tempfile
filename.
Therefore, one should always call unlink
or close in an ensure block, like this:
file = Tempfile.new('foo') begin ...do something with file... ensure file.close file.unlink # deletes the temp file end
On POSIX systems, it’s possible to unlink a file right after creating it, and before closing it. This removes the filesystem entry without closing the file handle, so it ensures that only the processes that already had the file handle open can access the file’s contents. It’s strongly recommended that you do this if you do not want any other processes to be able to read from or write to the Tempfile
, and you do not need to know the Tempfile’s filename either.
For example, a practical use case for unlink-after-creation would be this: you need a large byte buffer that’s too large to comfortably fit in RAM, e.g. when you’re writing a web server and you want to buffer the client’s file upload data.
Please refer to unlink
for more information and a code example.
Tempfile’s filename picking method is both thread-safe and inter-process-safe: it guarantees that no other threads or processes will pick the same filename.
Tempfile
itself however may not be entirely thread-safe. If you access the same Tempfile
object from multiple threads then you should protect it with a mutex.
The Comparable
mixin is used by classes whose objects may be ordered. The class must define the <=>
operator, which compares the receiver against another object, returning -1, 0, or +1 depending on whether the receiver is less than, equal to, or greater than the other object. If the other object is not comparable then the <=>
operator should return nil. Comparable
uses <=>
to implement the conventional comparison operators (<
, <=
, ==
, >=
, and >
) and the method between?
.
class SizeMatters include Comparable attr :str def <=>(other) str.size <=> other.str.size end def initialize(str) @str = str end def inspect @str end end s1 = SizeMatters.new("Z") s2 = SizeMatters.new("YY") s3 = SizeMatters.new("XXX") s4 = SizeMatters.new("WWWW") s5 = SizeMatters.new("VVVVV") s1 < s2 #=> true s4.between?(s1, s3) #=> false s4.between?(s3, s5) #=> true [ s3, s2, s5, s4, s1 ].sort #=> [Z, YY, XXX, WWWW, VVVVV]
The Enumerable
mixin provides collection classes with several traversal and searching methods, and with the ability to sort. The class must provide a method each
, which yields successive members of the collection. If Enumerable#max
, #min
, or #sort
is used, the objects in the collection must also implement a meaningful <=>
operator, as these methods rely on an ordering between members of the collection.
A libffi wrapper for Ruby.
Fiddle
is an extension to translate a foreign function interface (FFI) with ruby.
It wraps libffi, a popular C library which provides a portable interface that allows code written in one language to call code written in another language.
Here we will use Fiddle::Function
to wrap floor(3) from libm
require 'fiddle' libm = Fiddle.dlopen('/lib/libm.so.6') floor = Fiddle::Function.new( libm['floor'], [Fiddle::TYPE_DOUBLE], Fiddle::TYPE_DOUBLE ) puts floor.call(3.14159) #=> 3.0
FileTest
implements file test operations similar to those used in File::Stat
. It exists as a standalone module, and its methods are also insinuated into the File
class. (Note that this is not done by inclusion: the interpreter cheats).
The Forwardable module provides delegation of specified methods to a designated object, using the methods def_delegator
and def_delegators
.
For example, say you have a class RecordCollection which contains an array @records
. You could provide the lookup method record_number(), which simply calls [] on the @records
array, like this:
require 'forwardable' class RecordCollection attr_accessor :records extend Forwardable def_delegator :@records, :[], :record_number end
We can use the lookup method like so:
r = RecordCollection.new r.records = [4,5,6] r.record_number(0) # => 4
Further, if you wish to provide the methods size, <<, and map, all of which delegate to @records, this is how you can do it:
class RecordCollection # re-open RecordCollection class def_delegators :@records, :size, :<<, :map end r = RecordCollection.new r.records = [1,2,3] r.record_number(0) # => 1 r.size # => 3 r << 4 # => [1, 2, 3, 4] r.map { |x| x * 2 } # => [2, 4, 6, 8]
You can even extend regular objects with Forwardable.
my_hash = Hash.new my_hash.extend Forwardable # prepare object for delegation my_hash.def_delegator "STDOUT", "puts" # add delegation for STDOUT.puts() my_hash.puts "Howdy!"
We want to rely on what has come before obviously, but with delegation we can take just the methods we need and even rename them as appropriate. In many cases this is preferable to inheritance, which gives us the entire old interface, even if much of it isn’t needed.
class Queue extend Forwardable def initialize @q = [ ] # prepare delegate object end # setup preferred interface, enq() and deq()... def_delegator :@q, :push, :enq def_delegator :@q, :shift, :deq # support some general Array methods that fit Queues well def_delegators :@q, :clear, :first, :push, :shift, :size end q = Queue.new q.enq 1, 2, 3, 4, 5 q.push 6 q.shift # => 1 while q.size > 0 puts q.deq end q.enq "Ruby", "Perl", "Python" puts q.first q.clear puts q.first
This should output:
2 3 4 5 6 Ruby nil
Be advised, RDoc
will not detect delegated methods.
forwardable.rb
provides single-method delegation via the def_delegator
and def_delegators
methods. For full-class delegation via DelegateClass, see delegate.rb
.
mkmf.rb is used by Ruby C extensions to generate a Makefile which will correctly compile and link the C extension to Ruby and a third-party library.
The Observer pattern (also known as publish/subscribe) provides a simple mechanism for one object to inform a set of interested third-party objects when its state changes.
The notifying class mixes in the Observable
module, which provides the methods for managing the associated observer objects.
The observable object must:
assert that it has #changed
call #notify_observers
An observer subscribes to updates using Observable#add_observer
, which also specifies the method called via notify_observers
. The default method for notify_observers
is update.
The following example demonstrates this nicely. A Ticker
, when run, continually receives the stock Price
for its @symbol
. A Warner
is a general observer of the price, and two warners are demonstrated, a WarnLow
and a WarnHigh
, which print a warning if the price is below or above their set limits, respectively.
The update
callback allows the warners to run without being explicitly called. The system is set up with the Ticker
and several observers, and the observers do their duty without the top-level code having to interfere.
Note that the contract between publisher and subscriber (observable and observer) is not declared or enforced. The Ticker
publishes a time and a price, and the warners receive that. But if you don’t ensure that your contracts are correct, nothing else can warn you.
require "observer" class Ticker ### Periodically fetch a stock price. include Observable def initialize(symbol) @symbol = symbol end def run last_price = nil loop do price = Price.fetch(@symbol) print "Current price: #{price}\n" if price != last_price changed # notify observers last_price = price notify_observers(Time.now, price) end sleep 1 end end end class Price ### A mock class to fetch a stock price (60 - 140). def self.fetch(symbol) 60 + rand(80) end end class Warner ### An abstract observer of Ticker objects. def initialize(ticker, limit) @limit = limit ticker.add_observer(self) end end class WarnLow < Warner def update(time, price) # callback for observer if price < @limit print "--- #{time.to_s}: Price below #@limit: #{price}\n" end end end class WarnHigh < Warner def update(time, price) # callback for observer if price > @limit print "+++ #{time.to_s}: Price above #@limit: #{price}\n" end end end ticker = Ticker.new("MSFT") WarnLow.new(ticker, 80) WarnHigh.new(ticker, 120) ticker.run
Produces:
Current price: 83 Current price: 75 --- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 75 Current price: 90 Current price: 134 +++ Sun Jun 09 00:10:25 CDT 2002: Price above 120: 134 Current price: 134 Current price: 112 Current price: 79 --- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 79
Profile provides a way to Profile your Ruby application.
Profiling your program is a way of determining which methods are called and how long each method takes to complete. This way you can detect which methods are possible bottlenecks.
Profiling your program will slow down your execution time considerably, so activate it only when you need it. Don’t confuse benchmarking with profiling.
There are two ways to activate Profiling:
Run your Ruby script with -rprofile
:
ruby -rprofile example.rb
If you’re profiling an executable in your $PATH
you can use ruby -S
:
ruby -rprofile -S some_executable
Just require ‘profile’:
require 'profile' def slow_method 5000.times do 9999999999999999*999999999 end end def fast_method 5000.times do 9999999999999999+999999999 end end slow_method fast_method
The output in both cases is a report when the execution is over:
ruby -rprofile example.rb % cumulative self self total time seconds seconds calls ms/call ms/call name 68.42 0.13 0.13 2 65.00 95.00 Integer#times 15.79 0.16 0.03 5000 0.01 0.01 Fixnum#* 15.79 0.19 0.03 5000 0.01 0.01 Fixnum#+ 0.00 0.19 0.00 2 0.00 0.00 IO#set_encoding 0.00 0.19 0.00 1 0.00 100.00 Object#slow_method 0.00 0.19 0.00 2 0.00 0.00 Module#method_added 0.00 0.19 0.00 1 0.00 90.00 Object#fast_method 0.00 0.19 0.00 1 0.00 190.00 #toplevel
Object
is the default root of all Ruby objects. Object
inherits from BasicObject
which allows creating alternate object hierarchies. Methods on Object
are available to all classes unless explicitly overridden.
Object
mixes in the Kernel
module, making the built-in kernel functions globally accessible. Although the instance methods of Object
are defined by the Kernel
module, we have chosen to document them here for clarity.
When referencing constants in classes inheriting from Object
you do not need to use the full namespace. For example, referencing File
inside YourClass
will find the top-level File
class.
In the descriptions of Object’s methods, the parameter symbol refers to a symbol, which is either a quoted string or a Symbol
(such as :name
).
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.
A DateTime
object is created with DateTime::new
, DateTime::jd
, DateTime::ordinal
, DateTime::commercial
, DateTime::parse
, DateTime::strptime
, DateTime::now
, Time#to_datetime
, 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 a 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 ...>
The offset 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 negative/positive infinity. The default value is Date::ITALY
(2299161=1582-10-15).
A 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 the 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 there’s no way to express this with Time
objects. 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 is 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.