Helper methods for both Gem::Installer and Gem::Uninstaller
This module contains various utility methods as module methods.
An Array is an ordered, integer-indexed collection of objects, called elements. Any object may be an Array element.
Array indexing starts at 0, as in C or Java.
A positive index is an offset from the first element:
Index 0 indicates the first element.
Index 1 indicates the second element.
…
A negative index is an offset, backwards, from the end of the array:
Index -1 indicates the last element.
Index -2 indicates the next-to-last element.
…
A non-negative index is in range if it is smaller than the size of the array. For a 3-element array:
Indexes 0 through 2 are in range.
Index 3 is out of range.
A negative index is in range if its absolute value is not larger than the size of the array. For a 3-element array:
Indexes -1 through -3 are in range.
Index -4 is out of range.
You can create an Array object explicitly with:
An array literal.
You can convert certain objects to Arrays with:
Method Array.
An Array can contain different types of objects. For example, the array below contains an Integer, a String and a Float:
ary = [1, "two", 3.0] #=> [1, "two", 3.0]
An array can also be created by calling Array.new with zero, one (the initial size of the Array) or two arguments (the initial size and a default object).
ary = Array.new #=> [] Array.new(3) #=> [nil, nil, nil] Array.new(3, true) #=> [true, true, true]
Note that the second argument populates the array with references to the same object. Therefore, it is only recommended in cases when you need to instantiate arrays with natively immutable objects such as Symbols, numbers, true or false.
To create an array with separate objects a block can be passed instead. This method is safe to use with mutable objects such as hashes, strings or other arrays:
Array.new(4) {Hash.new} #=> [{}, {}, {}, {}] Array.new(4) {|i| i.to_s } #=> ["0", "1", "2", "3"]
This is also a quick way to build up multi-dimensional arrays:
empty_table = Array.new(3) {Array.new(3)} #=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
An array can also be created by using the Array() method, provided by Kernel, which tries to call to_ary, then to_a on its argument.
Array({:a => "a", :b => "b"}) #=> [[:a, "a"], [:b, "b"]]
In addition to the methods it mixes in through the Enumerable module, the Array class has proprietary methods for accessing, searching and otherwise manipulating arrays.
Some of the more common ones are illustrated below.
Elements in an array can be retrieved using the Array#[] method. It can take a single integer argument (a numeric index), a pair of arguments (start and length) or a range. Negative indices start counting from the end, with -1 being the last element.
arr = [1, 2, 3, 4, 5, 6] arr[2] #=> 3 arr[100] #=> nil arr[-3] #=> 4 arr[2, 3] #=> [3, 4, 5] arr[1..4] #=> [2, 3, 4, 5] arr[1..-3] #=> [2, 3, 4]
Another way to access a particular array element is by using the at method
arr.at(0) #=> 1
The slice method works in an identical manner to Array#[].
To raise an error for indices outside of the array bounds or else to provide a default value when that happens, you can use fetch.
arr = ['a', 'b', 'c', 'd', 'e', 'f'] arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6 arr.fetch(100, "oops") #=> "oops"
The special methods first and last will return the first and last elements of an array, respectively.
arr.first #=> 1 arr.last #=> 6
To return the first n elements of an array, use take
arr.take(3) #=> [1, 2, 3]
drop does the opposite of take, by returning the elements after n elements have been dropped:
arr.drop(3) #=> [4, 5, 6]
Array Arrays keep track of their own length at all times. To query an array about the number of elements it contains, use length, count or size.
browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE'] browsers.length #=> 5 browsers.count #=> 5
To check whether an array contains any elements at all
browsers.empty? #=> false
To check whether a particular item is included in the array
browsers.include?('Konqueror') #=> false
Items can be added to the end of an array by using either push or <<
arr = [1, 2, 3, 4] arr.push(5) #=> [1, 2, 3, 4, 5] arr << 6 #=> [1, 2, 3, 4, 5, 6]
unshift will add a new item to the beginning of an array.
arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
With insert you can add a new element to an array at any position.
arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
Using the insert method, you can also insert multiple values at once:
arr.insert(3, 'orange', 'pear', 'grapefruit') #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
Array The method pop removes the last element in an array and returns it:
arr = [1, 2, 3, 4, 5, 6] arr.pop #=> 6 arr #=> [1, 2, 3, 4, 5]
To retrieve and at the same time remove the first item, use shift:
arr.shift #=> 1 arr #=> [2, 3, 4, 5]
To delete an element at a particular index:
arr.delete_at(2) #=> 4 arr #=> [2, 3, 5]
To delete a particular element anywhere in an array, use delete:
arr = [1, 2, 2, 3] arr.delete(2) #=> 2 arr #=> [1,3]
A useful method if you need to remove nil values from an array is compact:
arr = ['foo', 0, nil, 'bar', 7, 'baz', nil] arr.compact #=> ['foo', 0, 'bar', 7, 'baz'] arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil] arr.compact! #=> ['foo', 0, 'bar', 7, 'baz'] arr #=> ['foo', 0, 'bar', 7, 'baz']
Another common need is to remove duplicate elements from an array.
It has the non-destructive uniq, and destructive method uniq!
arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556] arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
Like all classes that include the Enumerable module, Array has an each method, which defines what elements should be iterated over and how. In case of Array’s each, all elements in the Array instance are yielded to the supplied block in sequence.
Note that this operation leaves the array unchanged.
arr = [1, 2, 3, 4, 5] arr.each {|a| print a -= 10, " "} # prints: -9 -8 -7 -6 -5 #=> [1, 2, 3, 4, 5]
Another sometimes useful iterator is reverse_each which will iterate over the elements in the array in reverse order.
words = %w[first second third fourth fifth sixth] str = "" words.reverse_each {|word| str += "#{word} "} p str #=> "sixth fifth fourth third second first "
The map method can be used to create a new array based on the original array, but with the values modified by the supplied block:
arr.map {|a| 2*a} #=> [2, 4, 6, 8, 10] arr #=> [1, 2, 3, 4, 5] arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25] arr #=> [1, 4, 9, 16, 25]
Array Elements can be selected from an array according to criteria defined in a block. The selection can happen in a destructive or a non-destructive manner. While the destructive operations will modify the array they were called on, the non-destructive methods usually return a new array with the selected elements, but leave the original array unchanged.
arr = [1, 2, 3, 4, 5, 6] arr.select {|a| a > 3} #=> [4, 5, 6] arr.reject {|a| a < 3} #=> [3, 4, 5, 6] arr.drop_while {|a| a < 4} #=> [4, 5, 6] arr #=> [1, 2, 3, 4, 5, 6]
select! and reject! are the corresponding destructive methods to select and reject
Similar to select vs. reject, delete_if and keep_if have the exact opposite result when supplied with the same block:
arr.delete_if {|a| a < 4} #=> [4, 5, 6] arr #=> [4, 5, 6] arr = [1, 2, 3, 4, 5, 6] arr.keep_if {|a| a < 4} #=> [1, 2, 3] arr #=> [1, 2, 3]
First, what’s elsewhere. Class Array:
Inherits from class Object.
Includes module Enumerable, which provides dozens of additional methods.
Here, class Array provides methods that are useful for:
Array ::[]Returns a new array populated with given objects.
::newReturns a new array.
::try_convertReturns a new array created from a given object.
length, sizeReturns the count of elements.
include?Returns whether any element == a given object.
empty?Returns whether there are no elements.
all?Returns whether all elements meet a given criterion.
any?Returns whether any element meets a given criterion.
none?Returns whether no element == a given object.
one?Returns whether exactly one element == a given object.
countReturns the count of elements that meet a given criterion.
find_index, indexReturns the index of the first element that meets a given criterion.
rindexReturns the index of the last element that meets a given criterion.
hashReturns the integer hash code.
Returns -1, 0, or 1 as self is less than, equal to, or greater than a given object.
Returns whether each element in self is == to the corresponding element in a given object.
eql?Returns whether each element in self is eql? to the corresponding element in a given object.
These methods do not modify self.
[]Returns one or more elements.
fetchReturns the element at a given offset.
firstReturns one or more leading elements.
lastReturns one or more trailing elements.
maxReturns one or more maximum-valued elements, as determined by <=> or a given block.
maxReturns one or more minimum-valued elements, as determined by <=> or a given block.
minmaxReturns the minimum-valued and maximum-valued elements, as determined by <=> or a given block.
assocReturns the first element that is an array whose first element == a given object.
rassocReturns the first element that is an array whose second element == a given object.
atReturns the element at a given offset.
values_atReturns the elements at given offsets.
digReturns the object in nested objects that is specified by a given index and additional arguments.
dropReturns trailing elements as determined by a given index.
takeReturns leading elements as determined by a given index.
drop_whileReturns trailing elements as determined by a given block.
take_whileReturns leading elements as determined by a given block.
sliceReturns consecutive elements as determined by a given argument.
sortReturns all elements in an order determined by <=> or a given block.
reverseReturns all elements in reverse order.
compactReturns an array containing all non-nil elements.
select, filterReturns an array containing elements selected by a given block.
uniqReturns an array containing non-duplicate elements.
rotateReturns all elements with some rotated from one end to the other.
bsearchReturns an element selected via a binary search as determined by a given block.
bsearch_indexReturns the index of an element selected via a binary search as determined by a given block.
sampleReturns one or more random elements.
shuffleReturns elements in a random order.
These methods add, replace, or reorder elements in self.
[]=Assigns specified elements with a given object.
push, append, <<Appends trailing elements.
unshift, prependPrepends leading elements.
insertInserts given objects at a given offset; does not replace elements.
concatAppends all elements from given arrays.
fillReplaces specified elements with specified objects.
replaceReplaces the content of self with the content of a given array.
reverse!Replaces self with its elements reversed.
rotate!Replaces self with its elements rotated.
shuffle!Replaces self with its elements in random order.
sort!Replaces self with its elements sorted, as determined by <=> or a given block.
sort_by!Replaces self with its elements sorted, as determined by a given block.
Each of these methods removes elements from self:
popRemoves and returns the last element.
shiftRemoves and returns the first element.
compact!Removes all non-nil elements.
deleteRemoves elements equal to a given object.
delete_atRemoves the element at a given offset.
delete_ifRemoves elements specified by a given block.
keep_ifRemoves elements not specified by a given block.
reject!Removes elements specified by a given block.
select!, filter!Removes elements not specified by a given block.
slice!Removes and returns a sequence of elements.
uniq!Removes duplicates.
Returns an array containing elements found both in self and a given array.
intersectionReturns an array containing elements found both in self and in each given array.
+Returns an array containing all elements of self followed by all elements of a given array.
-Returns an array containiing all elements of self that are not found in a given array.
Returns an array containing all elements of self and all elements of a given array, duplicates removed.
unionReturns an array containing all elements of self and all elements of given arrays, duplicates removed.
differenceReturns an array containing all elements of self that are not found in any of the given arrays..
productReturns or yields all combinations of elements from self and given arrays.
eachPasses each element to a given block.
reverse_eachPasses each element, in reverse order, to a given block.
each_indexPasses each element index to a given block.
cycleCalls a given block with each element, then does so again, for a specified number of times, or forever.
combinationCalls a given block with combinations of elements of self; a combination does not use the same element more than once.
permutationCalls a given block with permutations of elements of self; a permutation does not use the same element more than once.
repeated_combinationCalls a given block with combinations of elements of self; a combination may use the same element more than once.
repeated_permutationCalls a given block with permutations of elements of self; a permutation may use the same element more than once.
map, collectReturns an array containing the block return-value for each element.
map!, collect!Replaces each element with a block return-value.
flattenReturns an array that is a recursive flattening of self.
flatten!Replaces each nested array in self with the elements from that array.
inspect, to_sReturns a new String containing the elements.
joinReturns a newsString containing the elements joined by the field separator.
to_aReturns self or a new array containing all elements.
to_aryReturns self.
to_hReturns a new hash formed from the elements.
transposeTransposes self, which must be an array of arrays.
zipReturns a new array of arrays containing self and given arrays; follow the link for details.
*Returns one of the following:
With integer argument n, a new array that is the concatenation of n copies of self.
With string argument field_separator, a new string that is equivalent to join(field_separator).
abbrevReturns a hash of unambiguous abbreviations for elements.
packPacks the elements into a binary sequence.
sumReturns a sum of elements according to either + or a given block.
for pack.c
Raised by exit to initiate the termination of the script.
The most standard error types are subclasses of StandardError. A rescue clause without an explicit Exception class will rescue all StandardErrors (and only those).
def foo raise "Oups" end foo rescue "Hello" #=> "Hello"
On the other hand:
require 'does/not/exist' rescue "Hi"
raises the exception:
LoadError: no such file to load -- does/not/exist
Raised when the arguments are wrong and there isn’t a more specific Exception class.
Ex: passing the wrong number of arguments
[1, 2, 3].first(4, 5)
raises the exception:
ArgumentError: wrong number of arguments (given 2, expected 1)
Ex: passing an argument that is not acceptable:
[1, 2, 3].first(-4)
raises the exception:
ArgumentError: negative array size
No longer used by internal code.
Expect library adds the IO instance method expect, which does similar act to tcl’s expect extension.
In order to use this method, you must require expect:
require 'expect'
Please see expect for usage.
The IO class is the basis for all input and output in Ruby. An I/O stream may be duplexed (that is, bidirectional), and so may use more than one native operating system stream.
Many of the examples in this section use the File class, the only standard subclass of IO. The two classes are closely associated. Like the File class, the Socket library subclasses from IO (such as TCPSocket or UDPSocket).
The Kernel#open method can create an IO (or File) object for these types of arguments:
A plain string represents a filename suitable for the underlying operating system.
A string starting with "|" indicates a subprocess. The remainder of the string following the "|" is invoked as a process with appropriate input/output channels connected to it.
A string equal to "|-" will create another Ruby instance as a subprocess.
The IO may be opened with different file modes (read-only, write-only) and encodings for proper conversion. See IO.new for these options. See Kernel#open for details of the various command formats described above.
IO.popen, the Open3 library, or Process#spawn may also be used to communicate with subprocesses through an IO.
Ruby will convert pathnames between different operating system conventions if possible. For instance, on a Windows system the filename "/gumby/ruby/test.rb" will be opened as "\gumby\ruby\test.rb". When specifying a Windows-style filename in a Ruby string, remember to escape the backslashes:
"C:\\gumby\\ruby\\test.rb"
Our examples here will use the Unix-style forward slashes; File::ALT_SEPARATOR can be used to get the platform-specific separator character.
The global constant ARGF (also accessible as $<) provides an IO-like stream which allows access to all files mentioned on the command line (or STDIN if no files are mentioned). ARGF#path and its alias ARGF#filename are provided to access the name of the file currently being read.
The io/console extension provides methods for interacting with the console. The console can be accessed from IO.console or the standard input/output/error IO objects.
Requiring io/console adds the following methods:
Example:
require 'io/console' rows, columns = $stdout.winsize puts "Your screen is #{columns} wide and #{rows} tall"
Many examples here use these filenames and their corresponding files:
t.txt: A text-only file that is assumed to exist via:
text = <<~EOT This is line one. This is the second line. This is the third line. EOT File.write('t.txt', text)
t.dat: A data file that is assumed to exist via:
data = "\u9990\u9991\u9992\u9993\u9994" f = File.open('t.dat', 'wb:UTF-16') f.write(data) f.close
t.rus: A Russian-language text file that is assumed to exist via:
File.write('t.rus', "\u{442 435 441 442}")
t.tmp: A file that is assumed not to exist.
A number of IO method calls must or may specify a mode for the stream; the mode determines how stream is to be accessible, including:
Whether the stream is to be read-only, write-only, or read-write.
Whether the stream is positioned at its beginning or its end.
Whether the stream treats data as text-only or binary.
The external and internal encodings.
When mode is an integer it must be one or more (combined by bitwise OR (|) of the modes defined in File::Constants:
File::RDONLY: Open for reading only.
File::WRONLY: Open for writing only.
File::RDWR: Open for reading and writing.
File::APPEND: Open for appending only.
File::CREAT: Create file if it does not exist.
File::EXCL: Raise an exception if File::CREAT is given and the file exists.
Examples:
File.new('t.txt', File::RDONLY) File.new('t.tmp', File::RDWR | File::CREAT | File::EXCL)
Note: Method IO#set_encoding does not allow the mode to be specified as an integer.
When mode is a string it must begin with one of the following:
'r': Read-only stream, positioned at the beginning; the stream cannot be changed to writable.
'w': Write-only stream, positioned at the beginning; the stream cannot be changed to readable.
'a': Write-only stream, positioned at the end; every write appends to the end; the stream cannot be changed to readable.
'r+': Read-write stream, positioned at the beginning.
'w+': Read-write stream, positioned at the end.
'a+': Read-write stream, positioned at the end.
For a writable file stream (that is, any except read-only), the file is truncated to zero if it exists, and is created if it does not exist.
Examples:
File.open('t.txt', 'r') File.open('t.tmp', 'w')
Either of the following may be suffixed to any of the above:
't': Text data; sets the default external encoding to Encoding::UTF_8; on Windows, enables conversion between EOL and CRLF.
'b': Binary data; sets the default external encoding to Encoding::ASCII_8BIT; on Windows, suppresses conversion between EOL and CRLF.
If neither is given, the stream defaults to text data.
Examples:
File.open('t.txt', 'rt') File.open('t.dat', 'rb')
The following may be suffixed to any writable mode above:
'x': Creates the file if it does not exist; raises an exception if the file exists.
Example:
File.open('t.tmp', 'wx')
Finally, the mode string may specify encodings – either external encoding only or both external and internal encodings – by appending one or both encoding names, separated by colons:
f = File.new('t.dat', 'rb') f.external_encoding # => #<Encoding:ASCII-8BIT> f.internal_encoding # => nil f = File.new('t.dat', 'rb:UTF-16') f.external_encoding # => #<Encoding:UTF-16 (dummy)> f.internal_encoding # => nil f = File.new('t.dat', 'rb:UTF-16:UTF-16') f.external_encoding # => #<Encoding:UTF-16 (dummy)> f.internal_encoding # => #<Encoding:UTF-16>
The numerous encoding names are available in array Encoding.name_list:
Encoding.name_list.size # => 175 Encoding.name_list.take(3) # => ["ASCII-8BIT", "UTF-8", "US-ASCII"]
When the external encoding is set, strings read are tagged by that encoding when reading, and strings written are converted to that encoding when writing.
When both external and internal encodings are set, strings read are converted from external to internal encoding, and strings written are converted from internal to external encoding. For further details about transcoding input and output, see Encoding.
If the external encoding is 'BOM|UTF-8', 'BOM|UTF-16LE' or 'BOM|UTF16-BE', Ruby checks for a Unicode BOM in the input document to help determine the encoding. For UTF-16 encodings the file open mode must be binary. If the BOM is found, it is stripped and the external encoding from the BOM is used.
Note that the BOM-style encoding option is case insensitive, so ‘bom|utf-8’ is also valid.)
A number of IO methods accept an optional parameter opts, which determines how a new stream is to be opened:
:mode: Stream mode.
:flags: Integer file open flags; If mode is also given, the two are bitwise-ORed.
:external_encoding: External encoding for the stream.
:internal_encoding: Internal encoding for the stream. '-' is a synonym for the default internal encoding. If the value is nil no conversion occurs.
:encoding: Specifies external and internal encodings as 'extern:intern'.
:textmode: If a truthy value, specifies the mode as text-only, binary otherwise.
:binmode: If a truthy value, specifies the mode as binary, text-only otherwise.
:autoclose: If a truthy value, specifies that the fd will close when the stream closes; otherwise it remains open.
Also available are the options offered in String#encode, which may control conversion between external internal encoding.
A number of IO methods accept optional keyword arguments that determine how a stream is to be treated:
:chomp: If true, line separators are omitted; default is false.
An IO stream has a position, which is the non-negative integer offset (in bytes) in the stream where the next read or write will occur.
Note that a text stream may have multi-byte characters, so a text stream whose position is n (bytes) may not have n characters preceding the current position – there may be fewer.
A new stream is initially positioned:
At the beginning (position 0) if its mode is 'r', 'w', or 'r+'.
At the end (position self.size) if its mode is 'a', 'w+', or 'a+'.
Methods to query the position:
IO#tell and its alias IO#pos return the position for an open stream.
IO#eof? and its alias IO#eof return whether the position is at the end of a readable stream.
Reading from a stream usually changes its position:
f = File.open('t.txt') f.tell # => 0 f.readline # => "This is line one.\n" f.tell # => 19 f.readline # => "This is the second line.\n" f.tell # => 45 f.eof? # => false f.readline # => "Here's the third line.\n" f.eof? # => true
Writing to a stream usually changes its position:
f = File.open('t.tmp', 'w') f.tell # => 0 f.write('foo') # => 3 f.tell # => 3 f.write('bar') # => 3 f.tell # => 6
Iterating over a stream usually changes its position:
f = File.open('t.txt') f.each do |line| p "position=#{f.pos} eof?=#{f.eof?} line=#{line}" end
Output:
"position=19 eof?=false line=This is line one.\n" "position=45 eof?=false line=This is the second line.\n" "position=70 eof?=true line=This is the third line.\n"
The position may also be changed by certain other methods:
IO#pos= and IO#seek change the position to a specified offset.
IO#rewind changes the position to the beginning.
A readable IO stream has a line number, which is the non-negative integer line number in the stream where the next read will occur.
A new stream is initially has line number 0.
Method IO#lineno returns the line number.
Reading lines from a stream usually changes its line number:
f = File.open('t.txt', 'r') f.lineno # => 0 f.readline # => "This is line one.\n" f.lineno # => 1 f.readline # => "This is the second line.\n" f.lineno # => 2 f.readline # => "Here's the third line.\n" f.lineno # => 3 f.eof? # => true
Iterating over lines in a stream usually changes its line number:
f = File.open('t.txt') f.each_line do |line| p "position=#{f.pos} eof?=#{f.eof?} line=#{line}" end
Output:
"position=19 eof?=false line=This is line one.\n" "position=45 eof?=false line=This is the second line.\n" "position=70 eof?=true line=This is the third line.\n"
First, what’s elsewhere. Class IO:
Inherits from class Object.
Includes module Enumerable, which provides dozens of additional methods.
Here, class IO provides methods that are useful for:
::openCreates a new IO object.
::pipeCreates a connected pair of reader and writer IO objects.
::popenCreates an IO object to interact with a subprocess.
::selectSelects which given IO instances are ready for reading,
writing, or have pending exceptions.
::binreadReturns a binary string with all or a subset of bytes from the given file.
::readReturns a string with all or a subset of bytes from the given file.
::readlinesReturns an array of strings, which are the lines from the given file.
getbyteReturns the next 8-bit byte read from self as an integer.
getcReturns the next character read from self as a string.
getsReturns the line read from self.
preadReturns all or the next n bytes read from self, not updating the receiver’s offset.
readReturns all remaining or the next n bytes read from self for a given n.
read_nonblockthe next n bytes read from self for a given n, in non-block mode.
readlineReturns the next line read from self; same as getline, but raises an exception of end-of-file.
readlinesReturns an array of all lines read read from self.
readpartialReturns up to the given number of bytes from self.
::binwriteWrites the given string to the file at the given filepath, in binary mode.
::writeWrites the given string to self.
Appends the given string to self.
printPrints last read line or given objects to self.
printfWrites to self based on the given format string and objects.
putcWrites a character to self.
putsWrites lines to self, making sure line ends with a newline.
pwriteWrites the given string at the given offset, not updating the receiver’s offset.
writeWrites one or more given strings to self.
write_nonblockWrites one or more given strings to self in non-blocking mode.
linenoReturns the current line number in self.
lineno=Sets the line number is self.
pos=Sets the byte offset in self.
reopenReassociates self with a new or existing IO stream.
rewindPositions self to the beginning of input.
seekSets the offset for self relative to given position.
::foreachYields each line of given file to the block.
each_byteCalls the given block with each successive byte in self as an integer.
each_charCalls the given block with each successive character in self as a string.
each_codepointCalls the given block with each successive codepoint in self as an integer.
autoclose=Sets whether self auto-closes.
binmodeSets self to binary mode.
closeCloses self.
close_on_exec=Sets the close-on-exec flag.
close_readCloses self for reading.
close_writeCloses self for writing.
set_encodingSets the encoding for self.
set_encoding_by_bomSets the encoding for self, based on its Unicode byte-order-mark.
sync=Sets the sync-mode to the given value.
autoclose?Returns whether self auto-closes.
binmode?Returns whether self is in binary mode.
close_on_exec?Returns the close-on-exec flag for self.
closed?Returns whether self is closed.
external_encodingReturns the external encoding object for self.
internal_encodingReturns the internal encoding object for self.
statReturns the File::Stat object containing status information for self.
syncReturns whether self is in sync-mode.
isatty)Returns whether self is a terminal.
fdatasyncImmediately writes all buffered data in self to disk.
flushFlushes any buffered data within self to the underlying operating system.
fsyncImmediately writes all buffered data and attributes in self to disk.
ungetbytePrepends buffer for self with given integer byte or string.
ungetcPrepends buffer for self with given string.
::sysopenOpens the file given by its path, returning the integer file descriptor.
adviseAnnounces the intention to access data from self in a specific way.
fcntlPasses a low-level command to the file specified by the given file descriptor.
ioctlPasses a low-level command to the device specified by the given file descriptor.
sysreadReturns up to the next n bytes read from self using a low-level read.
sysseekSets the offset for self.
syswriteWrites the given string to self using a low-level write.
::copy_streamCopies data from a source to a destination, each of which is a filepath or an IO-like object.
::try_convertReturns a new IO object resulting from converting the given object.
inspectReturns the string representation of self.
Pathname represents the name of a file or directory on the filesystem, but not the file itself.
The pathname depends on the Operating System: Unix, Windows, etc. This library works with pathnames of local OS, however non-Unix pathnames are supported experimentally.
A Pathname can be relative or absolute. It’s not until you try to reference the file that it even matters whether the file exists or not.
Pathname is immutable. It has no method for destructive update.
The goal of this class is to manipulate file path information in a neater way than standard Ruby provides. The examples below demonstrate the difference.
All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
Pathname require 'pathname' pn = Pathname.new("/usr/bin/ruby") size = pn.size # 27662 isdir = pn.directory? # false dir = pn.dirname # Pathname:/usr/bin base = pn.basename # Pathname:ruby dir, base = pn.split # [Pathname:/usr/bin, Pathname:ruby] data = pn.read pn.open { |f| _ } pn.each_line { |line| _ }
pn = "/usr/bin/ruby" size = File.size(pn) # 27662 isdir = File.directory?(pn) # false dir = File.dirname(pn) # "/usr/bin" base = File.basename(pn) # "ruby" dir, base = File.split(pn) # ["/usr/bin", "ruby"] data = File.read(pn) File.open(pn) { |f| _ } File.foreach(pn) { |line| _ }
p1 = Pathname.new("/usr/lib") # Pathname:/usr/lib p2 = p1 + "ruby/1.8" # Pathname:/usr/lib/ruby/1.8 p3 = p1.parent # Pathname:/usr p4 = p2.relative_path_from(p3) # Pathname:lib/ruby/1.8 pwd = Pathname.pwd # Pathname:/home/gavin pwd.absolute? # true p5 = Pathname.new "." # Pathname:. p5 = p5 + "music/../articles" # Pathname:music/../articles p5.cleanpath # Pathname:articles p5.realpath # Pathname:/home/gavin/articles p5.children # [Pathname:/home/gavin/articles/linux, ...]
These methods are effectively manipulating a String, because that’s all a path is. None of these access the file system except for mountpoint?, children, each_child, realdirpath and realpath.
+
File status predicate methods These methods are a facade for FileTest:
File property and manipulation methods These methods are a facade for File:
open(*args, &block)
These methods are a facade for Dir:
each_entry(&block)
IO These methods are a facade for IO:
each_line(*args, &block)
These methods are a mixture of Find, FileUtils, and others:
Method documentation As the above section shows, most of the methods in Pathname are facades. The documentation for these methods generally just says, for instance, “See FileTest.writable?”, as you should be familiar with the original method anyway, and its documentation (e.g. through ri) will contain more information. In some cases, a brief description will follow.
Pseudo I/O on String object, with interface corresponding to IO.
Commonly used to simulate $stdio or $stderr
require 'stringio' # Writing stream emulation io = StringIO.new io.puts "Hello World" io.string #=> "Hello World\n" # Reading stream emulation io = StringIO.new "first\nsecond\nlast\n" io.getc #=> "f" io.gets #=> "irst\n" io.read #=> "second\nlast\n"
OLEProperty helper class of Property with arguments.
Raised when an IO operation fails.
File.open("/etc/hosts") {|f| f << "example"} #=> IOError: not opened for writing File.open("/etc/hosts") {|f| f.close; f.read } #=> IOError: closed stream
Note that some IO failures raise SystemCallErrors and these are not subclasses of IOError:
File.open("does/not/exist") #=> Errno::ENOENT: No such file or directory - does/not/exist
ARGF is a stream designed for use in scripts that process files given as command-line arguments or passed in via STDIN.
The arguments passed to your script are stored in the ARGV Array, one argument per element. ARGF assumes that any arguments that aren’t filenames have been removed from ARGV. For example:
$ ruby argf.rb --verbose file1 file2 ARGV #=> ["--verbose", "file1", "file2"] option = ARGV.shift #=> "--verbose" ARGV #=> ["file1", "file2"]
You can now use ARGF to work with a concatenation of each of these named files. For instance, ARGF.read will return the contents of file1 followed by the contents of file2.
After a file in ARGV has been read ARGF removes it from the Array. Thus, after all files have been read ARGV will be empty.
You can manipulate ARGV yourself to control what ARGF operates on. If you remove a file from ARGV, it is ignored by ARGF; if you add files to ARGV, they are treated as if they were named on the command line. For example:
ARGV.replace ["file1"] ARGF.readlines # Returns the contents of file1 as an Array ARGV #=> [] ARGV.replace ["file2", "file3"] ARGF.read # Returns the contents of file2 and file3
If ARGV is empty, ARGF acts as if it contained STDIN, i.e. the data piped to your script. For example:
$ echo "glark" | ruby -e 'p ARGF.read' "glark\n"
The GetoptLong class allows you to parse command line options similarly to the GNU getopt_long() C library call. Note, however, that GetoptLong is a pure Ruby implementation.
GetoptLong allows for POSIX-style options like --file as well as single letter options like -f
The empty option -- (two minus symbols) is used to end option processing. This can be particularly important if options have optional arguments.
Here is a simple example of usage:
require 'getoptlong' opts = GetoptLong.new( [ '--help', '-h', GetoptLong::NO_ARGUMENT ], [ '--repeat', '-n', GetoptLong::REQUIRED_ARGUMENT ], [ '--name', GetoptLong::OPTIONAL_ARGUMENT ] ) dir = nil name = nil repetitions = 1 opts.each do |opt, arg| case opt when '--help' puts <<-EOF hello [OPTION] ... DIR -h, --help: show help --repeat x, -n x: repeat x times --name [name]: greet user by name, if name not supplied default is John DIR: The directory in which to issue the greeting. EOF when '--repeat' repetitions = arg.to_i when '--name' if arg == '' name = 'John' else name = arg end end end if ARGV.length != 1 puts "Missing dir argument (try --help)" exit 0 end dir = ARGV.shift Dir.chdir(dir) for i in (1..repetitions) print "Hello" if name print ", #{name}" end puts end
Example command line:
hello -n 6 --name -- /tmp
IPAddr provides a set of methods to manipulate an IP address. Both IPv4 and IPv6 are supported.
require 'ipaddr' ipaddr1 = IPAddr.new "3ffe:505:2::1" p ipaddr1 #=> #<IPAddr: IPv6:3ffe:0505:0002:0000:0000:0000:0000:0001/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff> p ipaddr1.to_s #=> "3ffe:505:2::1" ipaddr2 = ipaddr1.mask(48) #=> #<IPAddr: IPv6:3ffe:0505:0002:0000:0000:0000:0000:0000/ffff:ffff:ffff:0000:0000:0000:0000:0000> p ipaddr2.to_s #=> "3ffe:505:2::" ipaddr3 = IPAddr.new "192.168.2.0/24" p ipaddr3 #=> #<IPAddr: IPv4:192.168.2.0/255.255.255.0>
The Warning module contains a single method named warn, and the module extends itself, making Warning.warn available. Warning.warn is called for all warnings issued by Ruby. By default, warnings are printed to $stderr.
Changing the behavior of Warning.warn is useful to customize how warnings are handled by Ruby, for instance by filtering some warnings, and/or outputting warnings somewhere other than $stderr.
If you want to change the behavior of Warning.warn you should use +Warning.extend(MyNewModuleWithWarnMethod)+ and you can use ‘super` to get the default behavior of printing the warning to $stderr.
Example:
module MyWarningFilter def warn(message, category: nil, **kwargs) if /some warning I want to ignore/.match?(message) # ignore else super end end end Warning.extend MyWarningFilter
You should never redefine Warning#warn (the instance method), as that will then no longer provide a way to use the default behavior.
The warning gem provides convenient ways to customize Warning.warn.
newton.rb
Solves the nonlinear algebraic equation system f = 0 by Newton’s method. This program is not dependent on BigDecimal.
To call:
n = nlsolve(f,x)
where n is the number of iterations required,
x is the initial value vector
f is an Object which is used to compute the values of the equations to be solved.
It must provide the following methods:
returns the values of all functions at x
returns 0.0
returns 1.0
returns 2.0
returns 10.0
returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal.
On exit, x is the solution vector.
JSON is a lightweight data-interchange format.
A JSON value is one of the following:
Double-quoted text: "foo".
Number: 1, 1.0, 2.0e2.
Boolean: true, false.
Null: null.
Array: an ordered list of values, enclosed by square brackets:
["foo", 1, 1.0, 2.0e2, true, false, null]
Object: a collection of name/value pairs, enclosed by curly braces; each name is double-quoted text; the values may be any JSON values:
{"a": "foo", "b": 1, "c": 1.0, "d": 2.0e2, "e": true, "f": false, "g": null}
A JSON array or object may contain nested arrays, objects, and scalars to any depth:
{"foo": {"bar": 1, "baz": 2}, "bat": [0, 1, 2]}
[{"foo": 0, "bar": 1}, ["baz", 2]]
To make module JSON available in your code, begin with:
require 'json'
All examples here assume that this has been done.
You can parse a String containing JSON data using either of two methods:
where
source is a Ruby object.
opts is a Hash object containing options that control both input allowed and output formatting.
The difference between the two methods is that JSON.parse! omits some checks and may not be safe for some source data; use it only for data from trusted sources. Use the safer method JSON.parse for less trusted sources.
When source is a JSON array, JSON.parse by default returns a Ruby Array:
json = '["foo", 1, 1.0, 2.0e2, true, false, null]' ruby = JSON.parse(json) ruby # => ["foo", 1, 1.0, 200.0, true, false, nil] ruby.class # => Array
The JSON array may contain nested arrays, objects, and scalars to any depth:
json = '[{"foo": 0, "bar": 1}, ["baz", 2]]' JSON.parse(json) # => [{"foo"=>0, "bar"=>1}, ["baz", 2]]
When the source is a JSON object, JSON.parse by default returns a Ruby Hash:
json = '{"a": "foo", "b": 1, "c": 1.0, "d": 2.0e2, "e": true, "f": false, "g": null}' ruby = JSON.parse(json) ruby # => {"a"=>"foo", "b"=>1, "c"=>1.0, "d"=>200.0, "e"=>true, "f"=>false, "g"=>nil} ruby.class # => Hash
The JSON object may contain nested arrays, objects, and scalars to any depth:
json = '{"foo": {"bar": 1, "baz": 2}, "bat": [0, 1, 2]}' JSON.parse(json) # => {"foo"=>{"bar"=>1, "baz"=>2}, "bat"=>[0, 1, 2]}
When the source is a JSON scalar (not an array or object), JSON.parse returns a Ruby scalar.
String:
ruby = JSON.parse('"foo"') ruby # => 'foo' ruby.class # => String
Integer:
ruby = JSON.parse('1') ruby # => 1 ruby.class # => Integer
Float:
ruby = JSON.parse('1.0') ruby # => 1.0 ruby.class # => Float ruby = JSON.parse('2.0e2') ruby # => 200 ruby.class # => Float
Boolean:
ruby = JSON.parse('true') ruby # => true ruby.class # => TrueClass ruby = JSON.parse('false') ruby # => false ruby.class # => FalseClass
Null:
ruby = JSON.parse('null') ruby # => nil ruby.class # => NilClass
Option max_nesting (Integer) specifies the maximum nesting depth allowed; defaults to 100; specify false to disable depth checking.
With the default, false:
source = '[0, [1, [2, [3]]]]' ruby = JSON.parse(source) ruby # => [0, [1, [2, [3]]]]
Too deep:
# Raises JSON::NestingError (nesting of 2 is too deep): JSON.parse(source, {max_nesting: 1})
Bad value:
# Raises TypeError (wrong argument type Symbol (expected Fixnum)): JSON.parse(source, {max_nesting: :foo})
Option allow_nan (boolean) specifies whether to allow NaN, Infinity, and MinusInfinity in source; defaults to false.
With the default, false:
# Raises JSON::ParserError (225: unexpected token at '[NaN]'): JSON.parse('[NaN]') # Raises JSON::ParserError (232: unexpected token at '[Infinity]'): JSON.parse('[Infinity]') # Raises JSON::ParserError (248: unexpected token at '[-Infinity]'): JSON.parse('[-Infinity]')
Allow:
source = '[NaN, Infinity, -Infinity]' ruby = JSON.parse(source, {allow_nan: true}) ruby # => [NaN, Infinity, -Infinity]
Option symbolize_names (boolean) specifies whether returned Hash keys should be Symbols; defaults to false (use Strings).
With the default, false:
source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}' ruby = JSON.parse(source) ruby # => {"a"=>"foo", "b"=>1.0, "c"=>true, "d"=>false, "e"=>nil}
Use Symbols:
ruby = JSON.parse(source, {symbolize_names: true}) ruby # => {:a=>"foo", :b=>1.0, :c=>true, :d=>false, :e=>nil}
Option object_class (Class) specifies the Ruby class to be used for each JSON object; defaults to Hash.
With the default, Hash:
source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}' ruby = JSON.parse(source) ruby.class # => Hash
Use class OpenStruct:
ruby = JSON.parse(source, {object_class: OpenStruct}) ruby # => #<OpenStruct a="foo", b=1.0, c=true, d=false, e=nil>
Option array_class (Class) specifies the Ruby class to be used for each JSON array; defaults to Array.
With the default, Array:
source = '["foo", 1.0, true, false, null]' ruby = JSON.parse(source) ruby.class # => Array
Use class Set:
ruby = JSON.parse(source, {array_class: Set}) ruby # => #<Set: {"foo", 1.0, true, false, nil}>
Option create_additions (boolean) specifies whether to use JSON additions in parsing. See JSON Additions.
To generate a Ruby String containing JSON data, use method JSON.generate(source, opts), where
source is a Ruby object.
opts is a Hash object containing options that control both input allowed and output formatting.
When the source is a Ruby Array, JSON.generate returns a String containing a JSON array:
ruby = [0, 's', :foo] json = JSON.generate(ruby) json # => '[0,"s","foo"]'
The Ruby Array array may contain nested arrays, hashes, and scalars to any depth:
ruby = [0, [1, 2], {foo: 3, bar: 4}] json = JSON.generate(ruby) json # => '[0,[1,2],{"foo":3,"bar":4}]'
When the source is a Ruby Hash, JSON.generate returns a String containing a JSON object:
ruby = {foo: 0, bar: 's', baz: :bat} json = JSON.generate(ruby) json # => '{"foo":0,"bar":"s","baz":"bat"}'
The Ruby Hash array may contain nested arrays, hashes, and scalars to any depth:
ruby = {foo: [0, 1], bar: {baz: 2, bat: 3}, bam: :bad} json = JSON.generate(ruby) json # => '{"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}'
When the source is neither an Array nor a Hash, the generated JSON data depends on the class of the source.
When the source is a Ruby Integer or Float, JSON.generate returns a String containing a JSON number:
JSON.generate(42) # => '42' JSON.generate(0.42) # => '0.42'
When the source is a Ruby String, JSON.generate returns a String containing a JSON string (with double-quotes):
JSON.generate('A string') # => '"A string"'
When the source is true, false or nil, JSON.generate returns a String containing the corresponding JSON token:
JSON.generate(true) # => 'true' JSON.generate(false) # => 'false' JSON.generate(nil) # => 'null'
When the source is none of the above, JSON.generate returns a String containing a JSON string representation of the source:
JSON.generate(:foo) # => '"foo"' JSON.generate(Complex(0, 0)) # => '"0+0i"' JSON.generate(Dir.new('.')) # => '"#<Dir>"'
Option allow_nan (boolean) specifies whether NaN, Infinity, and -Infinity may be generated; defaults to false.
With the default, false:
# Raises JSON::GeneratorError (920: NaN not allowed in JSON): JSON.generate(JSON::NaN) # Raises JSON::GeneratorError (917: Infinity not allowed in JSON): JSON.generate(JSON::Infinity) # Raises JSON::GeneratorError (917: -Infinity not allowed in JSON): JSON.generate(JSON::MinusInfinity)
Allow:
ruby = [Float::NaN, Float::Infinity, Float::MinusInfinity] JSON.generate(ruby, allow_nan: true) # => '[NaN,Infinity,-Infinity]'
Option max_nesting (Integer) specifies the maximum nesting depth in obj; defaults to 100.
With the default, 100:
obj = [[[[[[0]]]]]] JSON.generate(obj) # => '[[[[[[0]]]]]]'
Too deep:
# Raises JSON::NestingError (nesting of 2 is too deep): JSON.generate(obj, max_nesting: 2)
The default formatting options generate the most compact JSON data, all on one line and with no whitespace.
You can use these formatting options to generate JSON data in a more open format, using whitespace. See also JSON.pretty_generate.
Option array_nl (String) specifies a string (usually a newline) to be inserted after each JSON array; defaults to the empty String, ''.
Option object_nl (String) specifies a string (usually a newline) to be inserted after each JSON object; defaults to the empty String, ''.
Option indent (String) specifies the string (usually spaces) to be used for indentation; defaults to the empty String, ''; defaults to the empty String, ''; has no effect unless options array_nl or object_nl specify newlines.
Option space (String) specifies a string (usually a space) to be inserted after the colon in each JSON object’s pair; defaults to the empty String, ''.
Option space_before (String) specifies a string (usually a space) to be inserted before the colon in each JSON object’s pair; defaults to the empty String, ''.
In this example, obj is used first to generate the shortest JSON data (no whitespace), then again with all formatting options specified:
obj = {foo: [:bar, :baz], bat: {bam: 0, bad: 1}} json = JSON.generate(obj) puts 'Compact:', json opts = { array_nl: "\n", object_nl: "\n", indent: ' ', space_before: ' ', space: ' ' } puts 'Open:', JSON.generate(obj, opts)
Output:
Compact:
{"foo":["bar","baz"],"bat":{"bam":0,"bad":1}}
Open:
{
"foo" : [
"bar",
"baz"
],
"bat" : {
"bam" : 0,
"bad" : 1
}
}
When you “round trip” a non-String object from Ruby to JSON and back, you have a new String, instead of the object you began with:
ruby0 = Range.new(0, 2) json = JSON.generate(ruby0) json # => '0..2"' ruby1 = JSON.parse(json) ruby1 # => '0..2' ruby1.class # => String
You can use JSON additions to preserve the original object. The addition is an extension of a ruby class, so that:
JSON.generate stores more information in the JSON string.
JSON.parse, called with option create_additions, uses that information to create a proper Ruby object.
This example shows a Range being generated into JSON and parsed back into Ruby, both without and with the addition for Range:
ruby = Range.new(0, 2) # This passage does not use the addition for Range. json0 = JSON.generate(ruby) ruby0 = JSON.parse(json0) # This passage uses the addition for Range. require 'json/add/range' json1 = JSON.generate(ruby) ruby1 = JSON.parse(json1, create_additions: true) # Make a nice display. display = <<EOT Generated JSON: Without addition: #{json0} (#{json0.class}) With addition: #{json1} (#{json1.class}) Parsed JSON: Without addition: #{ruby0.inspect} (#{ruby0.class}) With addition: #{ruby1.inspect} (#{ruby1.class}) EOT puts display
This output shows the different results:
Generated JSON:
Without addition: "0..2" (String)
With addition: {"json_class":"Range","a":[0,2,false]} (String)
Parsed JSON:
Without addition: "0..2" (String)
With addition: 0..2 (Range)
The JSON module includes additions for certain classes. You can also craft custom additions. See Custom JSON Additions.
The JSON module includes additions for certain classes. To use an addition, require its source:
BigDecimal: require 'json/add/bigdecimal'
Complex: require 'json/add/complex'
Date: require 'json/add/date'
DateTime: require 'json/add/date_time'
Exception: require 'json/add/exception'
OpenStruct: require 'json/add/ostruct'
Range: require 'json/add/range'
Rational: require 'json/add/rational'
Regexp: require 'json/add/regexp'
Set: require 'json/add/set'
Struct: require 'json/add/struct'
Symbol: require 'json/add/symbol'
Time: require 'json/add/time'
To reduce punctuation clutter, the examples below show the generated JSON via puts, rather than the usual inspect,
BigDecimal:
require 'json/add/bigdecimal' ruby0 = BigDecimal(0) # 0.0 json = JSON.generate(ruby0) # {"json_class":"BigDecimal","b":"27:0.0"} ruby1 = JSON.parse(json, create_additions: true) # 0.0 ruby1.class # => BigDecimal
Complex:
require 'json/add/complex' ruby0 = Complex(1+0i) # 1+0i json = JSON.generate(ruby0) # {"json_class":"Complex","r":1,"i":0} ruby1 = JSON.parse(json, create_additions: true) # 1+0i ruby1.class # Complex
Date:
require 'json/add/date' ruby0 = Date.today # 2020-05-02 json = JSON.generate(ruby0) # {"json_class":"Date","y":2020,"m":5,"d":2,"sg":2299161.0} ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02 ruby1.class # Date
DateTime:
require 'json/add/date_time' ruby0 = DateTime.now # 2020-05-02T10:38:13-05:00 json = JSON.generate(ruby0) # {"json_class":"DateTime","y":2020,"m":5,"d":2,"H":10,"M":38,"S":13,"of":"-5/24","sg":2299161.0} ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02T10:38:13-05:00 ruby1.class # DateTime
Exception (and its subclasses including RuntimeError):
require 'json/add/exception' ruby0 = Exception.new('A message') # A message json = JSON.generate(ruby0) # {"json_class":"Exception","m":"A message","b":null} ruby1 = JSON.parse(json, create_additions: true) # A message ruby1.class # Exception ruby0 = RuntimeError.new('Another message') # Another message json = JSON.generate(ruby0) # {"json_class":"RuntimeError","m":"Another message","b":null} ruby1 = JSON.parse(json, create_additions: true) # Another message ruby1.class # RuntimeError
OpenStruct:
require 'json/add/ostruct' ruby0 = OpenStruct.new(name: 'Matz', language: 'Ruby') # #<OpenStruct name="Matz", language="Ruby"> json = JSON.generate(ruby0) # {"json_class":"OpenStruct","t":{"name":"Matz","language":"Ruby"}} ruby1 = JSON.parse(json, create_additions: true) # #<OpenStruct name="Matz", language="Ruby"> ruby1.class # OpenStruct
Range:
require 'json/add/range' ruby0 = Range.new(0, 2) # 0..2 json = JSON.generate(ruby0) # {"json_class":"Range","a":[0,2,false]} ruby1 = JSON.parse(json, create_additions: true) # 0..2 ruby1.class # Range
Rational:
require 'json/add/rational' ruby0 = Rational(1, 3) # 1/3 json = JSON.generate(ruby0) # {"json_class":"Rational","n":1,"d":3} ruby1 = JSON.parse(json, create_additions: true) # 1/3 ruby1.class # Rational
Regexp:
require 'json/add/regexp' ruby0 = Regexp.new('foo') # (?-mix:foo) json = JSON.generate(ruby0) # {"json_class":"Regexp","o":0,"s":"foo"} ruby1 = JSON.parse(json, create_additions: true) # (?-mix:foo) ruby1.class # Regexp
Set:
require 'json/add/set' ruby0 = Set.new([0, 1, 2]) # #<Set: {0, 1, 2}> json = JSON.generate(ruby0) # {"json_class":"Set","a":[0,1,2]} ruby1 = JSON.parse(json, create_additions: true) # #<Set: {0, 1, 2}> ruby1.class # Set
Struct:
require 'json/add/struct' Customer = Struct.new(:name, :address) # Customer ruby0 = Customer.new("Dave", "123 Main") # #<struct Customer name="Dave", address="123 Main"> json = JSON.generate(ruby0) # {"json_class":"Customer","v":["Dave","123 Main"]} ruby1 = JSON.parse(json, create_additions: true) # #<struct Customer name="Dave", address="123 Main"> ruby1.class # Customer
Symbol:
require 'json/add/symbol' ruby0 = :foo # foo json = JSON.generate(ruby0) # {"json_class":"Symbol","s":"foo"} ruby1 = JSON.parse(json, create_additions: true) # foo ruby1.class # Symbol
Time:
require 'json/add/time' ruby0 = Time.now # 2020-05-02 11:28:26 -0500 json = JSON.generate(ruby0) # {"json_class":"Time","s":1588436906,"n":840560000} ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02 11:28:26 -0500 ruby1.class # Time
In addition to the JSON additions provided, you can craft JSON additions of your own, either for Ruby built-in classes or for user-defined classes.
Here’s a user-defined class Foo:
class Foo attr_accessor :bar, :baz def initialize(bar, baz) self.bar = bar self.baz = baz end end
Here’s the JSON addition for it:
# Extend class Foo with JSON addition. class Foo # Serialize Foo object with its class name and arguments def to_json(*args) { JSON.create_id => self.class.name, 'a' => [ bar, baz ] }.to_json(*args) end # Deserialize JSON string by constructing new Foo object with arguments. def self.json_create(object) new(*object['a']) end end
Demonstration:
require 'json' # This Foo object has no custom addition. foo0 = Foo.new(0, 1) json0 = JSON.generate(foo0) obj0 = JSON.parse(json0) # Lood the custom addition. require_relative 'foo_addition' # This foo has the custom addition. foo1 = Foo.new(0, 1) json1 = JSON.generate(foo1) obj1 = JSON.parse(json1, create_additions: true) # Make a nice display. display = <<EOT Generated JSON: Without custom addition: #{json0} (#{json0.class}) With custom addition: #{json1} (#{json1.class}) Parsed JSON: Without custom addition: #{obj0.inspect} (#{obj0.class}) With custom addition: #{obj1.inspect} (#{obj1.class}) EOT puts display
Output:
Generated JSON:
Without custom addition: "#<Foo:0x0000000006534e80>" (String)
With custom addition: {"json_class":"Foo","a":[0,1]} (String)
Parsed JSON:
Without custom addition: "#<Foo:0x0000000006534e80>" (String)
With custom addition: #<Foo:0x0000000006473bb8 @bar=0, @baz=1> (Foo)
Kanji Converter for Ruby.
The objspace library extends the ObjectSpace module and adds several methods to get internal statistic information about object/memory management.
You need to require 'objspace' to use this extension module.
Generally, you *SHOULD NOT* use this library if you do not know about the MRI implementation. Mainly, this library is for (memory) profiler developers and MRI developers who need to know about MRI memory usage.
The ObjectSpace module contains a number of routines that interact with the garbage collection facility and allow you to traverse all living objects with an iterator.
ObjectSpace also provides support for object finalizers, procs that will be called when a specific object is about to be destroyed by garbage collection. See the documentation for ObjectSpace.define_finalizer for important information on how to use this method correctly.
a = "A" b = "B" ObjectSpace.define_finalizer(a, proc {|id| puts "Finalizer one on #{id}" }) ObjectSpace.define_finalizer(b, proc {|id| puts "Finalizer two on #{id}" }) a = nil b = nil
produces:
Finalizer two on 537763470 Finalizer one on 537763480
The Benchmark module provides methods to measure and report the time used to execute Ruby code.
Measure the time to construct the string given by the expression "a"*1_000_000_000:
require 'benchmark' puts Benchmark.measure { "a"*1_000_000_000 }
On my machine (OSX 10.8.3 on i5 1.7 GHz) this generates:
0.350000 0.400000 0.750000 ( 0.835234)
This report shows the user CPU time, system CPU time, the sum of the user and system CPU times, and the elapsed real time. The unit of time is seconds.
Do some experiments sequentially using the bm method:
require 'benchmark' n = 5000000 Benchmark.bm do |x| x.report { for i in 1..n; a = "1"; end } x.report { n.times do ; a = "1"; end } x.report { 1.upto(n) do ; a = "1"; end } end
The result:
user system total real 1.010000 0.000000 1.010000 ( 1.014479) 1.000000 0.000000 1.000000 ( 0.998261) 0.980000 0.000000 0.980000 ( 0.981335)
Continuing the previous example, put a label in each report:
require 'benchmark' n = 5000000 Benchmark.bm(7) do |x| x.report("for:") { for i in 1..n; a = "1"; end } x.report("times:") { n.times do ; a = "1"; end } x.report("upto:") { 1.upto(n) do ; a = "1"; end } end
The result:
user system total real for: 1.010000 0.000000 1.010000 ( 1.015688) times: 1.000000 0.000000 1.000000 ( 1.003611) upto: 1.030000 0.000000 1.030000 ( 1.028098)
The times for some benchmarks depend on the order in which items are run. These differences are due to the cost of memory allocation and garbage collection. To avoid these discrepancies, the bmbm method is provided. For example, to compare ways to sort an array of floats:
require 'benchmark' array = (1..1000000).map { rand } Benchmark.bmbm do |x| x.report("sort!") { array.dup.sort! } x.report("sort") { array.dup.sort } end
The result:
Rehearsal -----------------------------------------
sort! 1.490000 0.010000 1.500000 ( 1.490520)
sort 1.460000 0.000000 1.460000 ( 1.463025)
-------------------------------- total: 2.960000sec
user system total real
sort! 1.460000 0.000000 1.460000 ( 1.460465)
sort 1.450000 0.010000 1.460000 ( 1.448327)
Report statistics of sequential experiments with unique labels, using the benchmark method:
require 'benchmark' include Benchmark # we need the CAPTION and FORMAT constants n = 5000000 Benchmark.benchmark(CAPTION, 7, FORMAT, ">total:", ">avg:") do |x| tf = x.report("for:") { for i in 1..n; a = "1"; end } tt = x.report("times:") { n.times do ; a = "1"; end } tu = x.report("upto:") { 1.upto(n) do ; a = "1"; end } [tf+tt+tu, (tf+tt+tu)/3] end
The result:
user system total real for: 0.950000 0.000000 0.950000 ( 0.952039) times: 0.980000 0.000000 0.980000 ( 0.984938) upto: 0.950000 0.000000 0.950000 ( 0.946787) >total: 2.880000 0.000000 2.880000 ( 2.883764) >avg: 0.960000 0.000000 0.960000 ( 0.961255)
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!"
You could use Forwardable as an alternative to inheritance, when you don’t want to inherit all methods from the superclass. For instance, here is how you might add a range of Array instance methods to a new class Queue:
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 = Thread::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.