Simple Access Control Lists.
Access control lists are composed of “allow” and “deny” halves to control access. Use “all” or “*” to match any address. To match a specific address use any address or address mask that IPAddr can understand.
Example:
list = %w[
deny all
allow 192.168.1.1
allow ::ffff:192.168.1.2
allow 192.168.1.3
]
# From Socket#peeraddr, see also ACL#allow_socket?
addr = ["AF_INET", 10, "lc630", "192.168.1.3"]
acl = ACL.new
p acl.allow_addr?(addr) # => true
acl = ACL.new(list, ACL::DENY_ALLOW)
p acl.allow_addr?(addr) # => true
An entry in an ACL
A list of ACLEntry objects. Used to implement the allow and deny halves of an ACL
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 Addrinfo class maps struct addrinfo to ruby. This structure identifies an Internet host and a service.
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
Arrays are ordered, integer-indexed collections of any object.
Array indexing starts at 0, as in C or Java. A negative index is assumed to be relative to the end of the array—that is, an index of -1 indicates the last element of the array, -2 is the next to last element in the array, and so on.
Creating Arrays¶ ↑
A new array can be created by using the literal constructor []. Arrays 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 explicitly 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"]]
Example Usage¶ ↑
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.
Accessing Elements¶ ↑
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]
Obtaining Information about an 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
Adding Items to Arrays¶ ↑
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]
Removing Items from an 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]
Iterating over Arrays¶ ↑
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]
Selecting Items from an 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.
Non-destructive Selection¶ ↑
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]
Destructive Selection¶ ↑
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]
BasicObject is the parent class of all classes in Ruby. It's an explicit blank class.
BasicObject can be used for creating object hierarchies independent of Ruby's object hierarchy, proxy objects like the Delegator class, or other uses where namespace pollution from Ruby's methods and classes must be avoided.
To avoid polluting BasicObject for other users an appropriately named subclass of BasicObject should be created instead of directly modifying BasicObject:
class MyObjectSystem < BasicObject
end
BasicObject does not include Kernel (for methods like puts) and BasicObject is outside of the namespace of the standard library so common classes will not be found without using a full class path.
A variety of strategies can be used to provide useful portions of the standard library to subclasses of BasicObject. A subclass could include Kernel to obtain puts, exit, etc. A custom Kernel-like module could be created and included or delegation can be used via method_missing:
class MyObjectSystem < BasicObject
DELEGATE = [:puts, :p]
def method_missing(name, *args, &block)
super unless DELEGATE.include? name
::Kernel.send(name, *args, &block)
end
def respond_to_missing?(name, include_private = false)
DELEGATE.include?(name) or super
end
end
Access to classes and modules from the Ruby standard library can be obtained in a BasicObject subclass by referencing the desired constant from the root like ::File or ::Enumerator. Like method_missing, const_missing can be used to delegate constant lookup to Object:
class MyObjectSystem < BasicObject
def self.const_missing(name)
::Object.const_get(name)
end
end
BasicSocket is the super class for all the Socket classes.
A data object, representing the times associated with a benchmark measurement.
BigDecimal provides arbitrary-precision floating point decimal arithmetic.
Introduction¶ ↑
Ruby provides built-in support for arbitrary precision integer arithmetic.
For example:
42**13 #=> 1265437718438866624512
BigDecimal provides similar support for very large or very accurate floating point numbers.
Decimal arithmetic is also useful for general calculation, because it provides the correct answers people expect–whereas normal binary floating point arithmetic often introduces subtle errors because of the conversion between base 10 and base 2.
For example, try:
sum = 0
10_000.times do
sum = sum + 0.0001
end
print sum #=> 0.9999999999999062
and contrast with the output from:
require 'bigdecimal'
sum = BigDecimal("0")
10_000.times do
sum = sum + BigDecimal("0.0001")
end
print sum #=> 0.1E1
Similarly:
(BigDecimal("1.2") - BigDecimal("1.0")) == BigDecimal("0.2") #=> true
(1.2 - 1.0) == 0.2 #=> false
Special features of accurate decimal arithmetic¶ ↑
Because BigDecimal is more accurate than normal binary floating point arithmetic, it requires some special values.
Infinity¶ ↑
BigDecimal sometimes needs to return infinity, for example if you divide a value by zero.
BigDecimal("1.0") / BigDecimal("0.0") #=> Infinity
BigDecimal("-1.0") / BigDecimal("0.0") #=> -Infinity
You can represent infinite numbers to BigDecimal using the strings 'Infinity', '+Infinity' and '-Infinity' (case-sensitive)
Not a Number¶ ↑
When a computation results in an undefined value, the special value NaN (for 'not a number') is returned.
Example:
BigDecimal("0.0") / BigDecimal("0.0") #=> NaN
You can also create undefined values.
NaN is never considered to be the same as any other value, even NaN itself:
n = BigDecimal('NaN')
n == 0.0 #=> false
n == n #=> false
Positive and negative zero¶ ↑
If a computation results in a value which is too small to be represented as a BigDecimal within the currently specified limits of precision, zero must be returned.
If the value which is too small to be represented is negative, a BigDecimal value of negative zero is returned.
BigDecimal("1.0") / BigDecimal("-Infinity") #=> -0.0
If the value is positive, a value of positive zero is returned.
BigDecimal("1.0") / BigDecimal("Infinity") #=> 0.0
(See BigDecimal.mode for how to specify limits of precision.)
Note that -0.0 and 0.0 are considered to be the same for the purposes of comparison.
Note also that in mathematics, there is no particular concept of negative or positive zero; true mathematical zero has no sign.
bigdecimal/util¶ ↑
When you require bigdecimal/util, the to_d method will be available on BigDecimal and the native Integer, Float, Rational, and String classes:
require 'bigdecimal/util'
42.to_d # => 0.42e2
0.5.to_d # => 0.5e0
(2/3r).to_d(3) # => 0.667e0
"0.5".to_d # => 0.5e0
License¶ ↑
Copyright (C) 2002 by Shigeo Kobayashi <[email protected]>.
BigDecimal is released under the Ruby and 2-clause BSD licenses. See LICENSE.txt for details.
Maintained by mrkn <[email protected]> and ruby-core members.
Documented by zzak <[email protected]>, mathew <[email protected]>, and many other contributors.
Objects of class Binding encapsulate the execution context at some particular place in the code and retain this context for future use. The variables, methods, value of self, and possibly an iterator block that can be accessed in this context are all retained. Binding objects can be created using Kernel#binding, and are made available to the callback of Kernel#set_trace_func.
These binding objects can be passed as the second argument of the Kernel#eval method, establishing an environment for the evaluation.
class Demo
def initialize(n)
@secret = n
end
def get_binding
binding
end
end
k1 = Demo.new(99)
b1 = k1.get_binding
k2 = Demo.new(-3)
b2 = k2.get_binding
eval("@secret", b1) #=> 99
eval("@secret", b2) #=> -3
eval("@secret") #=> nil
Binding objects have no class-specific methods.
used for Creating Specifications from the Gemcutter Endpoint
Handles all the fetching with the rubygems server
This error is raised if HTTP authentication is required, but not provided.
This error is raised if HTTP authentication is provided, but incorrect.
This is the error raised if OpenSSL fails the cert verification
This error is raised if the API returns a 413 (only printed in verbose)
This error is raised when it looks like the network is down
This is the error raised when a source is HTTPS and OpenSSL didn't load
Adds support for setting custom HTTP headers when fetching gems from the server.
TODO: Get rid of this when and if gemstash only supports RubyGems versions that contain github.com/rubygems/rubygems/commit/3db265cc20b2f813.
This class contains all of the logic for determining the next version of a Gem to update to based on the requested level (patch, minor, major). Primarily designed to work with Resolver which will provide it the list of available dependency versions as found in its index, before returning it to to the resolution engine to select the best version.
Class used to build the list of sockets that correspond to
a given mirror.
One mirror may correspond to many different addresses, both
because of it having many dns entries or because
the network interface is both ipv4 and ipv5
An error caused by attempting to fulfil a dependency that was circular
@note This exception will be thrown iff a {Vertex} is added to a
{DependencyGraph} that has a {DependencyGraph::Vertex#path_to?} an
existing {DependencyGraph::Vertex}
A directed acyclic graph that is tuned to hold named dependencies
An action that modifies a {DependencyGraph} that is reversible. @abstract
@!visibility private (see DependencyGraph#add_edge_no_circular)
@!visibility private (see DependencyGraph#delete_edge)
@!visibility private @see DependencyGraph#detach_vertex_named
A log for dependency graph actions
@!visibility private @see DependencyGraph#tag
A vertex in a {DependencyGraph} that encapsulates a {#name} and a {#payload}
A state that encapsulates a set of {#requirements} with an {Array} of possibilities
An error caused by searching for a dependency that is completely unknown, i.e. has no versions available whatsoever.
A state that encapsulates a single possibility to fulfill the given {#requirement}
This class encapsulates a dependency resolver. The resolver is responsible for determining which set of dependencies to activate, with feedback from the {#specification_provider}
A specific resolution from a given {Resolver}
An error that occurred during the resolution process
An error caused by conflicts in version
Persistent connections for Net::HTTP
Bundler::Persistent::Net::HTTP::Persistent maintains persistent connections across all the servers you wish to talk to. For each host:port you communicate with a single persistent connection is created.
Multiple Bundler::Persistent::Net::HTTP::Persistent objects will share the same set of connections.
For each thread you start a new connection will be created. A Bundler::Persistent::Net::HTTP::Persistent connection will not be shared across threads.
You can shut down the HTTP connections when done by calling shutdown. You should name your Bundler::Persistent::Net::HTTP::Persistent object if you intend to call this method.
Example:
require 'bundler/vendor/net-http-persistent/lib/net/http/persistent'
uri = URI 'http://example.com/awesome/web/service'
http = Bundler::Persistent::Net::HTTP::Persistent.new 'my_app_name'
# perform a GET
response = http.request uri
# or
get = Net::HTTP::Get.new uri.request_uri
response = http.request get
# create a POST
post_uri = uri + 'create'
post = Net::HTTP::Post.new post_uri.path
post.set_form_data 'some' => 'cool data'
# perform the POST, the URI is always required
response http.request post_uri, post
Note that for GET, HEAD and other requests that do not have a body you want to use URI#request_uri not URI#path. The request_uri contains the query params which are sent in the body for other requests.
SSL¶ ↑
SSL connections are automatically created depending upon the scheme of the URI. SSL connections are automatically verified against the default certificate store for your computer. You can override this by changing verify_mode or by specifying an alternate cert_store.
Here are the SSL settings, see the individual methods for documentation:
certificate
This client's certificate
ca_file
The certificate-authority
cert_store
An SSL certificate store
private_key
The client's SSL private key
reuse_ssl_sessions
Reuse a previously opened SSL session for a new connection
ssl_version
Which specific SSL version to use
verify_callback
For server certificate verification
verify_mode
How connections should be verified
Proxies¶ ↑
A proxy can be set through proxy= or at initialization time by providing a second argument to ::new. The proxy may be the URI of the proxy server or :ENV which will consult environment variables.
See proxy= and proxy_from_env for details.
Headers¶ ↑
Headers may be specified for use in every request. headers are appended to any headers on the request. override_headers replace existing headers on the request.
The difference between the two can be seen in setting the User-Agent. Using http.headers['User-Agent'] = 'MyUserAgent' will send “Ruby, MyUserAgent” while http.override_headers['User-Agent'] = 'MyUserAgent' will send “MyUserAgent”.
Tuning¶ ↑
Segregation¶ ↑
By providing an application name to ::new you can separate your connections from the connections of other applications.
Idle Timeout¶ ↑
If a connection hasn't been used for this number of seconds it will automatically be reset upon the next use to avoid attempting to send to a closed connection. The default value is 5 seconds. nil means no timeout. Set through idle_timeout.
Reducing this value may help avoid the “too many connection resets” error when sending non-idempotent requests while increasing this value will cause fewer round-trips.
Read Timeout¶ ↑
The amount of time allowed between reading two chunks from the socket. Set through read_timeout
Max Requests¶ ↑
The number of requests that should be made before opening a new connection. Typically many keep-alive capable servers tune this to 100 or less, so the 101st request will fail with ECONNRESET. If unset (default), this value has no effect, if set, connections will be reset on the request after max_requests.
Open Timeout¶ ↑
The amount of time to wait for a connection to be opened. Set through open_timeout.
Socket Options¶ ↑
Socket options may be set on newly-created connections. See socket_options for details.
Non-Idempotent Requests¶ ↑
By default non-idempotent requests will not be retried per RFC 2616. By setting retry_change_requests to true requests will automatically be retried once.
Only do this when you know that retrying a POST or other non-idempotent request is safe for your application and will not create duplicate resources.
The recommended way to handle non-idempotent requests is the following:
require 'bundler/vendor/net-http-persistent/lib/net/http/persistent'
uri = URI 'http://example.com/awesome/web/service'
post_uri = uri + 'create'
http = Bundler::Persistent::Net::HTTP::Persistent.new 'my_app_name'
post = Net::HTTP::Post.new post_uri.path
# ... fill in POST request
begin
response = http.request post_uri, post
rescue Bundler::Persistent::Net::HTTP::Persistent::Error
# POST failed, make a new request to verify the server did not process
# the request
exists_uri = uri + '...'
response = http.get exists_uri
# Retry if it failed
retry if response.code == '404'
end
The method of determining if the resource was created or not is unique to the particular service you are using. Of course, you will want to add protection from infinite looping.
Connection Termination¶ ↑
If you are done using the Bundler::Persistent::Net::HTTP::Persistent instance you may shut down all the connections in the current thread with shutdown. This is not recommended for normal use, it should only be used when it will be several minutes before you make another HTTP request.
If you are using multiple threads, call shutdown in each thread when the thread is done making requests. If you don't call shutdown, that's OK. Ruby will automatically garbage collect and shutdown your HTTP connections when the thread terminates.
Error class for errors raised by Bundler::Persistent::Net::HTTP::Persistent. Various SystemCallErrors are re-raised with a human-readable message under this class.
This Net::HTTP subclass adds SSL session reuse and Server Name Indication (SNI) RFC 3546.
DO NOT DEPEND UPON THIS CLASS
This class is an implementation detail and is subject to change or removal at any time.
Dsl to parse the Gemfile looking for plugins to install
Represents a lazily loaded gem specification, where the full specification is on the source server in rubygems' “quick” index. The proxy object is to be seeded with what we're given from the source's abbreviated index - the full specification will only be fetched when necessary.
General purpose class for retrying code that may fail
RubyGems 1.8.0 to 1.8.4
RubyGems versions 1.3.6 and 1.3.7
RubyGems 2.0
RubyGems 1.4 through 1.6
RubyGems 1.8.5-1.8.19
RubyGems 2.1.0
RubyGems 1.8.20+
RubyGems 1.7
A mirror
Contains both the uri that should be used as a mirror and the
fallback timeout which will be used for probing if the mirror
replies on time or not.
Class used to parse one configuration line
Gets the configuration line and the value.
This object provides a `update_mirror` method
used to setup the given mirror value.
Class used to build the mirror set and then find a mirror for a given URI
@param prober [Prober object, nil] by default a TCPSocketProbe, this object
will be used to probe the mirror address to validate that the mirror replies.
Class used for probing TCP availability for a given mirror.
Socket address builder.
Given a socket type, a host and a port,
provides a method to build sockaddr string
The GitProxy is responsible to interact with git repositories. All actions required by the Git source is encapsulated in this object.
Bundler::Thor::Actions#capture depends on what kind of buffer is used in ERB. Thus CapturableERB fixes ERB to use String buffer.
A dynamic command that handles method missing scenarios.
A dynamic command that handles method missing scenarios.
Bundler::Thor::Error is raised when it's caused by wrong usage of thor classes. Those errors have their backtrace suppressed and are nicely shown to the user.
Errors that are caused by the developer, like declaring a method which overwrites a thor keyword, SHOULD NOT raise a Bundler::Thor::Error. This way, we ensure that developer errors are shown with full backtrace.
Bundler::Thor has a special class called Bundler::Thor::Group. The main difference to Bundler::Thor class is that it invokes all commands at once. It also include some methods that allows invocations to be done at the class method, which are not available to Bundler::Thor commands.
A command that is hidden in help messages but still invocable.
A command that is hidden in help messages but still invocable.
Raised when a command was found, but not invoked properly.
Inherit from Bundler::Thor::Shell::Basic and add set_color behavior. Check Bundler::Thor::Shell::Basic to see all available methods.
Inherit from Bundler::Thor::Shell::Basic and add set_color behavior. Check Bundler::Thor::Shell::Basic to see all available methods.
Raised when a command was not found.
Raised when a command was not found.
Internal error, should be rescued
Overview¶ ↑
The Common Gateway Interface (CGI) is a simple protocol for passing an HTTP request from a web server to a standalone program, and returning the output to the web browser. Basically, a CGI program is called with the parameters of the request passed in either in the environment (GET) or via $stdin (POST), and everything it prints to $stdout is returned to the client.
This file holds the CGI class. This class provides functionality for retrieving HTTP request parameters, managing cookies, and generating HTML output.
The file CGI::Session provides session management functionality; see that class for more details.
See www.w3.org/CGI/ for more information on the CGI protocol.
Introduction¶ ↑
CGI is a large class, providing several categories of methods, many of which are mixed in from other modules. Some of the documentation is in this class, some in the modules CGI::QueryExtension and CGI::HtmlExtension. See CGI::Cookie for specific information on handling cookies, and cgi/session.rb (CGI::Session) for information on sessions.
For queries, CGI provides methods to get at environmental variables, parameters, cookies, and multipart request data. For responses, CGI provides methods for writing output and generating HTML.
Read on for more details. Examples are provided at the bottom.
Queries¶ ↑
The CGI class dynamically mixes in parameter and cookie-parsing functionality, environmental variable access, and support for parsing multipart requests (including uploaded files) from the CGI::QueryExtension module.
Environmental Variables¶ ↑
The standard CGI environmental variables are available as read-only attributes of a CGI object. The following is a list of these variables:
AUTH_TYPE HTTP_HOST REMOTE_IDENT
CONTENT_LENGTH HTTP_NEGOTIATE REMOTE_USER
CONTENT_TYPE HTTP_PRAGMA REQUEST_METHOD
GATEWAY_INTERFACE HTTP_REFERER SCRIPT_NAME
HTTP_ACCEPT HTTP_USER_AGENT SERVER_NAME
HTTP_ACCEPT_CHARSET PATH_INFO SERVER_PORT
HTTP_ACCEPT_ENCODING PATH_TRANSLATED SERVER_PROTOCOL
HTTP_ACCEPT_LANGUAGE QUERY_STRING SERVER_SOFTWARE
HTTP_CACHE_CONTROL REMOTE_ADDR
HTTP_FROM REMOTE_HOST
For each of these variables, there is a corresponding attribute with the same name, except all lower case and without a preceding HTTP_. content_length and server_port are integers; the rest are strings.
Parameters¶ ↑
The method params() returns a hash of all parameters in the request as name/value-list pairs, where the value-list is an Array of one or more values. The CGI object itself also behaves as a hash of parameter names to values, but only returns a single value (as a String) for each parameter name.
For instance, suppose the request contains the parameter “favourite_colours” with the multiple values “blue” and “green”. The following behavior would occur:
cgi.params["favourite_colours"] # => ["blue", "green"]
cgi["favourite_colours"] # => "blue"
If a parameter does not exist, the former method will return an empty array, the latter an empty string. The simplest way to test for existence of a parameter is by the has_key? method.
Cookies¶ ↑
HTTP Cookies are automatically parsed from the request. They are available from the cookies() accessor, which returns a hash from cookie name to CGI::Cookie object.
Multipart requests¶ ↑
If a request's method is POST and its content type is multipart/form-data, then it may contain uploaded files. These are stored by the QueryExtension module in the parameters of the request. The parameter name is the name attribute of the file input field, as usual. However, the value is not a string, but an IO object, either an IOString for small files, or a Tempfile for larger ones. This object also has the additional singleton methods:
local_path()
the path of the uploaded file on the local filesystem
original_filename()
the name of the file on the client computer
content_type()
the content type of the file
Responses¶ ↑
The CGI class provides methods for sending header and content output to the HTTP client, and mixes in methods for programmatic HTML generation from CGI::HtmlExtension and CGI::TagMaker modules. The precise version of HTML to use for HTML generation is specified at object creation time.
Writing output¶ ↑
The simplest way to send output to the HTTP client is using the out() method. This takes the HTTP headers as a hash parameter, and the body content via a block. The headers can be generated as a string using the http_header() method. The output stream can be written directly to using the print() method.
Generating HTML¶ ↑
Each HTML element has a corresponding method for generating that element as a String. The name of this method is the same as that of the element, all lowercase. The attributes of the element are passed in as a hash, and the body as a no-argument block that evaluates to a String. The HTML generation module knows which elements are always empty, and silently drops any passed-in body. It also knows which elements require matching closing tags and which don't. However, it does not know what attributes are legal for which elements.
There are also some additional HTML generation methods mixed in from the CGI::HtmlExtension module. These include individual methods for the different types of form inputs, and methods for elements that commonly take particular attributes where the attributes can be directly specified as arguments, rather than via a hash.
Utility HTML escape and other methods like a function.¶ ↑
There are some utility tool defined in cgi/util.rb . And when include, you can use utility methods like a function.
Examples of use¶ ↑
Get form values¶ ↑
require "cgi"
cgi = CGI.new
value = cgi['field_name'] # <== value string for 'field_name'
# if not 'field_name' included, then return "".
fields = cgi.keys # <== array of field names
# returns true if form has 'field_name'
cgi.has_key?('field_name')
cgi.has_key?('field_name')
cgi.include?('field_name')
CAUTION! cgi returned an Array with the old cgi.rb(included in Ruby 1.6)
Get form values as hash¶ ↑
require "cgi"
cgi = CGI.new
params = cgi.params
cgi.params is a hash.
cgi.params['new_field_name'] = ["value"] # add new param
cgi.params['field_name'] = ["new_value"] # change value
cgi.params.delete('field_name') # delete param
cgi.params.clear # delete all params
Save form values to file¶ ↑
require "pstore"
db = PStore.new("query.db")
db.transaction do
db["params"] = cgi.params
end
Restore form values from file¶ ↑
require "pstore"
db = PStore.new("query.db")
db.transaction do
cgi.params = db["params"]
end
Get multipart form values¶ ↑
require "cgi"
cgi = CGI.new
value = cgi['field_name'] # <== value string for 'field_name'
value.read # <== body of value
value.local_path # <== path to local file of value
value.original_filename # <== original filename of value
value.content_type # <== content_type of value
and value has StringIO or Tempfile class methods.
Get cookie values¶ ↑
require "cgi"
cgi = CGI.new
values = cgi.cookies['name'] # <== array of 'name'
# if not 'name' included, then return [].
names = cgi.cookies.keys # <== array of cookie names
and cgi.cookies is a hash.
Get cookie objects¶ ↑
require "cgi"
cgi = CGI.new
for name, cookie in cgi.cookies
cookie.expires = Time.now + 30
end
cgi.out("cookie" => cgi.cookies) {"string"}
cgi.cookies # { "name1" => cookie1, "name2" => cookie2, ... }
require "cgi"
cgi = CGI.new
cgi.cookies['name'].expires = Time.now + 30
cgi.out("cookie" => cgi.cookies['name']) {"string"}
Print http header and html string to $DEFAULT_OUTPUT ($>)¶ ↑
require "cgi"
cgi = CGI.new("html4") # add HTML generation methods
cgi.out do
cgi.html do
cgi.head do
cgi.title { "TITLE" }
end +
cgi.body do
cgi.form("ACTION" => "uri") do
cgi.p do
cgi.textarea("get_text") +
cgi.br +
cgi.submit
end
end +
cgi.pre do
CGI::escapeHTML(
"params: #{cgi.params.inspect}\n" +
"cookies: #{cgi.cookies.inspect}\n" +
ENV.collect do |key, value|
"#{key} --> #{value}\n"
end.join("")
)
end
end
end
end
# add HTML generation methods
CGI.new("html3") # html3.2
CGI.new("html4") # html4.01 (Strict)
CGI.new("html4Tr") # html4.01 Transitional
CGI.new("html4Fr") # html4.01 Frameset
CGI.new("html5") # html5
Some utility methods¶ ↑
require 'cgi/util'
CGI.escapeHTML('Usage: foo "bar" <baz>')
Some utility methods like a function¶ ↑
require 'cgi/util'
include CGI::Util
escapeHTML('Usage: foo "bar" <baz>')
h('Usage: foo "bar" <baz>') # alias
Class representing an HTTP cookie.
In addition to its specific fields and methods, a Cookie instance is a delegator to the array of its values.
See RFC 2965.
Examples of use¶ ↑
cookie1 = CGI::Cookie.new("name", "value1", "value2", ...)
cookie1 = CGI::Cookie.new("name" => "name", "value" => "value")
cookie1 = CGI::Cookie.new('name' => 'name',
'value' => ['value1', 'value2', ...],
'path' => 'path', # optional
'domain' => 'domain', # optional
'expires' => Time.now, # optional
'secure' => true, # optional
'httponly' => true # optional
)
cgi.out("cookie" => [cookie1, cookie2]) { "string" }
name = cookie1.name
values = cookie1.value
path = cookie1.path
domain = cookie1.domain
expires = cookie1.expires
secure = cookie1.secure
httponly = cookie1.httponly
cookie1.name = 'name'
cookie1.value = ['value1', 'value2', ...]
cookie1.path = 'path'
cookie1.domain = 'domain'
cookie1.expires = Time.now + 30
cookie1.secure = true
cookie1.httponly = true
Exception raised when there is an invalid encoding detected
Overview¶ ↑
This file provides the CGI::Session class, which provides session support for CGI scripts. A session is a sequence of HTTP requests and responses linked together and associated with a single client. Information associated with the session is stored on the server between requests. A session id is passed between client and server with every request and response, transparently to the user. This adds state information to the otherwise stateless HTTP request/response protocol.
Lifecycle¶ ↑
A CGI::Session instance is created from a CGI object. By default, this CGI::Session instance will start a new session if none currently exists, or continue the current session for this client if one does exist. The new_session option can be used to either always or never create a new session. See new() for more details.
delete() deletes a session from session storage. It does not however remove the session id from the client. If the client makes another request with the same id, the effect will be to start a new session with the old session's id.
Setting and retrieving session data.¶ ↑
The Session class associates data with a session as key-value pairs. This data can be set and retrieved by indexing the Session instance using '[]', much the same as hashes (although other hash methods are not supported).
When session processing has been completed for a request, the session should be closed using the close() method. This will store the session's state to persistent storage. If you want to store the session's state to persistent storage without finishing session processing for this request, call the update() method.
Storing session state¶ ↑
The caller can specify what form of storage to use for the session's data with the database_manager option to CGI::Session::new. The following storage classes are provided as part of the standard library:
CGI::Session::FileStore
stores data as plain text in a flat file. Only works with String data. This is the default storage type.
CGI::Session::MemoryStore
stores data in an in-memory hash. The data only persists for as long as the current Ruby interpreter instance does.
CGI::Session::PStore
stores data in Marshalled format. Provided by cgi/session/pstore.rb. Supports data of any type, and provides file-locking and transaction support.
Custom storage types can also be created by defining a class with the following methods:
new(session, options)
restore # returns hash of session data.
update
close
delete
Changing storage type mid-session does not work. Note in particular that by default the FileStore and PStore session data files have the same name. If your application switches from one to the other without making sure that filenames will be different and clients still have old sessions lying around in cookies, then things will break nastily!
Maintaining the session id.¶ ↑
Most session state is maintained on the server. However, a session id must be passed backwards and forwards between client and server to maintain a reference to this session state.
The simplest way to do this is via cookies. The CGI::Session class provides transparent support for session id communication via cookies if the client has cookies enabled.
If the client has cookies disabled, the session id must be included as a parameter of all requests sent by the client to the server. The CGI::Session class in conjunction with the CGI class will transparently add the session id as a hidden input field to all forms generated using the CGI#form() HTML generation method. No built-in support is provided for other mechanisms, such as URL re-writing. The caller is responsible for extracting the session id from the session_id attribute and manually encoding it in URLs and adding it as a hidden input to HTML forms created by other mechanisms. Also, session expiry is not automatically handled.
Examples of use¶ ↑
Setting the user's name¶ ↑
require 'cgi'
require 'cgi/session'
require 'cgi/session/pstore' # provides CGI::Session::PStore
cgi = CGI.new("html4")
session = CGI::Session.new(cgi,
'database_manager' => CGI::Session::PStore, # use PStore
'session_key' => '_rb_sess_id', # custom session key
'session_expires' => Time.now + 30 * 60, # 30 minute timeout
'prefix' => 'pstore_sid_') # PStore option
if cgi.has_key?('user_name') and cgi['user_name'] != ''
# coerce to String: cgi[] returns the
# string-like CGI::QueryExtension::Value
session['user_name'] = cgi['user_name'].to_s
elsif !session['user_name']
session['user_name'] = "guest"
end
session.close
Creating a new session safely¶ ↑
require 'cgi'
require 'cgi/session'
cgi = CGI.new("html4")
# We make sure to delete an old session if one exists,
# not just to free resources, but to prevent the session
# from being maliciously hijacked later on.
begin
session = CGI::Session.new(cgi, 'new_session' => false)
session.delete
rescue ArgumentError # if no old session
end
session = CGI::Session.new(cgi, 'new_session' => true)
session.close
File-based session storage class.
Implements session storage as a flat file of 'key=value' values. This storage type only works directly with String values; the user is responsible for converting other types to Strings when storing and from Strings when retrieving.
In-memory session storage class.
Implements session storage as a global in-memory hash. Session data will only persist for as long as the Ruby interpreter instance does.
Dummy session storage class.
Implements session storage place holder. No actual storage will be done.
PStore-based session storage class.
This builds upon the top-level PStore class provided by the library file pstore.rb. Session data is marshalled and stored in a file. File locking and transaction services are provided.
This class provides a complete interface to CSV files and data. It offers tools to enable you to read and write to and from Strings or IO objects, as needed.
The most generic interface of the library is:
csv = CSV.new(string_or_io, **options)
# Reading: IO object should be open for read
csv.read # => array of rows
# or
csv.each do |row|
# ...
end
# or
row = csv.shift
# Writing: IO object should be open for write
csv << row
There are several specialized class methods for one-statement reading or writing, described in the Specialized Methods section.
If a String is passed into ::new, it is internally wrapped into a StringIO object.
options can be used for specifying the particular CSV flavor (column separators, row separators, value quoting and so on), and for data conversion, see Data Conversion section for the description of the latter.
Specialized Methods¶ ↑
Reading¶ ↑
# From a file: all at once
arr_of_rows = CSV.read("path/to/file.csv", **options)
# iterator-style:
CSV.foreach("path/to/file.csv", **options) do |row|
# ...
end
# From a string
arr_of_rows = CSV.parse("CSV,data,String", **options)
# or
CSV.parse("CSV,data,String", **options) do |row|
# ...
end
Writing¶ ↑
# To a file
CSV.open("path/to/file.csv", "wb") do |csv|
csv << ["row", "of", "CSV", "data"]
csv << ["another", "row"]
# ...
end
# To a String
csv_string = CSV.generate do |csv|
csv << ["row", "of", "CSV", "data"]
csv << ["another", "row"]
# ...
end
Shortcuts¶ ↑
# Core extensions for converting one line
csv_string = ["CSV", "data"].to_csv # to CSV
csv_array = "CSV,String".parse_csv # from CSV
# CSV() method
CSV { |csv_out| csv_out << %w{my data here} } # to $stdout
CSV(csv = "") { |csv_str| csv_str << %w{my data here} } # to a String
CSV($stderr) { |csv_err| csv_err << %w{my data here} } # to $stderr
CSV($stdin) { |csv_in| csv_in.each { |row| p row } } # from $stdin
Data Conversion¶ ↑
CSV with headers¶ ↑
CSV allows to specify column names of CSV file, whether they are in data, or provided separately. If headers specified, reading methods return an instance of CSV::Table, consisting of CSV::Row.
# Headers are part of data
data = CSV.parse(<<~ROWS, headers: true)
Name,Department,Salary
Bob,Engineering,1000
Jane,Sales,2000
John,Management,5000
ROWS
data.class #=> CSV::Table
data.first #=> #<CSV::Row "Name":"Bob" "Department":"Engineering" "Salary":"1000">
data.first.to_h #=> {"Name"=>"Bob", "Department"=>"Engineering", "Salary"=>"1000"}
# Headers provided by developer
data = CSV.parse('Bob,Engeneering,1000', headers: %i[name department salary])
data.first #=> #<CSV::Row name:"Bob" department:"Engineering" salary:"1000">
Typed data reading¶ ↑
CSV allows to provide a set of data converters e.g. transformations to try on input data. Converter could be a symbol from CSV::Converters constant's keys, or lambda.
# Without any converters:
CSV.parse('Bob,2018-03-01,100')
#=> [["Bob", "2018-03-01", "100"]]
# With built-in converters:
CSV.parse('Bob,2018-03-01,100', converters: %i[numeric date])
#=> [["Bob", #<Date: 2018-03-01>, 100]]
# With custom converters:
CSV.parse('Bob,2018-03-01,100', converters: [->(v) { Time.parse(v) rescue v }])
#=> [["Bob", 2018-03-01 00:00:00 +0200, "100"]]
CSV and Character Encodings (M17n or Multilingualization)¶ ↑
This new CSV parser is m17n savvy. The parser works in the Encoding of the IO or String object being read from or written to. Your data is never transcoded (unless you ask Ruby to transcode it for you) and will literally be parsed in the Encoding it is in. Thus CSV will return Arrays or Rows of Strings in the Encoding of your data. This is accomplished by transcoding the parser itself into your Encoding.
Some transcoding must take place, of course, to accomplish this multiencoding support. For example, :col_sep, :row_sep, and :quote_char must be transcoded to match your data. Hopefully this makes the entire process feel transparent, since CSV's defaults should just magically work for your data. However, you can set these values manually in the target Encoding to avoid the translation.
It's also important to note that while all of CSV's core parser is now Encoding agnostic, some features are not. For example, the built-in converters will try to transcode data to UTF-8 before making conversions. Again, you can provide custom converters that are aware of your Encodings to avoid this translation. It's just too hard for me to support native conversions in all of Ruby's Encodings.
Anyway, the practical side of this is simple: make sure IO and String objects passed into CSV have the proper Encoding set and everything should just work. CSV methods that allow you to open IO objects (CSV::foreach(), CSV::open(), CSV::read(), and CSV::readlines()) do allow you to specify the Encoding.
One minor exception comes when generating CSV into a String with an Encoding that is not ASCII compatible. There's no existing data for CSV to use to prepare itself and thus you will probably need to manually specify the desired Encoding for most of those cases. It will try to guess using the fields in a row of output though, when using CSV::generate_line() or Array#to_csv().
I try to point out any other Encoding issues in the documentation of methods as they come up.
This has been tested to the best of my ability with all non-“dummy” Encodings Ruby ships with. However, it is brave new code and may have some bugs. Please feel free to report any issues you find with it.
The error thrown when the parser encounters illegal CSV formatting.
A CSV::Row is part Array and part Hash. It retains an order for the fields and allows duplicates just as an Array would, but also allows you to access fields by name just as you could if they were in a Hash.
All rows returned by CSV will be constructed from this class, if header row processing is activated.
A CSV::Table is a two-dimensional data structure for representing CSV documents. Tables allow you to work with the data by row or column, manipulate the data, and even convert the results back to CSV, if needed.
All tables returned by CSV will be constructed from this class, if header row processing is activated.
Extends any Class to include json_creatable? method.
Classes in Ruby are first-class objects—each is an instance of class Class.
Typically, you create a new class by using:
class Name
# some code describing the class behavior
end
When a new class is created, an object of type Class is initialized and assigned to a global constant (Name in this case).
When Name.new is called to create a new object, the new method in Class is run by default. This can be demonstrated by overriding new in Class:
class Class
alias old_new new
def new(*args)
print "Creating a new ", self.name, "\n"
old_new(*args)
end
end
class Name
end
n = Name.new
produces:
Creating a new Name
Classes, modules, and objects are interrelated. In the diagram that follows, the vertical arrows represent inheritance, and the parentheses metaclasses. All metaclasses are instances of the class `Class'.
+---------+ +-...
| | |
BasicObject-----|-->(BasicObject)-------|-...
^ | ^ |
| | | |
Object---------|----->(Object)---------|-...
^ | ^ |
| | | |
+-------+ | +--------+ |
| | | | | |
| Module-|---------|--->(Module)-|-...
| ^ | | ^ |
| | | | | |
| Class-|---------|---->(Class)-|-...
| ^ | | ^ |
| +---+ | +----+
| |
obj--->OtherClass---------->(OtherClass)-----------...
The exception class which will be raised when pushing into a closed Queue. See Queue#close and SizedQueue#close.
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)
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:
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
}
}
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
Introduction¶ ↑
The DBM class provides a wrapper to a Unix-style dbm or Database Manager library.
Dbm databases do not have tables or columns; they are simple key-value data stores, like a Ruby Hash except not resident in RAM. Keys and values must be strings.
The exact library used depends on how Ruby was compiled. It could be any of the following:
The original ndbm library is released in 4.3BSD. It is based on dbm library in Unix Version 7 but has different API to support multiple databases in a process.
Berkeley DB versions 1 thru 6, also known as BDB and Sleepycat DB, now owned by Oracle Corporation.
Berkeley DB 1.x, still found in 4.4BSD derivatives (FreeBSD, OpenBSD, etc).
gdbm, the GNU implementation of dbm.
qdbm, another open source reimplementation of dbm.
All of these dbm implementations have their own Ruby interfaces available, which provide richer (but varying) APIs.
Cautions¶ ↑
Before you decide to use DBM, there are some issues you should consider:
Each implementation of dbm has its own file format. Generally, dbm libraries will not read each other's files. This makes dbm files a bad choice for data exchange.
Even running the same OS and the same dbm implementation, the database file format may depend on the CPU architecture. For example, files may not be portable between PowerPC and 386, or between 32 and 64 bit Linux.
Different versions of Berkeley DB use different file formats. A change to the OS may therefore break DBM access to existing files.
Data size limits vary between implementations. Original Berkeley DB was limited to 2GB of data. Dbm libraries also sometimes limit the total size of a key/value pair, and the total size of all the keys that hash to the same value. These limits can be as little as 512 bytes. That said, gdbm and recent versions of Berkeley DB do away with these limits.
Given the above cautions, DBM is not a good choice for long term storage of important data. It is probably best used as a fast and easy alternative to a Hash for processing large amounts of data.
Example¶ ↑
require 'dbm'
db = DBM.open('rfcs', 0666, DBM::WRCREAT)
db['822'] = 'Standard for the Format of ARPA Internet Text Messages'
db['1123'] = 'Requirements for Internet Hosts - Application and Support'
db['3068'] = 'An Anycast Prefix for 6to4 Relay Routers'
puts db['822']
Exception class used to return errors from the dbm library.
This library provides debugging functionality to Ruby.
To add a debugger to your code, start by requiring debug in your program:
def say(word)
require 'debug'
puts word
end
This will cause Ruby to interrupt execution and show a prompt when the say method is run.
Once you're inside the prompt, you can start debugging your program.
(rdb:1) p word
"hello"
Getting help¶ ↑
You can get help at any time by pressing h.
(rdb:1) h
Debugger help v.-0.002b
Commands
b[reak] [file:|class:]<line|method>
b[reak] [class.]<line|method>
set breakpoint to some position
wat[ch] <expression> set watchpoint to some expression
cat[ch] (<exception>|off) set catchpoint to an exception
b[reak] list breakpoints
cat[ch] show catchpoint
del[ete][ nnn] delete some or all breakpoints
disp[lay] <expression> add expression into display expression list
undisp[lay][ nnn] delete one particular or all display expressions
c[ont] run until program ends or hit breakpoint
s[tep][ nnn] step (into methods) one line or till line nnn
n[ext][ nnn] go over one line or till line nnn
w[here] display frames
f[rame] alias for where
l[ist][ (-|nn-mm)] list program, - lists backwards
nn-mm lists given lines
up[ nn] move to higher frame
down[ nn] move to lower frame
fin[ish] return to outer frame
tr[ace] (on|off) set trace mode of current thread
tr[ace] (on|off) all set trace mode of all threads
q[uit] exit from debugger
v[ar] g[lobal] show global variables
v[ar] l[ocal] show local variables
v[ar] i[nstance] <object> show instance variables of object
v[ar] c[onst] <object> show constants of object
m[ethod] i[nstance] <obj> show methods of object
m[ethod] <class|module> show instance methods of class or module
th[read] l[ist] list all threads
th[read] c[ur[rent]] show current thread
th[read] [sw[itch]] <nnn> switch thread context to nnn
th[read] stop <nnn> stop thread nnn
th[read] resume <nnn> resume thread nnn
p expression evaluate expression and print its value
h[elp] print this help
<everything else> evaluate
Usage¶ ↑
The following is a list of common functionalities that the debugger provides.
Navigating through your code¶ ↑
In general, a debugger is used to find bugs in your program, which often means pausing execution and inspecting variables at some point in time.
Let's look at an example:
def my_method(foo)
require 'debug'
foo = get_foo if foo.nil?
raise if foo.nil?
end
When you run this program, the debugger will kick in just before the foo assignment.
(rdb:1) p foo
nil
In this example, it'd be interesting to move to the next line and inspect the value of foo again. You can do that by pressing n:
(rdb:1) n # goes to next line
(rdb:1) p foo
nil
You now know that the original value of foo was nil, and that it still was nil after calling get_foo.
Other useful commands for navigating through your code are:
c
Runs the program until it either exists or encounters another breakpoint. You usually press c when you are finished debugging your program and want to resume its execution.
s
Steps into method definition. In the previous example, s would take you inside the method definition of get_foo.
r
Restart the program.
q
Quit the program.
Inspecting variables¶ ↑
You can use the debugger to easily inspect both local and global variables. We've seen how to inspect local variables before:
(rdb:1) p my_arg
42
You can also pretty print the result of variables or expressions:
(rdb:1) pp %w{a very long long array containing many words}
["a",
"very",
"long",
...
]
You can list all local variables with +v l+:
(rdb:1) v l
foo => "hello"
Similarly, you can show all global variables with +v g+:
(rdb:1) v g
all global variables
Finally, you can omit p if you simply want to evaluate a variable or expression
(rdb:1) 5**2
25
Going beyond basics¶ ↑
Ruby Debug provides more advanced functionalities like switching between threads, setting breakpoints and watch expressions, and more. The full list of commands is available at any time by pressing h.
Staying out of trouble¶ ↑
Make sure you remove every instance of +require 'debug'+ before shipping your code. Failing to do so may result in your program hanging unpredictably.
Debug is not available in safe mode.
An Array wrapper that can be sent to another server via DRb.
All entries in the array will be dumped or be references that point to the local server.
Error raised by a dRuby protocol when it doesn't support the scheme specified in a URI. See DRb::DRbProtocol.
Error raised by the DRbProtocol module when it cannot find any protocol implementation support the scheme specified in a URI.
Class handling the connection between a DRbObject and the server the real object lives on.
This class maintains a pool of connections, to reduce the overhead of starting and closing down connections for each method call.
This class is used internally by DRbObject. The user does not normally need to deal with it directly.
Error raised when an error occurs on the underlying communication protocol.
Superclass of all errors raised in the DRb module.
Class responsible for converting between an object and its id.
This, the default implementation, uses an object's local ObjectSpace __id__ as its id. This means that an object's identification over drb remains valid only while that object instance remains alive within the server runtime.
For alternative mechanisms, see DRb::TimerIdConv in drb/timeridconv.rb and DRbNameIdConv in sample/name.rb in the full drb distribution.
Class responsible for converting between an object and its id.
This, the default implementation, uses an object's local ObjectSpace __id__ as its id. This means that an object's identification over drb remains valid only while that object instance remains alive within the server runtime.
For alternative mechanisms, see DRb::TimerIdConv in drb/timeridconv.rb and DRbNameIdConv in sample/name.rb in the full drb distribution.
Handler for sending and receiving drb messages.
This takes care of the low-level marshalling and unmarshalling of drb requests and responses sent over the wire between server and client. This relieves the implementor of a new drb protocol layer with having to deal with these details.
The user does not have to directly deal with this object in normal use.
Object wrapping a reference to a remote drb object.
Method calls on this object are relayed to the remote object that this object is a stub for.
Object wrapping a reference to a remote drb object.
Method calls on this object are relayed to the remote object that this object is a stub for.
An exception wrapping an error object
The protocol for DRb over an SSL socket
The URI for a DRb socket over SSL is: drbssl://<host>:<port>?<option>. The option is optional
SSLConfig handles the needed SSL information for establishing a DRbSSLSocket connection, including generating the X509 / RSA pair.
An instance of this config can be passed to DRbSSLSocket.new, DRbSSLSocket.open and DRbSSLSocket.open_server
See DRb::DRbSSLSocket::SSLConfig.new for more details
Error raised by the DRb module when an attempt is made to refer to the context's current drb server but the context does not have one. See current_server.
The default drb protocol which communicates over a TCP socket.
The DRb TCP protocol URI looks like: druby://<host>:<port>?<option>. The option is optional.
Implements DRb over a UNIX socket
DRb UNIX socket URIs look like drbunix:<path>?<option>. The option is optional.
Class wrapping a marshalled object whose type is unknown locally.
If an object is returned by a method invoked over drb, but the class of the object is unknown in the client namespace, or the object is a constant unknown in the client namespace, then the still-marshalled object is returned wrapped in a DRbUnknown instance.
If this object is passed as an argument to a method invoked over drb, then the wrapped object is passed instead.
The class or constant name of the object can be read from the name attribute. The marshalled object is held in the buf attribute.
An exception wrapping a DRb::DRbUnknown object
The GW provides a synchronized store for participants in the gateway to communicate.
Gateway id conversion forms a gateway between different DRb protocols or networks.
The gateway needs to install this id conversion and create servers for each of the protocols or networks it will be a gateway between. It then needs to create a server that attaches to each of these networks. For example:
require 'drb/drb'
require 'drb/unix'
require 'drb/gw'
DRb.install_id_conv DRb::GWIdConv.new
gw = DRb::GW.new
s1 = DRb::DRbServer.new 'drbunix:/path/to/gateway', gw
s2 = DRb::DRbServer.new 'druby://example:10000', gw
s1.thread.join
s2.thread.join
Each client must register services with the gateway, for example:
DRb.start_service 'drbunix:', nil # an anonymous server
gw = DRbObject.new nil, 'drbunix:/path/to/gateway'
gw[:unix] = some_service
DRb.thread.join
Timer id conversion keeps objects alive for a certain amount of time after their last access. The default time period is 600 seconds and can be changed upon initialization.
To use TimerIdConv:
DRb.install_id_conv TimerIdConv.new 60 # one minute
This is a deprecated class, base class for C extensions using Data_Make_Struct or Data_Wrap_Struct.
date and datetime class - Tadayoshi Funaba 1998-2011
'date' provides two classes: Date and DateTime.
Terms and Definitions¶ ↑
Some terms and definitions are based on ISO 8601 and JIS X 0301.
Calendar Date¶ ↑
The calendar date is a particular day of a calendar year, identified by its ordinal number within a calendar month within that year.
In those classes, this is so-called “civil”.
Ordinal Date¶ ↑
The ordinal date is a particular day of a calendar year identified by its ordinal number within the year.
In those classes, this is so-called “ordinal”.
Week Date¶ ↑
The week date is a date identified by calendar week and day numbers.
The calendar week is a seven day period within a calendar year, starting on a Monday and identified by its ordinal number within the year; the first calendar week of the year is the one that includes the first Thursday of that year. In the Gregorian calendar, this is equivalent to the week which includes January 4.
In those classes, this is so-called “commercial”.
Julian Day Number¶ ↑
The Julian day number is in elapsed days since noon (Greenwich Mean Time) on January 1, 4713 BCE (in the Julian calendar).
In this document, the astronomical Julian day number is the same as the original Julian day number. And the chronological Julian day number is a variation of the Julian day number. Its days begin at midnight on local time.
In this document, when the term “Julian day number” simply appears, it just refers to “chronological Julian day number”, not the original.
In those classes, those are so-called “ajd” and “jd”.
Modified Julian Day Number¶ ↑
The modified Julian day number is in elapsed days since midnight (Coordinated Universal Time) on November 17, 1858 CE (in the Gregorian calendar).
In this document, the astronomical modified Julian day number is the same as the original modified Julian day number. And the chronological modified Julian day number is a variation of the modified Julian day number. Its days begin at midnight on local time.
In this document, when the term “modified Julian day number” simply appears, it just refers to “chronological modified Julian day number”, not the original.
In those classes, those are so-called “amjd” and “mjd”.
Date¶ ↑
A subclass of Object that includes the Comparable module and easily handles date.
A Date object is created with Date::new, Date::jd, Date::ordinal, Date::commercial, Date::parse, Date::strptime, Date::today, Time#to_date, etc.
require 'date'
Date.new(2001,2,3)
#=> #<Date: 2001-02-03 ...>
Date.jd(2451944)
#=> #<Date: 2001-02-03 ...>
Date.ordinal(2001,34)
#=> #<Date: 2001-02-03 ...>
Date.commercial(2001,5,6)
#=> #<Date: 2001-02-03 ...>
Date.parse('2001-02-03')
#=> #<Date: 2001-02-03 ...>
Date.strptime('03-02-2001', '%d-%m-%Y')
#=> #<Date: 2001-02-03 ...>
Time.new(2001,2,3).to_date
#=> #<Date: 2001-02-03 ...>
All date objects are immutable; hence cannot modify themselves.
The concept of a date object can be represented as a tuple of the day count, the offset and the day of calendar reform.
The day count denotes the absolute position of a temporal dimension. The offset is relative adjustment, which determines decoded local time with the day count. The day of calendar reform denotes the start day of the new style. The old style of the West is the Julian calendar which was adopted by Caesar. The new style is the Gregorian calendar, which is the current civil calendar of many countries.
The day count is virtually the astronomical Julian day number. The offset in this class is usually zero, and cannot be specified directly.
A Date object can be created with an optional argument, the day of calendar reform as a Julian day number, which should be 2298874 to 2426355 or negative/positive infinity. The default value is Date::ITALY (2299161=1582-10-15). See also sample/cal.rb.
$ ruby sample/cal.rb -c it 10 1582
October 1582
S M Tu W Th F S
1 2 3 4 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
$ ruby sample/cal.rb -c gb 9 1752
September 1752
S M Tu W Th F S
1 2 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
A Date object has various methods. See each reference.
d = Date.parse('3rd Feb 2001')
#=> #<Date: 2001-02-03 ...>
d.year #=> 2001
d.mon #=> 2
d.mday #=> 3
d.wday #=> 6
d += 1 #=> #<Date: 2001-02-04 ...>
d.strftime('%a %d %b %Y') #=> "Sun 04 Feb 2001"
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
When should you use 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.
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
Notes¶ ↑
Be advised, RDoc will not detect delegated methods.
This abstract class provides a common interface to message digest implementation classes written in C.
Write a Digest subclass in C¶ ↑
Digest::Base provides a common interface to message digest classes written in C. These classes must provide a struct of type rb_digest_metadata_t:
typedef int (*rb_digest_hash_init_func_t)(void *);
typedef void (*rb_digest_hash_update_func_t)(void *, unsigned char *, size_t);
typedef int (*rb_digest_hash_finish_func_t)(void *, unsigned char *);
typedef struct {
int api_version;
size_t digest_len;
size_t block_len;
size_t ctx_size;
rb_digest_hash_init_func_t init_func;
rb_digest_hash_update_func_t update_func;
rb_digest_hash_finish_func_t finish_func;
} rb_digest_metadata_t;
This structure must be set as an instance variable named metadata (without the +@+ in front of the name). By example:
static const rb_digest_metadata_t sha1 = {
RUBY_DIGEST_API_VERSION,
SHA1_DIGEST_LENGTH,
SHA1_BLOCK_LENGTH,
sizeof(SHA1_CTX),
(rb_digest_hash_init_func_t)SHA1_Init,
(rb_digest_hash_update_func_t)SHA1_Update,
(rb_digest_hash_finish_func_t)SHA1_Finish,
};
rb_ivar_set(cDigest_SHA1, rb_intern("metadata"),
Data_Wrap_Struct(0, 0, 0, (void *)&sha1));
This module stands as a base class for digest implementation classes.
A class for calculating message digests using the MD5 Message-Digest Algorithm by RSA Data Security, Inc., described in RFC1321.
MD5 calculates a digest of 128 bits (16 bytes).
Examples¶ ↑
require 'digest'
# Compute a complete digest
Digest::MD5.hexdigest 'abc' #=> "90015098..."
# Compute digest by chunks
md5 = Digest::MD5.new # =>#<Digest::MD5>
md5.update "ab"
md5 << "c" # alias for #update
md5.hexdigest # => "90015098..."
# Use the same object to compute another digest
md5.reset
md5 << "message"
md5.hexdigest # => "78e73102..."
A class for calculating message digests using RIPEMD-160 cryptographic hash function, designed by Hans Dobbertin, Antoon Bosselaers, and Bart Preneel.
RMD160 calculates a digest of 160 bits (20 bytes).
Examples¶ ↑
require 'digest'
# Compute a complete digest
Digest::RMD160.hexdigest 'abc' #=> "8eb208f7..."
# Compute digest by chunks
rmd160 = Digest::RMD160.new # =>#<Digest::RMD160>
rmd160.update "ab"
rmd160 << "c" # alias for #update
rmd160.hexdigest # => "8eb208f7..."
# Use the same object to compute another digest
rmd160.reset
rmd160 << "message"
rmd160.hexdigest # => "1dddbe1b..."
A class for calculating message digests using the SHA-1 Secure Hash Algorithm by NIST (the US' National Institute of Standards and Technology), described in FIPS PUB 180-1.
See Digest::Instance for digest API.
SHA-1 calculates a digest of 160 bits (20 bytes).
Examples¶ ↑
require 'digest'
# Compute a complete digest
Digest::SHA1.hexdigest 'abc' #=> "a9993e36..."
# Compute digest by chunks
sha1 = Digest::SHA1.new # =>#<Digest::SHA1>
sha1.update "ab"
sha1 << "c" # alias for #update
sha1.hexdigest # => "a9993e36..."
# Use the same object to compute another digest
sha1.reset
sha1 << "message"
sha1.hexdigest # => "6f9b9af3..."
Objects of class Dir are directory streams representing directories in the underlying file system. They provide a variety of ways to list directories and their contents. See also File.
The directory used in these examples contains the two regular files (config.h and main.rb), the parent directory (..), and the directory itself (.).
ENV is a hash-like accessor for environment variables.
Raised by some IO operations when reaching the end of file. Many IO methods exist in two forms,
one that returns nil when the end of file is reached, the other raises EOFError.
EOFError is a subclass of IOError.
file = File.open("/etc/hosts")
file.read
file.gets #=> nil
file.readline #=> EOFError: end of file reached
ERB – Ruby Templating¶ ↑
Introduction¶ ↑
ERB provides an easy to use but powerful templating system for Ruby. Using ERB, actual Ruby code can be added to any plain text document for the purposes of generating document information details and/or flow control.
A very simple example is this:
require 'erb'
x = 42
template = ERB.new <<-EOF
The value of x is: <%= x %>
EOF
puts template.result(binding)
Prints: The value of x is: 42
More complex examples are given below.
Recognized Tags¶ ↑
ERB recognizes certain tags in the provided template and converts them based on the rules below:
<% Ruby code -- inline with output %>
<%= Ruby expression -- replace with result %>
<%# comment -- ignored -- useful in testing %>
% a line of Ruby code -- treated as <% line %> (optional -- see ERB.new)
%% replaced with % if first thing on a line and % processing is used
<%% or %%> -- replace with <% or %> respectively
All other text is passed through ERB filtering unchanged.
Options¶ ↑
There are several settings you can change when you use ERB:
the nature of the tags that are recognized;
the value of $SAFE under which the template is run;
the binding used to resolve local variables in the template.
See the ERB.new and ERB#result methods for more detail.
Character encodings¶ ↑
ERB (or Ruby code generated by ERB) returns a string in the same character encoding as the input string. When the input string has a magic comment, however, it returns a string in the encoding specified by the magic comment.
# -*- coding: utf-8 -*-
require 'erb'
template = ERB.new <<EOF
<%#-*- coding: Big5 -*-%>
\_\_ENCODING\_\_ is <%= \_\_ENCODING\_\_ %>.
EOF
puts template.result
Prints: _ENCODING_ is Big5.
Examples¶ ↑
Plain Text¶ ↑
ERB is useful for any generic templating situation. Note that in this example, we use the convenient “% at start of line” tag, and we quote the template literally with %q{...} to avoid trouble with the backslash.
require "erb"
# Create template.
template = %q{
From: James Edward Gray II <[email protected]>
To: <%= to %>
Subject: Addressing Needs
<%= to[/\w+/] %>:
Just wanted to send a quick note assuring that your needs are being
addressed.
I want you to know that my team will keep working on the issues,
especially:
<%# ignore numerous minor requests -- focus on priorities %>
% priorities.each do |priority|
* <%= priority %>
% end
Thanks for your patience.
James Edward Gray II
}.gsub(/^ /, '')
message = ERB.new(template, trim_mode: "%<>")
# Set up template data.
to = "Community Spokesman <spokesman@ruby_community.org>"
priorities = [ "Run Ruby Quiz",
"Document Modules",
"Answer Questions on Ruby Talk" ]
# Produce result.
email = message.result
puts email
Generates:
From: James Edward Gray II <[email protected]>
To: Community Spokesman <spokesman@ruby_community.org>
Subject: Addressing Needs
Community:
Just wanted to send a quick note assuring that your needs are being addressed.
I want you to know that my team will keep working on the issues, especially:
* Run Ruby Quiz
* Document Modules
* Answer Questions on Ruby Talk
Thanks for your patience.
James Edward Gray II
Ruby in HTML¶ ↑
ERB is often used in .rhtml files (HTML with embedded Ruby). Notice the need in this example to provide a special binding when the template is run, so that the instance variables in the Product object can be resolved.
require "erb"
# Build template data class.
class Product
def initialize( code, name, desc, cost )
@code = code
@name = name
@desc = desc
@cost = cost
@features = [ ]
end
def add_feature( feature )
@features << feature
end
# Support templating of member data.
def get_binding
binding
end
# ...
end
# Create template.
template = %{
<html>
<head><title>Ruby Toys -- <%= @name %></title></head>
<body>
<h1><%= @name %> (<%= @code %>)</h1>
<p><%= @desc %></p>
<ul>
<% @features.each do |f| %>
<li><b><%= f %></b></li>
<% end %>
</ul>
<p>
<% if @cost < 10 %>
<b>Only <%= @cost %>!!!</b>
<% else %>
Call for a price, today!
<% end %>
</p>
</body>
</html>
}.gsub(/^ /, '')
rhtml = ERB.new(template)
# Set up template data.
toy = Product.new( "TZ-1002",
"Rubysapien",
"Geek's Best Friend! Responds to Ruby commands...",
999.95 )
toy.add_feature("Listens for verbal commands in the Ruby language!")
toy.add_feature("Ignores Perl, Java, and all C variants.")
toy.add_feature("Karate-Chop Action!!!")
toy.add_feature("Matz signature on left leg.")
toy.add_feature("Gem studded eyes... Rubies, of course!")
# Produce result.
rhtml.run(toy.get_binding)
Generates (some blank lines removed):
<html>
<head><title>Ruby Toys -- Rubysapien</title></head>
<body>
<h1>Rubysapien (TZ-1002)</h1>
<p>Geek's Best Friend! Responds to Ruby commands...</p>
<ul>
<li><b>Listens for verbal commands in the Ruby language!</b></li>
<li><b>Ignores Perl, Java, and all C variants.</b></li>
<li><b>Karate-Chop Action!!!</b></li>
<li><b>Matz signature on left leg.</b></li>
<li><b>Gem studded eyes... Rubies, of course!</b></li>
</ul>
<p>
Call for a price, today!
</p>
</body>
</html>
Notes¶ ↑
There are a variety of templating solutions available in various Ruby projects:
ERB's big brother, eRuby, works the same but is written in C for speed;
Amrita (smart at producing HTML/XML);
cs/Template (written in C for speed);
RDoc, distributed with Ruby, uses its own template engine, which can be reused elsewhere;
and others; search RubyGems.org or The Ruby Toolbox.
Rails, the web application framework, uses ERB to create views.
An Encoding instance represents a character encoding usable in Ruby. It is defined as a constant under the Encoding namespace. It has a name and optionally, aliases:
Encoding::ISO_8859_1.name
#=> "ISO-8859-1"
Encoding::ISO_8859_1.names
#=> ["ISO-8859-1", "ISO8859-1"]
Ruby methods dealing with encodings return or accept Encoding instances as arguments (when a method accepts an Encoding instance as an argument, it can be passed an Encoding name or alias instead).
"some string".encoding
#=> #<Encoding:UTF-8>
string = "some string".encode(Encoding::ISO_8859_1)
#=> "some string"
string.encoding
#=> #<Encoding:ISO-8859-1>
"some string".encode "ISO-8859-1"
#=> "some string"
Encoding::ASCII_8BIT is a special encoding that is usually used for a byte string, not a character string. But as the name insists, its characters in the range of ASCII are considered as ASCII characters. This is useful when you use ASCII-8BIT characters with other ASCII compatible characters.
Changing an encoding¶ ↑
The associated Encoding of a String can be changed in two different ways.
First, it is possible to set the Encoding of a string to a new Encoding without changing the internal byte representation of the string, with String#force_encoding. This is how you can tell Ruby the correct encoding of a string.
string
#=> "R\xC3\xA9sum\xC3\xA9"
string.encoding
#=> #<Encoding:ISO-8859-1>
string.force_encoding(Encoding::UTF_8)
#=> "R\u00E9sum\u00E9"
Second, it is possible to transcode a string, i.e. translate its internal byte representation to another encoding. Its associated encoding is also set to the other encoding. See String#encode for the various forms of transcoding, and the Encoding::Converter class for additional control over the transcoding process.
string
#=> "R\u00E9sum\u00E9"
string.encoding
#=> #<Encoding:UTF-8>
string = string.encode!(Encoding::ISO_8859_1)
#=> "R\xE9sum\xE9"
string.encoding
#=> #<Encoding::ISO-8859-1>
Script encoding¶ ↑
All Ruby script code has an associated Encoding which any String literal created in the source code will be associated to.
The default script encoding is Encoding::UTF-8 after v2.0, but it can be changed by a magic comment on the first line of the source code file (or second line, if there is a shebang line on the first). The comment must contain the word coding or encoding, followed by a colon, space and the Encoding name or alias:
# encoding: UTF-8
"some string".encoding
#=> #<Encoding:UTF-8>
The __ENCODING__ keyword returns the script encoding of the file which the keyword is written:
# encoding: ISO-8859-1
__ENCODING__
#=> #<Encoding:ISO-8859-1>
ruby -K will change the default locale encoding, but this is not recommended. Ruby source files should declare its script encoding by a magic comment even when they only depend on US-ASCII strings or regular expressions.
Locale encoding¶ ↑
The default encoding of the environment. Usually derived from locale.
see Encoding.locale_charmap, Encoding.find('locale')
Filesystem encoding¶ ↑
The default encoding of strings from the filesystem of the environment. This is used for strings of file names or paths.
see Encoding.find('filesystem')
External encoding¶ ↑
Each IO object has an external encoding which indicates the encoding that Ruby will use to read its data. By default Ruby sets the external encoding of an IO object to the default external encoding. The default external encoding is set by locale encoding or the interpreter -E option. Encoding.default_external returns the current value of the external encoding.
ENV["LANG"]
#=> "UTF-8"
Encoding.default_external
#=> #<Encoding:UTF-8>
$ ruby -E ISO-8859-1 -e "p Encoding.default_external"
#<Encoding:ISO-8859-1>
$ LANG=C ruby -e 'p Encoding.default_external'
#<Encoding:US-ASCII>
The default external encoding may also be set through Encoding.default_external=, but you should not do this as strings created before and after the change will have inconsistent encodings. Instead use ruby -E to invoke ruby with the correct external encoding.
When you know that the actual encoding of the data of an IO object is not the default external encoding, you can reset its external encoding with IO#set_encoding or set it at IO object creation (see IO.new options).
Internal encoding¶ ↑
To process the data of an IO object which has an encoding different from its external encoding, you can set its internal encoding. Ruby will use this internal encoding to transcode the data when it is read from the IO object.
Conversely, when data is written to the IO object it is transcoded from the internal encoding to the external encoding of the IO object.
The internal encoding of an IO object can be set with IO#set_encoding or at IO object creation (see IO.new options).
The internal encoding is optional and when not set, the Ruby default internal encoding is used. If not explicitly set this default internal encoding is nil meaning that by default, no transcoding occurs.
The default internal encoding can be set with the interpreter option -E. Encoding.default_internal returns the current internal encoding.
$ ruby -e 'p Encoding.default_internal'
nil
$ ruby -E ISO-8859-1:UTF-8 -e "p [Encoding.default_external, \
Encoding.default_internal]"
[#<Encoding:ISO-8859-1>, #<Encoding:UTF-8>]
The default internal encoding may also be set through Encoding.default_internal=, but you should not do this as strings created before and after the change will have inconsistent encodings. Instead use ruby -E to invoke ruby with the correct internal encoding.
IO encoding example¶ ↑
In the following example a UTF-8 encoded string “Ru00E9sumu00E9” is transcoded for output to ISO-8859-1 encoding, then read back in and transcoded to UTF-8:
string = "R\u00E9sum\u00E9"
open("transcoded.txt", "w:ISO-8859-1") do |io|
io.write(string)
end
puts "raw text:"
p File.binread("transcoded.txt")
puts
open("transcoded.txt", "r:ISO-8859-1:UTF-8") do |io|
puts "transcoded text:"
p io.read
end
While writing the file, the internal encoding is not specified as it is only necessary for reading. While reading the file both the internal and external encoding must be specified to obtain the correct result.
$ ruby t.rb
raw text:
"R\xE9sum\xE9"
transcoded text:
"R\u00E9sum\u00E9"
Raised by Encoding and String methods when the source encoding is incompatible with the target encoding.
Encoding conversion class.
Raised by transcoding methods when a named encoding does not correspond with a known converter.
Raised by Encoding and String methods when the string being transcoded contains a byte invalid for the either the source or target encoding.
Raised by Encoding and String methods when a transcoding operation fails.
EncodingError is the base class for encoding errors.
A class which allows both internal and external iteration.
An Enumerator can be created by the following methods.
Kernel#to_enum
Kernel#enum_for
Enumerator.new
Most methods have two forms: a block form where the contents are evaluated for each item in the enumeration, and a non-block form which returns a new Enumerator wrapping the iteration.
enumerator = %w(one two three).each
puts enumerator.class # => Enumerator
enumerator.each_with_object("foo") do |item, obj|
puts "#{obj}: #{item}"
end
# foo: one
# foo: two
# foo: three
enum_with_obj = enumerator.each_with_object("foo")
puts enum_with_obj.class # => Enumerator
enum_with_obj.each do |item, obj|
puts "#{obj}: #{item}"
end
# foo: one
# foo: two
# foo: three
This allows you to chain Enumerators together. For example, you can map a list's elements to strings containing the index and the element as a string via:
puts %w[foo bar baz].map.with_index { |w, i| "#{i}:#{w}" }
# => ["0:foo", "1:bar", "2:baz"]
An Enumerator can also be used as an external iterator. For example, Enumerator#next returns the next value of the iterator or raises StopIteration if the Enumerator is at the end.
e = [1,2,3].each # returns an enumerator object.
puts e.next # => 1
puts e.next # => 2
puts e.next # => 3
puts e.next # raises StopIteration
You can use this to implement an internal iterator as follows:
def ext_each(e)
while true
begin
vs = e.next_values
rescue StopIteration
return $!.result
end
y = yield(*vs)
e.feed y
end
end
o = Object.new
def o.each
puts yield
puts yield(1)
puts yield(1, 2)
3
end
# use o.each as an internal iterator directly.
puts o.each {|*x| puts x; [:b, *x] }
# => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3
# convert o.each to an external iterator for
# implementing an internal iterator.
puts ext_each(o.to_enum) {|*x| puts x; [:b, *x] }
# => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3
Enumerator::ArithmeticSequence is a subclass of Enumerator, that is a representation of sequences of numbers with common difference. Instances of this class can be generated by the Range#step and Numeric#step methods.
Enumerator::Chain is a subclass of Enumerator, which represents a chain of enumerables that works as a single enumerator.
This type of objects can be created by Enumerable#chain and Enumerator#+.
Generator
Lazy
Yielder
Client sent TCP reset (RST) before server has accepted the connection requested by client.
Remote host reset the connection request.
Protocol error.
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:
NoMemoryError
ScriptError
LoadError
NotImplementedError
SyntaxError
SecurityError
SignalException
Interrupt
StandardError – default for rescue
ArgumentError
UncaughtThrowError
EncodingError
FiberError
IOError
EOFError
IndexError
KeyError
StopIteration
LocalJumpError
NameError
NoMethodError
RangeError
FloatDomainError
RegexpError
RuntimeError – default for raise
FrozenError
SystemCallError
Errno::*
ThreadError
TypeError
ZeroDivisionError
SystemExit
SystemStackError
fatal – impossible to rescue
The global value false is the only instance of class FalseClass and represents a logically false value in boolean expressions. The class provides operators allowing false to participate correctly in logical expressions.
Fibers are primitives for implementing light weight cooperative concurrency in Ruby. Basically they are a means of creating code blocks that can be paused and resumed, much like threads. The main difference is that they are never preempted and that the scheduling must be done by the programmer and not the VM.
As opposed to other stackless light weight concurrency models, each fiber comes with a stack. This enables the fiber to be paused from deeply nested function calls within the fiber block. See the ruby(1) manpage to configure the size of the fiber stack(s).
When a fiber is created it will not run automatically. Rather it must be explicitly asked to run using the Fiber#resume method. The code running inside the fiber can give up control by calling Fiber.yield in which case it yields control back to caller (the caller of the Fiber#resume).
Upon yielding or termination the Fiber returns the value of the last executed expression
For instance:
fiber = Fiber.new do
Fiber.yield 1
2
end
puts fiber.resume
puts fiber.resume
puts fiber.resume
produces
1
2
FiberError: dead fiber called
The Fiber#resume method accepts an arbitrary number of parameters, if it is the first call to resume then they will be passed as block arguments. Otherwise they will be the return value of the call to Fiber.yield
Example:
fiber = Fiber.new do |first|
second = Fiber.yield first + 2
end
puts fiber.resume 10
puts fiber.resume 14
puts fiber.resume 18
produces
12
14
FiberError: dead fiber called
Raised when an invalid operation is attempted on a Fiber, in particular when attempting to call/resume a dead fiber, attempting to yield from the root fiber, or calling a fiber across threads.
fiber = Fiber.new{}
fiber.resume #=> nil
fiber.resume #=> FiberError: dead fiber called
C struct shell
A C struct wrapper
C union shell
A C union wrapper
Description¶ ↑
An FFI closure wrapper, for handling callbacks.
Example¶ ↑
closure = Class.new(Fiddle::Closure) {
def call
10
end
}.new(Fiddle::TYPE_INT, [])
#=> #<#<Class:0x0000000150d308>:0x0000000150d240>
func = Fiddle::Function.new(closure, [], Fiddle::TYPE_INT)
#=> #<Fiddle::Function:0x00000001516e58>
func.call
#=> 10
Extends Fiddle::Closure to allow for building the closure in a block
Used internally by Fiddle::Importer
standard dynamic load exception
Description¶ ↑
A representation of a C function
Examples¶ ↑
'strcpy'¶ ↑
@libc = Fiddle.dlopen "/lib/libc.so.6"
#=> #<Fiddle::Handle:0x00000001d7a8d8>
f = Fiddle::Function.new(
@libc['strcpy'],
[Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP],
Fiddle::TYPE_VOIDP)
#=> #<Fiddle::Function:0x00000001d8ee00>
buff = "000"
#=> "000"
str = f.call(buff, "123")
#=> #<Fiddle::Pointer:0x00000001d0c380 ptr=0x000000018a21b8 size=0 free=0x00000000000000>
str.to_s
=> "123"
ABI check¶ ↑
@libc = Fiddle.dlopen "/lib/libc.so.6"
#=> #<Fiddle::Handle:0x00000001d7a8d8>
f = Fiddle::Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP)
#=> #<Fiddle::Function:0x00000001d8ee00>
f.abi == Fiddle::Function::DEFAULT
#=> true
The Fiddle::Handle is the manner to access the dynamic library
Example¶ ↑
Setup¶ ↑
libc_so = "/lib64/libc.so.6"
=> "/lib64/libc.so.6"
@handle = Fiddle::Handle.new(libc_so)
=> #<Fiddle::Handle:0x00000000d69ef8>
Setup, with flags¶ ↑
libc_so = "/lib64/libc.so.6"
=> "/lib64/libc.so.6"
@handle = Fiddle::Handle.new(libc_so, Fiddle::RTLD_LAZY | Fiddle::RTLD_GLOBAL)
=> #<Fiddle::Handle:0x00000000d69ef8>
See RTLD_LAZY and RTLD_GLOBAL
Addresses to symbols¶ ↑
strcpy_addr = @handle['strcpy']
=> 140062278451968
or
strcpy_addr = @handle.sym('strcpy')
=> 140062278451968
Fiddle::Pointer is a class to handle C pointers
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.
Objects of class File::Stat encapsulate common status information for File objects. The information is recorded at the moment the File::Stat object is created; changes made to the file after that point will not be reflected. File::Stat objects are returned by IO#stat, File::stat, File#lstat, and File::lstat. Many of these methods return platform-specific values, and not all values are meaningful on all systems. See also Kernel#test.
Float objects represent inexact real numbers using the native architecture's double-precision floating point representation.
Floating point has a different arithmetic and is an inexact number. So you should know its esoteric system. See following:
docs.sun.com/source/806-3568/ncg_goldberg.html
wiki.github.com/rdp/ruby_tutorials_core/ruby-talk-faq#wiki-floats_imprecise
en.wikipedia.org/wiki/Floating_point#Accuracy_problems
Raised when attempting to convert special float values (in particular Infinity or NaN) to numerical classes which don't support them.
Float::INFINITY.to_r #=> FloatDomainError: Infinity
Raised when there is an attempt to modify a frozen object.
[1, 2, 3].freeze << 4
raises the exception:
FrozenError: can't modify frozen Array
Summary¶ ↑
Ruby extension for GNU dbm (gdbm) – a simple database engine for storing key-value pairs on disk.
Description¶ ↑
GNU dbm is a library for simple databases. A database is a file that stores key-value pairs. Gdbm allows the user to store, retrieve, and delete data by key. It furthermore allows a non-sorted traversal of all key-value pairs. A gdbm database thus provides the same functionality as a hash. As with objects of the Hash class, elements can be accessed with []. Furthermore, GDBM mixes in the Enumerable module, thus providing convenient methods such as find, collect, map, etc.
A process is allowed to open several different databases at the same time. A process can open a database as a “reader” or a “writer”. Whereas a reader has only read-access to the database, a writer has read- and write-access. A database can be accessed either by any number of readers or by exactly one writer at the same time.
Examples¶ ↑
Opening/creating a database, and filling it with some entries:
require 'gdbm'
gdbm = GDBM.new("fruitstore.db")
gdbm["ananas"] = "3"
gdbm["banana"] = "8"
gdbm["cranberry"] = "4909"
gdbm.close
Reading out a database:
require 'gdbm'
gdbm = GDBM.new("fruitstore.db")
gdbm.each_pair do |key, value|
print "#{key}: #{value}\n"
end
gdbm.close
produces
banana: 8
ananas: 3
cranberry: 4909
Links¶ ↑
www.gnu.org/software/gdbm/
BasicSpecification is an abstract class which implements some common code used by both Specification and StubSpecification.
Base class for all Gem commands. When creating a new gem command, define initialize, execute, arguments, defaults_str, description and usage (as appropriate). See the above mentioned methods for details.
A very good example to look at is Gem::Commands::ContentsCommand
The command manager registers and installs all the individual sub-commands supported by the gem command.
Extra commands can be provided by writing a rubygems_plugin.rb file in an installed gem. You should register your command against the Gem::CommandManager instance, like this:
# file rubygems_plugin.rb
require 'rubygems/command_manager'
Gem::CommandManager.instance.register_command :edit
You should put the implementation of your command in rubygems/commands.
# file rubygems/commands/edit_command.rb
class Gem::Commands::EditCommand < Gem::Command
# ...
end
See Gem::Command for instructions on writing gem commands.
Generates a index files for use as a gem server.
See `gem help generate_index`
Gem installer command line tool
See `gem help install`
An alternate to Gem::Commands::QueryCommand that searches for gems starting with the supplied argument.
Installs RubyGems itself. This command is ordinarily only available from a RubyGems checkout or tarball.
Gem uninstaller command line tool
See `gem help uninstall`
Gem::ConfigFile RubyGems options and gem command options from gemrc.
gemrc is a YAML file that uses strings to match gem command arguments and symbols to match RubyGems options.
Gem command arguments use a String key that matches the command name and allow you to specify default arguments:
install: --no-rdoc --no-ri
update: --no-rdoc --no-ri
You can use gem: to set default arguments for all commands.
RubyGems options use symbol keys. Valid options are:
:backtrace
See backtrace
:sources
Sets Gem::sources
:verbose
See verbose
:concurrent_downloads
See concurrent_downloads
gemrc files may exist in various locations and are read and merged in the following order:
system wide (/etc/gemrc)
per user (~/.gemrc)
per environment (gemrc files listed in the GEMRC environment variable)
Raised when there are conflicting gem specs loaded
Subclass of StreamUI that instantiates the user interaction using STDIN, STDOUT, and STDERR.
Installs a gem along with all its dependencies from local and remote gems.
Gem::DependencyList is used for installing and uninstalling gems in the correct order to avoid conflicts.
Raised by Gem::Resolver when a Gem::Dependency::Conflict reaches the toplevel. Indicates which dependencies were incompatible through conflict and conflicting_dependencies
Cleans up after a partially-failed uninstall or for an invalid Gem::Specification.
If a specification was removed by hand this will remove any remaining files.
If a corrupt specification was installed this will clean up warnings by removing the bogus specification.
Potentially raised when a specification is validated.
Base exception class for RubyGems. All exception raised by RubyGems are a subclass of this one.
Raised when there is an error while building extensions.
A fake Gem::RemoteFetcher for use in tests or to avoid real live HTTP requests when testing code that uses RubyGems.
Example:
@fetcher = Gem::FakeFetcher.new
@fetcher.data['http://gems.example.com/yaml'] = source_index.to_yaml
Gem::RemoteFetcher.fetcher = @fetcher
# invoke RubyGems code
paths = @fetcher.paths
assert_equal 'http://gems.example.com/yaml', paths.shift
assert paths.empty?, paths.join(', ')
See RubyGems' tests for more examples of FakeFetcher.
Signals that a file permission error is preventing the user from operating on the given directory.
Used to raise parsing and loading errors
Raised when attempting to uninstall a gem that isn't in GEM_HOME.
Run an instance of the gem program.
Gem::GemRunner is only intended for internal use by RubyGems itself. It does not form any public API and may change at any time for any reason.
If you would like to duplicate functionality of `gem` commands, use the classes they call directly.
Raised by Gem::Resolver when dependencies conflict and create the inability to find a valid possible spec for a request.
Top level class for building the gem repository index.
The installer installs the files contained in the .gem into the Gem.home.
Gem::Installer does the work of putting files in all the right places on the filesystem including unpacking the gem into its gem dir, installing the gemspec in the specifications dir, storing the cached gem in the cache dir, and installing either wrappers or symlinks for executables.
The installer invokes pre and post install hooks. Hooks can be added either through a rubygems_plugin.rb file in an installed gem or via a rubygems/defaults/#{RUBY_ENGINE}.rb or rubygems/defaults/operating_system.rb file. See Gem.pre_install and Gem.post_install for details.
A test case for Gem::Installer.
Potentially raised when a specification is validated.
Raised when RubyGems is unable to load or activate a gem. Contains the name and version requirements of the gem that either conflicts with already activated gems or that RubyGems is otherwise unable to activate.
Raised when trying to activate a gem, and that gem does not exist on the system. Instead of rescuing from this class, make sure to rescue from the superclass Gem::LoadError to catch all types of load errors.
Raised when trying to activate a gem, and the gem exists on the system, but not the requested version. Instead of rescuing from this class, make sure to rescue from the superclass Gem::LoadError to catch all types of load errors.
This Gem::StreamUI subclass records input and output to StringIO for retrieval during tests.
Raised when you haven't provided enough input to your MockGemUi
IO wrapper that creates digests of contents written to the IO it wraps.
The format class knows the guts of the ancient .gem file format and provides the capability to read such ancient gems.
Please pretend this doesn't exist.
A header for a tar file
Raised when a tar file is corrupt
TarReader reads tar files and allows iteration over their items
Class for reading entries out of a tar file
Raised if the tar IO is not seekable
A test case for Gem::Package::Tar* classes
Allows writing of tar files
IO wrapper that allows writing a limited amount of data
IO wrapper that provides only write
Create a package based upon a Gem::Specification. Gem packages, as well as zip files and tar/gzipped packages can be produced by this task.
In addition to the Rake targets generated by Rake::PackageTask, a Gem::PackageTask will also generate the following tasks:
“package_dir/name-version.gem”
Create a RubyGems package with the given name and version.
Example using a Gem::Specification:
require 'rubygems'
require 'rubygems/package_task'
spec = Gem::Specification.new do |s|
s.summary = "Ruby based make-like utility."
s.name = 'rake'
s.version = PKG_VERSION
s.requirements << 'none'
s.files = PKG_FILES
s.description = <<-EOF
Rake is a Make-like program implemented in Ruby. Tasks
and dependencies are specified in standard Ruby syntax.
EOF
end
Gem::PackageTask.new(spec) do |pkg|
pkg.need_zip = true
pkg.need_tar = true
end
Gem::PathSupport facilitates the GEM_HOME and GEM_PATH environment settings to the rest of RubyGems.
Available list of platforms for targeting Gem installations.
See `gem help platform` for information on platform matching.
Generated when trying to lookup a gem to indicate that the gem was found, but that it isn't usable on the current platform.
fetch and install read these and report them to the user to aid in figuring out why a gem couldn't be installed.
Signals that a remote operation cannot be conducted, probably due to not being connected (or just not finding host).
RemoteFetcher handles the details of fetching gems and gem information from a remote source.
A FetchError exception wraps up the various possible IO and HTTP failures that could happen while downloading from the internet.
A FetchError that indicates that the reason for not being able to fetch data was that the host could not be contacted
Represents an error communicating via HTTP.
A RequestSet groups a request to activate a set of dependencies.
nokogiri = Gem::Dependency.new 'nokogiri', '~> 1.6'
pg = Gem::Dependency.new 'pg', '~> 0.14'
set = Gem::RequestSet.new nokogiri, pg
requests = set.resolve
p requests.map { |r| r.full_name }
#=> ["nokogiri-1.6.0", "mini_portile-0.5.1", "pg-0.17.0"]
A semi-compatible DSL for the Bundler Gemfile and Isolate gem dependencies files.
To work with both the Bundler Gemfile and Isolate formats this implementation takes some liberties to allow compatibility with each, most notably in source.
A basic gem dependencies file will look like the following:
source 'https://rubygems.org'
gem 'rails', '3.2.14a
gem 'devise', '~> 2.1', '>= 2.1.3'
gem 'cancan'
gem 'airbrake'
gem 'pg'
RubyGems recommends saving this as gem.deps.rb over Gemfile or Isolate.
To install the gems in this Gemfile use `gem install -g` to install it and create a lockfile. The lockfile will ensure that when you make changes to your gem dependencies file a minimum amount of change is made to the dependencies of your gems.
RubyGems can activate all the gems in your dependencies file at startup using the RUBYGEMS_GEMDEPS environment variable or through Gem.use_gemdeps. See Gem.use_gemdeps for details and warnings.
See `gem help install` and `gem help gem_dependencies` for further details.
Parses a gem.deps.rb.lock file and constructs a LockSet containing the dependencies found inside. If the lock file is missing no LockSet is constructed.
Raised when a lockfile cannot be parsed
A Requirement is a set of one or more version restrictions. It supports a few (=, !=, >, <, >=, <=, ~>) different restriction operators.
See Gem::Version for a description on how versions and requirements work together in RubyGems.
Raised when a bad requirement is encountered
Given a set of Gem::Dependency objects as needed and a way to query the set of available specs via set, calculates a set of ActivationRequest objects which indicate all the specs that should be activated to meet the all the requirements.
The global rubygems pool, available via the rubygems.org API. Returns instances of APISpecification.
Represents a specification retrieved via the rubygems.org API.
This is used to avoid loading the full Specification object when all we need is the name, version, and dependencies.
Specifies a Specification object that should be activated. Also contains a dependency that was used to introduce this activation.
The BestSet chooses the best available method to query a remote index.
It combines IndexSet and APISet
A ComposedSet allows multiple sets to be queried like a single set.
To create a composed set with any number of sets use:
Gem::Resolver.compose_sets set1, set2
This method will eliminate nesting of composed sets.
Used internally to indicate that a dependency conflicted with a spec that would be activated.
A set which represents the installed gems. Respects all the normal settings that control where to look for installed gems.
Used Internally. Wraps a Dependency object to also track which spec contained the Dependency.
A GitSet represents gems that are sourced from git repositories.
This is used for gem dependency file support.
Example:
set = Gem::Resolver::GitSet.new
set.add_git_gem 'rake', 'git://example/rake.git', tag: 'rake-10.1.0'
A GitSpecification represents a gem that is sourced from a git repository and is being loaded through a gem dependencies file through the git: option.
The global rubygems pool represented via the traditional source index.
Represents a possible Specification object returned from IndexSet. Used to delay needed to download full Specification objects when only the name and version are needed.
An InstalledSpecification represents a gem that is already installed locally.
A set of gems for installation sourced from remote sources and local .gem files
A LocalSpecification comes from a .gem file on the local filesystem.
A set of gems from a gem dependencies lockfile.
The LockSpecification comes from a lockfile (Gem::RequestSet::Lockfile).
A LockSpecification's dependency information is pre-filled from the lockfile.
An error caused by attempting to fulfil a dependency that was circular
@note This exception will be thrown iff a {Vertex} is added to a
{DependencyGraph} that has a {DependencyGraph::Vertex#path_to?} an
existing {DependencyGraph::Vertex}
A directed acyclic graph that is tuned to hold named dependencies
An action that modifies a {DependencyGraph} that is reversible. @abstract
@!visibility private (see DependencyGraph#add_edge_no_circular)
@!visibility private (see DependencyGraph#delete_edge)
@!visibility private @see DependencyGraph#detach_vertex_named
A log for dependency graph actions
@!visibility private @see DependencyGraph#tag
A vertex in a {DependencyGraph} that encapsulates a {#name} and a {#payload}
A state that encapsulates a set of {#requirements} with an {Array} of possibilities
An error caused by searching for a dependency that is completely unknown, i.e. has no versions available whatsoever.
A state that encapsulates a single possibility to fulfill the given {#requirement}
This class encapsulates a dependency resolver. The resolver is responsible for determining which set of dependencies to activate, with feedback from the {#specification_provider}
A specific resolution from a given {Resolver}
An error that occurred during the resolution process
An error caused by conflicts in version
The RequirementList is used to hold the requirements being considered while resolving a set of gems.
The RequirementList acts like a queue where the oldest items are removed first.
Resolver sets are used to look up specifications (and their dependencies) used in resolution. This set is abstract.
The SourceSet chooses the best available method to query a remote index.
Kind off like BestSet but filters the sources for gems
The Resolver::SpecSpecification contains common functionality for Resolver specifications that are backed by a Gem::Specification.
A Resolver::Specification contains a subset of the information contained in a Gem::Specification. Only the information necessary for dependency resolution in the resolver is included.
A VendorSet represents gems that have been unpacked into a specific directory that contains a gemspec.
This is used for gem dependency file support.
Example:
set = Gem::Resolver::VendorSet.new
set.add_vendor_gem 'rake', 'vendor/rake'
The directory vendor/rake must contain an unpacked rake gem along with a rake.gemspec (watching the given name).
A VendorSpecification represents a gem that has been unpacked into a project and is being loaded through a gem dependencies file through the path: option.
Raised when a gem dependencies file specifies a ruby version that does not match the current version.
Gem::Security default exception type
A Gem::Security::Policy object encapsulates the settings for verifying signed gem files. This is the base class. You can either declare an instance of this or use one of the preset security policies in Gem::Security::Policies.
The TrustDir manages the trusted certificates for gem signature verification.
Gem::Server and allows users to serve gems for consumption by `gem –remote-install`.
gem_server starts an HTTP server on the given port and serves the following:
“/” - Browsing of gem spec files for installed gems
“/specs.#{Gem.marshal_version}.gz” - specs name/version/platform index
“/latest_specs.#{Gem.marshal_version}.gz” - latest specs name/version/platform index
“/quick/” - Individual gemspecs
“/gems” - Direct access to download the installable gems
“/rdoc?q=” - Search for installed rdoc documentation
Usage¶ ↑
gem_server = Gem::Server.new Gem.dir, 8089, false
gem_server.run
SilentUI is a UI choice that is absolutely silent.
A Source knows how to list and fetch gems from a RubyGems marshal index.
There are other Source subclasses for installed gems, local gems, the bundler dependency API and so-forth.
A git gem for use in a gem dependencies file.
Example:
source =
Gem::Source::Git.new 'rake', 'git@example:rake.git', 'rake-10.1.0', false
source.specs
Represents an installed gem. This is used for dependency resolution.
The local source finds gems in the current directory for fulfilling dependencies.
A Lock source wraps an installed gem's source and sorts before other sources during dependency resolution. This allows RubyGems to prefer gems from dependency lock files.
A source representing a single .gem file. This is used for installation of local gems.
This represents a vendored source that is similar to an installed gem.
An error that indicates we weren't able to fetch some data from a source
The SourceList represents the sources rubygems has been configured to use. A source may be created from an array of sources:
Gem::SourceList.from %w[https://rubygems.example https://internal.example]
Or by adding them:
sources = Gem::SourceList.new
sources << 'https://rubygems.example'
The most common way to get a SourceList is Gem.sources.
SpecFetcher handles metadata updates from remote gem repositories.
Raised by the DependencyInstaller when a specific gem cannot be found
The Specification class contains the information for a Gem. Typically defined in a .gemspec file or a Rakefile, and looks like this:
Gem::Specification.new do |s|
s.name = 'example'
s.version = '0.1.0'
s.licenses = ['MIT']
s.summary = "This is an example!"
s.description = "Much longer explanation of the example!"
s.authors = ["Ruby Coder"]
s.email = '[email protected]'
s.files = ["lib/example.rb"]
s.homepage = 'https://rubygems.org/gems/example'
s.metadata = { "source_code_uri" => "https://github.com/example/example" }
end
Starting in RubyGems 2.0, a Specification can hold arbitrary metadata. See metadata for restrictions on the format and size of metadata items you may add to a specification.
Gem::StreamUI implements a simple stream based user interface.
An absolutely silent download reporter.
An absolutely silent progress reporter.
A basic dotted progress reporter.
A progress reporter that behaves nicely with threaded downloading.
A progress reporter that prints out messages about the current progress.
Gem::StubSpecification reads the stub: line from the gemspec. This prevents us having to eval the entire gemspec in order to find out certain information.
Raised to indicate that a system exit should occur with the specified exit_code
RubyGemTestCase provides a variety of methods for testing rubygems and gem-related behavior in a sandbox. Through RubyGemTestCase you can install and uninstall gems, fetch remote gems through a stub fetcher and be assured your normal set of gems is not affected.
Tests are always run at a safe level of 1.
The SpecFetcherSetup allows easy setup of a remote source in RubyGems tests:
spec_fetcher do |f|
f.gem 'a', 1
f.spec 'a', 2
f.gem 'b', 1' 'a' => '~> 1.0'
end
The above declaration creates two gems, a-1 and b-1, with a dependency from b to a. The declaration creates an additional spec a-2, but no gem for it (so it cannot be installed).
After the gems are created they are removed from Gem.dir.
The StaticSet is a static set of gem specifications used for testing only. It is available by requiring Gem::TestCase.
Raised when removing a gem with the uninstall command fails
An Uninstaller.
The uninstaller fires pre and post uninstall hooks. Hooks can be added either through a rubygems_plugin.rb file in an installed gem or via a rubygems/defaults/#{RUBY_ENGINE}.rb or rubygems/defaults/operating_system.rb file. See Gem.pre_uninstall and Gem.post_uninstall for details.
Raised by Resolver when a dependency requests a gem for which there is no spec.
The UriFormatter handles URIs from user-input and escaping.
uf = Gem::UriFormatter.new 'example.com'
p uf.normalize #=> 'http://example.com'
Validator performs various gem file and gem database validation
Raised by Gem::Validator when something is not right in a gem.
The Version class processes string versions into comparable values. A version string should normally be a series of numbers separated by periods. Each part (digits separated by periods) is considered its own number, and these are used for sorting. So for instance, 3.10 sorts higher than 3.2 because ten is greater than two.
If any part contains letters (currently only a-z are supported) then that version is considered prerelease. Versions with a prerelease part in the Nth part sort less than versions with N-1 parts. Prerelease parts are sorted alphabetically using the normal Ruby string sorting rules. If a prerelease part contains both letters and numbers, it will be broken into multiple parts to provide expected sort behavior (1.0.a10 becomes 1.0.a.10, and is greater than 1.0.a9).
Prereleases sort between real releases (newest to oldest):
1.0
1.0.b1
1.0.a.2
0.9
If you want to specify a version restriction that includes both prereleases and regular releases of the 1.x series this is the best way:
s.add_dependency 'example', '>= 1.0.0.a', '< 2.0.0'
How Software Changes¶ ↑
Users expect to be able to specify a version constraint that gives them some reasonable expectation that new versions of a library will work with their software if the version constraint is true, and not work with their software if the version constraint is false. In other words, the perfect system will accept all compatible versions of the library and reject all incompatible versions.
Libraries change in 3 ways (well, more than 3, but stay focused here!).
The change may be an implementation detail only and have no effect on the client software.
The change may add new features, but do so in a way that client software written to an earlier version is still compatible.
The change may change the public interface of the library in such a way that old software is no longer compatible.
Some examples are appropriate at this point. Suppose I have a Stack class that supports a push and a pop method.
Examples of Category 1 changes:¶ ↑
Switch from an array based implementation to a linked-list based implementation.
Provide an automatic (and transparent) backing store for large stacks.
Examples of Category 2 changes might be:¶ ↑
Add a depth method to return the current depth of the stack.
Add a top method that returns the current top of stack (without changing the stack).
Change push so that it returns the item pushed (previously it had no usable return value).
Examples of Category 3 changes might be:¶ ↑
Changes pop so that it no longer returns a value (you must use top to get the top of the stack).
Rename the methods to push_item and pop_item.
RubyGems Rational Versioning¶ ↑
Versions shall be represented by three non-negative integers, separated by periods (e.g. 3.1.4). The first integers is the “major” version number, the second integer is the “minor” version number, and the third integer is the “build” number.
A category 1 change (implementation detail) will increment the build number.
A category 2 change (backwards compatible) will increment the minor version number and reset the build number.
A category 3 change (incompatible) will increment the major build number and reset the minor and build numbers.
Any “public” release of a gem should have a different version. Normally that means incrementing the build number. This means a developer can generate builds all day long, but as soon as they make a public release, the version must be updated.
Examples¶ ↑
Let's work through a project lifecycle using our Stack example from above.
Version 0.0.1
The initial Stack class is release.
Version 0.0.2
Switched to a linked=list implementation because it is cooler.
Version 0.1.0
Added a depth method.
Version 1.0.0
Added top and made pop return nil (pop used to return the old top item).
Version 1.1.0
push now returns the value pushed (it used it return nil).
Version 1.1.1
Fixed a bug in the linked list implementation.
Version 1.1.2
Fixed a bug introduced in the last fix.
Client A needs a stack with basic push/pop capability. They write to the original interface (no top), so their version constraint looks like:
gem 'stack', '>= 0.0'
Essentially, any version is OK with Client A. An incompatible change to the library will cause them grief, but they are willing to take the chance (we call Client A optimistic).
Client B is just like Client A except for two things: (1) They use the depth method and (2) they are worried about future incompatibilities, so they write their version constraint like this:
gem 'stack', '~> 0.1'
The depth method was introduced in version 0.1.0, so that version or anything later is fine, as long as the version stays below version 1.0 where incompatibilities are introduced. We call Client B pessimistic because they are worried about incompatible future changes (it is OK to be pessimistic!).
Preventing Version Catastrophe:¶ ↑
From: blog.zenspider.com/2008/10/rubygems-howto-preventing-cata.html
Let's say you're depending on the fnord gem version 2.y.z. If you specify your dependency as “>= 2.0.0” then, you're good, right? What happens if fnord 3.0 comes out and it isn't backwards compatible with 2.y.z? Your stuff will break as a result of using “>=”. The better route is to specify your dependency with an “approximate” version specifier (“~>”). They're a tad confusing, so here is how the dependency specifiers work:
Specification From ... To (exclusive)
">= 3.0" 3.0 ... ∞
"~> 3.0" 3.0 ... 4.0
"~> 3.0.0" 3.0.0 ... 3.1
"~> 3.5" 3.5 ... 4.0
"~> 3.5.0" 3.5.0 ... 3.6
"~> 3" 3.0 ... 4.0
For the last example, single-digit versions are automatically extended with a zero to give a sensible result.
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
Error types.
A Hash is a dictionary-like collection of unique keys and their values. Also called associative arrays, they are similar to Arrays, but where an Array uses integers as its index, a Hash allows you to use any object type.
Hashes enumerate their values in the order that the corresponding keys were inserted.
A Hash can be easily created by using its implicit form:
grades = { "Jane Doe" => 10, "Jim Doe" => 6 }
Hashes allow an alternate syntax for keys that are symbols. Instead of
options = { :font_size => 10, :font_family => "Arial" }
You could write it as:
options = { font_size: 10, font_family: "Arial" }
Each named key is a symbol you can access in hash:
options[:font_size] # => 10
A Hash can also be created through its ::new method:
grades = Hash.new
grades["Dorothy Doe"] = 9
Hashes have a default value that is returned when accessing keys that do not exist in the hash. If no default is set nil is used. You can set the default value by sending it as an argument to Hash.new:
grades = Hash.new(0)
Or by using the default= method:
grades = {"Timmy Doe" => 8}
grades.default = 0
Accessing a value in a Hash requires using its key:
puts grades["Jane Doe"] # => 0
Common Uses¶ ↑
Hashes are an easy way to represent data structures, such as
books = {}
books[:matz] = "The Ruby Programming Language"
books[:black] = "The Well-Grounded Rubyist"
Hashes are also commonly used as a way to have named parameters in functions. Note that no brackets are used below. If a hash is the last argument on a method call, no braces are needed, thus creating a really clean interface:
Person.create(name: "John Doe", age: 27)
def self.create(params)
@name = params[:name]
@age = params[:age]
end
Hash Keys¶ ↑
Two objects refer to the same hash key when their hash value is identical and the two objects are eql? to each other.
A user-defined class may be used as a hash key if the hash and eql? methods are overridden to provide meaningful behavior. By default, separate instances refer to separate hash keys.
A typical implementation of hash is based on the object's data while eql? is usually aliased to the overridden == method:
class Book
attr_reader :author, :title
def initialize(author, title)
@author = author
@title = title
end
def ==(other)
self.class === other and
other.author == @author and
other.title == @title
end
alias eql? ==
def hash
@author.hash ^ @title.hash # XOR
end
end
book1 = Book.new 'matz', 'Ruby in a Nutshell'
book2 = Book.new 'matz', 'Ruby in a Nutshell'
reviews = {}
reviews[book1] = 'Great reference!'
reviews[book2] = 'Nice and compact!'
reviews.length #=> 1
See also Object#hash and Object#eql?
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.
io/console¶ ↑
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:
IO::console
IO#raw
IO#raw!
IO#cooked
IO#cooked!
IO#getch
IO#echo=
IO#echo?
IO#noecho
IO#winsize
IO#winsize=
IO#iflush
IO#ioflush
IO#oflush
Example:
require 'io/console'
rows, columns = $stdout.winsize
puts "Your screen is #{columns} wide and #{rows} tall"
exception to wait for reading by EAGAIN. see IO.select.
exception to wait for writing by EAGAIN. see IO.select.
exception to wait for reading by EINPROGRESS. see IO.select.
exception to wait for writing by EINPROGRESS. see IO.select.
exception to wait for reading by EWOULDBLOCK. see IO.select.
exception to wait for writing by EWOULDBLOCK. see IO.select.
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
IPAddr provides a set of methods to manipulate an IP address. Both IPv4 and IPv6 are supported.
Example¶ ↑
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>
Raised when the address family is invalid such as an address with an unsupported family, an address with an inconsistent family, or an address who's family cannot be determined.
Generic IPAddr related error. Exceptions raised in this class should inherit from Error.
Raised when the provided IP address is an invalid address.
Raised when the address is an invalid length.
IPSocket is the super class of TCPSocket and UDPSocket.
An exception raised by IRB.irb_abort
A class that wraps the current state of the irb session, including the configuration of IRB.conf.
Use a File for IO with irb, see InputMethod
An irb inspector
In order to create your own custom inspector there are two things you should be aware of:
Inspector uses inspect_value, or inspect_proc, for output of return values.
This also allows for an optional init+, or init_proc, which is called when the inspector is activated.
Knowing this, you can create a rudimentary inspector as follows:
irb(main):001:0> ins = IRB::Inspector.new(proc{ |v| "omg! #{v}" })
irb(main):001:0> IRB.CurrentContext.inspect_mode = ins # => omg! #<IRB::Inspector:0x007f46f7ba7d28>
irb(main):001:0> "what?" #=> omg! what?
Raised in the event of an exception in a file loaded from an Irb session
An abstract class, or superclass, for CompositeNotifier and LeveledNotifier to inherit. It provides several wrapper methods for the OutputMethod object used by the Notifier.
A class that can be used to create a group of notifier objects with the intent of representing a leveled notification system for irb.
This class will allow you to generate other notifiers, and assign them the appropriate level for output.
The Notifier class provides a class-method Notifier.def_notifier to create a new composite notifier. Using the first composite notifier object you create, sibling notifiers can be initialized with def_notifier.
A leveled notifier is comparable to the composite group from CompositeNotifier#notifiers.
NoMsgNotifier is a LeveledNotifier that's used as the default notifier when creating a new CompositeNotifier.
This notifier is used as the zero index, or level 0, for CompositeNotifier#notifiers, and will not output messages of any sort.
An abstract output class for IO in irb. This is mainly used internally by IRB::Notifier. You can define your own output method to use with Irb.new, or Context.new
A standard output printer
Raised when the given index is invalid.
a = [:foo, :bar]
a.fetch(0) #=> :foo
a[4] #=> nil
a.fetch(4) #=> IndexError: index 4 outside of array bounds: -2...2
Holds Integer values. You cannot add a singleton method to an Integer object, any attempt to do so will raise a TypeError.
Raised when the interrupt signal is received, typically because the user has pressed Control-C (on most posix platforms). As such, it is a subclass of SignalException.
begin
puts "Press ctrl-C when you get bored"
loop {}
rescue Interrupt => e
puts "Note: You will typically use Signal.trap instead."
end
produces:
Press ctrl-C when you get bored
then waits until it is interrupted with Control-C and then prints:
Note: You will typically use Signal.trap instead.
This is the JSON parser implemented as a C extension. It can be configured to be used by setting
JSON.parser = JSON::Ext::Parser
with the method parser= in JSON.
This exception is raised if a generator or unparser error occurs.
The base exception for JSON errors.
This exception is raised if the required unicode support is missing on the system. Usually this means that the iconv library is not installed.
This exception is raised if the nesting of parsed data structures is too deep.
This exception is raised if a parser error occurs.
This exception is raised if a generator or unparser error occurs.
Raised when the specified key is not found. It is a subclass of IndexError.
h = {"foo" => :bar}
h.fetch("foo") #=> :bar
h.fetch("baz") #=> KeyError: key not found: "baz"
Raised when a file required (a Ruby script, extension library, …) fails to load.
require 'this/file/does/not/exist'
raises the exception:
LoadError: no such file to load -- this/file/does/not/exist
Raised when Ruby can't yield as requested.
A typical scenario is attempting to yield when no block is given:
def call_block
yield 42
end
call_block
raises the exception:
LocalJumpError: no block given (yield)
A more subtle example:
def get_me_a_return
Proc.new { return 42 }
end
get_me_a_return.call
raises the exception:
LocalJumpError: unexpected return
Description¶ ↑
The Logger class provides a simple but sophisticated logging utility that you can use to output messages.
The messages have associated levels, such as INFO or ERROR that indicate their importance. You can then give the Logger a level, and only messages at that level or higher will be printed.
The levels are:
UNKNOWN
An unknown message that should always be logged.
FATAL
An unhandleable error that results in a program crash.
ERROR
A handleable error condition.
WARN
A warning.
INFO
Generic (useful) information about system operation.
DEBUG
Low-level information for developers.
For instance, in a production system, you may have your Logger set to INFO or even WARN. When you are developing the system, however, you probably want to know about the program's internal state, and would set the Logger to DEBUG.
Note: Logger does not escape or sanitize any messages passed to it. Developers should be aware of when potentially malicious data (user-input) is passed to Logger, and manually escape the untrusted data:
logger.info("User-input: #{input.dump}")
logger.info("User-input: %p" % input)
You can use formatter= for escaping all data.
original_formatter = Logger::Formatter.new
logger.formatter = proc { |severity, datetime, progname, msg|
original_formatter.call(severity, datetime, progname, msg.dump)
}
logger.info(input)
Example¶ ↑
This creates a Logger that outputs to the standard output stream, with a level of WARN:
require 'logger'
logger = Logger.new(STDOUT)
logger.level = Logger::WARN
logger.debug("Created logger")
logger.info("Program started")
logger.warn("Nothing to do!")
path = "a_non_existent_file"
begin
File.foreach(path) do |line|
unless line =~ /^(\w+) = (.*)$/
logger.error("Line in wrong format: #{line.chomp}")
end
end
rescue => err
logger.fatal("Caught exception; exiting")
logger.fatal(err)
end
Because the Logger's level is set to WARN, only the warning, error, and fatal messages are recorded. The debug and info messages are silently discarded.
Features¶ ↑
There are several interesting features that Logger provides, like auto-rolling of log files, setting the format of log messages, and specifying a program name in conjunction with the message. The next section shows you how to achieve these things.
HOWTOs¶ ↑
How to create a logger¶ ↑
The options below give you various choices, in more or less increasing complexity.
Create a logger which logs messages to STDERR/STDOUT.
logger = Logger.new(STDERR)
logger = Logger.new(STDOUT)
Create a logger for the file which has the specified name.
logger = Logger.new('logfile.log')
Create a logger for the specified file.
file = File.open('foo.log', File::WRONLY | File::APPEND)
# To create new logfile, add File::CREAT like:
# file = File.open('foo.log', File::WRONLY | File::APPEND | File::CREAT)
logger = Logger.new(file)
Create a logger which ages the logfile once it reaches a certain size. Leave 10 “old” log files where each file is about 1,024,000 bytes.
logger = Logger.new('foo.log', 10, 1024000)
Create a logger which ages the logfile daily/weekly/monthly.
logger = Logger.new('foo.log', 'daily')
logger = Logger.new('foo.log', 'weekly')
logger = Logger.new('foo.log', 'monthly')
How to log a message¶ ↑
Notice the different methods (fatal, error, info) being used to log messages of various levels? Other methods in this family are warn and debug. add is used below to log a message of an arbitrary (perhaps dynamic) level.
Message in a block.
logger.fatal { "Argument 'foo' not given." }
Message as a string.
logger.error "Argument #{@foo} mismatch."
With progname.
logger.info('initialize') { "Initializing..." }
With severity.
logger.add(Logger::FATAL) { 'Fatal error!' }
The block form allows you to create potentially complex log messages, but to delay their evaluation until and unless the message is logged. For example, if we have the following:
logger.debug { "This is a " + potentially + " expensive operation" }
If the logger's level is INFO or higher, no debug messages will be logged, and the entire block will not even be evaluated. Compare to this:
logger.debug("This is a " + potentially + " expensive operation")
Here, the string concatenation is done every time, even if the log level is not set to show the debug message.
How to close a logger¶ ↑
logger.close
Setting severity threshold¶ ↑
Original interface.
logger.sev_threshold = Logger::WARN
Log4r (somewhat) compatible interface.
logger.level = Logger::INFO
# DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN
Symbol or String (case insensitive)
logger.level = :info
logger.level = 'INFO'
# :debug < :info < :warn < :error < :fatal < :unknown
Constructor
Logger.new(logdev, level: Logger::INFO)
Logger.new(logdev, level: :info)
Logger.new(logdev, level: 'INFO')
Format¶ ↑
Log messages are rendered in the output stream in a certain format by default. The default format and a sample are shown below:
Log format:
SeverityID, [DateTime #pid] SeverityLabel -- ProgName: message
Log sample:
I, [1999-03-03T02:34:24.895701 #19074] INFO -- Main: info.
You may change the date and time format via datetime_format=.
logger.datetime_format = '%Y-%m-%d %H:%M:%S'
# e.g. "2004-01-03 00:54:26"
or via the constructor.
Logger.new(logdev, datetime_format: '%Y-%m-%d %H:%M:%S')
Or, you may change the overall format via the formatter= method.
logger.formatter = proc do |severity, datetime, progname, msg|
"#{datetime}: #{msg}\n"
end
# e.g. "2005-09-22 08:51:08 +0900: hello world"
or via the constructor.
Logger.new(logdev, formatter: proc {|severity, datetime, progname, msg|
"#{datetime}: #{msg}\n"
})
Default formatter for log messages.
Device used for logging messages.
MatchData encapsulates the result of matching a Regexp against string. It is returned by Regexp#match and String#match, and also stored in a global variable returned by Regexp.last_match.
Usage:
url = 'https://docs.ruby-lang.org/en/2.5.0/MatchData.html'
m = url.match(/(\d\.?)+/) # => #<MatchData "2.5.0" 1:"0">
m.string # => "https://docs.ruby-lang.org/en/2.5.0/MatchData.html"
m.regexp # => /(\d\.?)+/
# entire matched substring:
m[0] # => "2.5.0"
# Working with unnamed captures
m = url.match(%r{([^/]+)/([^/]+)\.html$})
m.captures # => ["2.5.0", "MatchData"]
m[1] # => "2.5.0"
m.values_at(1, 2) # => ["2.5.0", "MatchData"]
# Working with named captures
m = url.match(%r{(?<version>[^/]+)/(?<module>[^/]+)\.html$})
m.captures # => ["2.5.0", "MatchData"]
m.named_captures # => {"version"=>"2.5.0", "module"=>"MatchData"}
m[:version] # => "2.5.0"
m.values_at(:version, :module)
# => ["2.5.0", "MatchData"]
# Numerical indexes are working, too
m[1] # => "2.5.0"
m.values_at(1, 2) # => ["2.5.0", "MatchData"]
Global variables equivalence¶ ↑
Parts of last MatchData (returned by Regexp.last_match) are also aliased as global variables:
$~ is Regexp.last_match;
$& is Regexp.last_match[0];
$1, $2, and so on are Regexp.last_match[i] (captures by number);
$` is Regexp.last_match.pre_match;
$' is Regexp.last_match.post_match;
$+ is Regexp.last_match[-1] (the last capture).
See also “Special global variables” section in Regexp documentation.
Raised when a mathematical function is evaluated outside of its domain of definition.
For example, since cos returns values in the range -1..1, its inverse function acos is only defined on that interval:
Math.acos(42)
produces:
Math::DomainError: Numerical argument is out of domain - "acos"
The Matrix class represents a mathematical matrix. It provides methods for creating matrices, operating on them arithmetically and algebraically, and determining their mathematical properties such as trace, rank, inverse, determinant, or eigensystem.
Eigenvalues and eigenvectors of a real matrix.
Computes the eigenvalues and eigenvectors of a matrix A.
If A is diagonalizable, this provides matrices V and D such that A = V*D*V.inv, where D is the diagonal matrix with entries equal to the eigenvalues and V is formed by the eigenvectors.
If A is symmetric, then V is orthogonal and thus A = V*D*V.t
For an m-by-n matrix A with m >= n, the LU decomposition is an m-by-n unit lower triangular matrix L, an n-by-n upper triangular matrix U, and a m-by-m permutation matrix P so that L*U = P*A. If m < n, then L is m-by-m and U is m-by-n.
The LUP decomposition with pivoting always exists, even if the matrix is singular, so the constructor will never fail. The primary use of the LU decomposition is in the solution of square systems of simultaneous linear equations. This will fail if singular? returns true.
Method objects are created by Object#method, and are associated with a particular object (not just with a class). They may be used to invoke the method within the object, and as a block associated with an iterator. They may also be unbound from one object (creating an UnboundMethod) and bound to another.
class Thing
def square(n)
n*n
end
end
thing = Thing.new
meth = thing.method(:square)
meth.call(9) #=> 81
[ 1, 2, 3 ].collect(&meth) #=> [1, 4, 9]
[ 1, 2, 3 ].each(&method(:puts)) #=> prints 1, 2, 3
require 'date'
%w[2017-03-01 2017-03-02].collect(&Date.method(:parse))
#=> [#<Date: 2017-03-01 ((2457814j,0s,0n),+0s,2299161j)>, #<Date: 2017-03-02 ((2457815j,0s,0n),+0s,2299161j)>]
A Module is a collection of methods and constants. The methods in a module may be instance methods or module methods. Instance methods appear as methods in a class when the module is included, module methods do not. Conversely, module methods may be called without creating an encapsulating object, while instance methods may not. (See Module#module_function.)
In the descriptions that follow, the parameter sym refers to a symbol, which is either a quoted string or a Symbol (such as :name).
module Mod
include Math
CONST = 1
def meth
# ...
end
end
Mod.class #=> Module
Mod.constants #=> [:CONST, :PI, :E]
Mod.instance_methods #=> [:meth]
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
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.
Mutex implements a simple semaphore that can be used to coordinate access to shared data from multiple concurrent threads.
Example:
semaphore = Mutex.new
a = Thread.new {
semaphore.synchronize {
# access shared resource
}
}
b = Thread.new {
semaphore.synchronize {
# access shared resource
}
}
Raised when a given name is invalid or undefined.
puts foo
raises the exception:
NameError: undefined local variable or method `foo' for main:Object
Since constant names must start with a capital:
Integer.const_set :answer, 42
raises the exception:
NameError: wrong constant name answer
This class is equivalent to POP3, except that it uses APOP authentication.
This class is equivalent to POP3, except that it uses APOP authentication.
This class implements the File Transfer Protocol. If you have used a command-line FTP program, and are familiar with the commands, you will be able to use this class easily. Some extra features are included to take advantage of Ruby's style and strengths.
Example¶ ↑
require 'net/ftp'
Example 1¶ ↑
ftp = Net::FTP.new('example.com')
ftp.login
files = ftp.chdir('pub/lang/ruby/contrib')
files = ftp.list('n*')
ftp.getbinaryfile('nif.rb-0.91.gz', 'nif.gz', 1024)
ftp.close
Example 2¶ ↑
Net::FTP.open('example.com') do |ftp|
ftp.login
files = ftp.chdir('pub/lang/ruby/contrib')
files = ftp.list('n*')
ftp.getbinaryfile('nif.rb-0.91.gz', 'nif.gz', 1024)
end
Major Methods¶ ↑
The following are the methods most likely to be useful to users:
FTP.open
getbinaryfile
gettextfile
putbinaryfile
puttextfile
chdir
nlst
size
rename
delete
MLSxEntry represents an entry in responses of MLST/MLSD. Each entry has the facts (e.g., size, last modification time, etc.) and the pathname.
An HTTP client API for Ruby.¶ ↑
Net::HTTP provides a rich library which can be used to build HTTP user-agents. For more details about HTTP see [RFC2616](www.ietf.org/rfc/rfc2616.txt).
Net::HTTP is designed to work closely with URI. URI::HTTP#host, URI::HTTP#port and URI::HTTP#request_uri are designed to work with Net::HTTP.
If you are only performing a few GET requests you should try OpenURI.
Simple Examples¶ ↑
All examples assume you have loaded Net::HTTP with:
require 'net/http'
This will also require 'uri' so you don't need to require it separately.
The Net::HTTP methods in the following section do not persist connections. They are not recommended if you are performing many HTTP requests.
GET¶ ↑
Net::HTTP.get('example.com', '/index.html') # => String
GET by URI¶ ↑
uri = URI('http://example.com/index.html?count=10')
Net::HTTP.get(uri) # => String
GET with Dynamic Parameters¶ ↑
uri = URI('http://example.com/index.html')
params = { :limit => 10, :page => 3 }
uri.query = URI.encode_www_form(params)
res = Net::HTTP.get_response(uri)
puts res.body if res.is_a?(Net::HTTPSuccess)
POST¶ ↑
uri = URI('http://www.example.com/search.cgi')
res = Net::HTTP.post_form(uri, 'q' => 'ruby', 'max' => '50')
puts res.body
POST with Multiple Values¶ ↑
uri = URI('http://www.example.com/search.cgi')
res = Net::HTTP.post_form(uri, 'q' => ['ruby', 'perl'], 'max' => '50')
puts res.body
How to use Net::HTTP¶ ↑
The following example code can be used as the basis of an HTTP user-agent which can perform a variety of request types using persistent connections.
uri = URI('http://example.com/some_path?query=string')
Net::HTTP.start(uri.host, uri.port) do |http|
request = Net::HTTP::Get.new uri
response = http.request request # Net::HTTPResponse object
end
Net::HTTP::start immediately creates a connection to an HTTP server which is kept open for the duration of the block. The connection will remain open for multiple requests in the block if the server indicates it supports persistent connections.
If you wish to re-use a connection across multiple HTTP requests without automatically closing it you can use ::new and then call start and finish manually.
The request types Net::HTTP supports are listed below in the section “HTTP Request Classes”.
For all the Net::HTTP request objects and shortcut request methods you may supply either a String for the request path or a URI from which Net::HTTP will extract the request path.
Response Data¶ ↑
uri = URI('http://example.com/index.html')
res = Net::HTTP.get_response(uri)
# Headers
res['Set-Cookie'] # => String
res.get_fields('set-cookie') # => Array
res.to_hash['set-cookie'] # => Array
puts "Headers: #{res.to_hash.inspect}"
# Status
puts res.code # => '200'
puts res.message # => 'OK'
puts res.class.name # => 'HTTPOK'
# Body
puts res.body if res.response_body_permitted?
Following Redirection¶ ↑
Each Net::HTTPResponse object belongs to a class for its response code.
For example, all 2XX responses are instances of a Net::HTTPSuccess subclass, a 3XX response is an instance of a Net::HTTPRedirection subclass and a 200 response is an instance of the Net::HTTPOK class. For details of response classes, see the section “HTTP Response Classes” below.
Using a case statement you can handle various types of responses properly:
def fetch(uri_str, limit = 10)
# You should choose a better exception.
raise ArgumentError, 'too many HTTP redirects' if limit == 0
response = Net::HTTP.get_response(URI(uri_str))
case response
when Net::HTTPSuccess then
response
when Net::HTTPRedirection then
location = response['location']
warn "redirected to #{location}"
fetch(location, limit - 1)
else
response.value
end
end
print fetch('http://www.ruby-lang.org')
POST¶ ↑
A POST can be made using the Net::HTTP::Post request class. This example creates a URL encoded POST body:
uri = URI('http://www.example.com/todo.cgi')
req = Net::HTTP::Post.new(uri)
req.set_form_data('from' => '2005-01-01', 'to' => '2005-03-31')
res = Net::HTTP.start(uri.hostname, uri.port) do |http|
http.request(req)
end
case res
when Net::HTTPSuccess, Net::HTTPRedirection
# OK
else
res.value
end
To send multipart/form-data use Net::HTTPHeader#set_form:
req = Net::HTTP::Post.new(uri)
req.set_form([['upload', File.open('foo.bar')]], 'multipart/form-data')
Other requests that can contain a body such as PUT can be created in the same way using the corresponding request class (Net::HTTP::Put).
Setting Headers¶ ↑
The following example performs a conditional GET using the If-Modified-Since header. If the files has not been modified since the time in the header a Not Modified response will be returned. See RFC 2616 section 9.3 for further details.
uri = URI('http://example.com/cached_response')
file = File.stat 'cached_response'
req = Net::HTTP::Get.new(uri)
req['If-Modified-Since'] = file.mtime.rfc2822
res = Net::HTTP.start(uri.hostname, uri.port) {|http|
http.request(req)
}
open 'cached_response', 'w' do |io|
io.write res.body
end if res.is_a?(Net::HTTPSuccess)
Basic Authentication¶ ↑
Basic authentication is performed according to [RFC2617](www.ietf.org/rfc/rfc2617.txt).
uri = URI('http://example.com/index.html?key=value')
req = Net::HTTP::Get.new(uri)
req.basic_auth 'user', 'pass'
res = Net::HTTP.start(uri.hostname, uri.port) {|http|
http.request(req)
}
puts res.body
Streaming Response Bodies¶ ↑
By default Net::HTTP reads an entire response into memory. If you are handling large files or wish to implement a progress bar you can instead stream the body directly to an IO.
uri = URI('http://example.com/large_file')
Net::HTTP.start(uri.host, uri.port) do |http|
request = Net::HTTP::Get.new uri
http.request request do |response|
open 'large_file', 'w' do |io|
response.read_body do |chunk|
io.write chunk
end
end
end
end
HTTPS¶ ↑
HTTPS is enabled for an HTTP connection by Net::HTTP#use_ssl=.
uri = URI('https://secure.example.com/some_path?query=string')
Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
request = Net::HTTP::Get.new uri
response = http.request request # Net::HTTPResponse object
end
Or if you simply want to make a GET request, you may pass in an URI object that has an HTTPS URL. Net::HTTP automatically turns on TLS verification if the URI object has a 'https' URI scheme.
uri = URI('https://example.com/')
Net::HTTP.get(uri) # => String
In previous versions of Ruby you would need to require 'net/https' to use HTTPS. This is no longer true.
Proxies¶ ↑
Net::HTTP will automatically create a proxy from the http_proxy environment variable if it is present. To disable use of http_proxy, pass nil for the proxy address.
You may also create a custom proxy:
proxy_addr = 'your.proxy.host'
proxy_port = 8080
Net::HTTP.new('example.com', nil, proxy_addr, proxy_port).start { |http|
# always proxy via your.proxy.addr:8080
}
See Net::HTTP.new for further details and examples such as proxies that require a username and password.
Compression¶ ↑
Net::HTTP automatically adds Accept-Encoding for compression of response bodies and automatically decompresses gzip and deflate responses unless a Range header was sent.
Compression can be disabled through the Accept-Encoding: identity header.
HTTP Request Classes¶ ↑
Here is the HTTP request class hierarchy.
Net::HTTPRequest
Net::HTTP::Get
Net::HTTP::Head
Net::HTTP::Post
Net::HTTP::Patch
Net::HTTP::Put
Net::HTTP::Proppatch
Net::HTTP::Lock
Net::HTTP::Unlock
Net::HTTP::Options
Net::HTTP::Propfind
Net::HTTP::Delete
Net::HTTP::Move
Net::HTTP::Copy
Net::HTTP::Mkcol
Net::HTTP::Trace
HTTP Response Classes¶ ↑
Here is HTTP response class hierarchy. All classes are defined in Net module and are subclasses of Net::HTTPResponse.
HTTPUnknownResponse
For unhandled HTTP extensions
HTTPInformation
1xx
HTTPContinue
100
HTTPSwitchProtocol
101
HTTPSuccess
2xx
HTTPOK
200
HTTPCreated
201
HTTPAccepted
202
HTTPNonAuthoritativeInformation
203
HTTPNoContent
204
HTTPResetContent
205
HTTPPartialContent
206
HTTPMultiStatus
207
HTTPIMUsed
226
HTTPRedirection
3xx
HTTPMultipleChoices
300
HTTPMovedPermanently
301
HTTPFound
302
HTTPSeeOther
303
HTTPNotModified
304
HTTPUseProxy
305
HTTPTemporaryRedirect
307
HTTPClientError
4xx
HTTPBadRequest
400
HTTPUnauthorized
401
HTTPPaymentRequired
402
HTTPForbidden
403
HTTPNotFound
404
HTTPMethodNotAllowed
405
HTTPNotAcceptable
406
HTTPProxyAuthenticationRequired
407
HTTPRequestTimeOut
408
HTTPConflict
409
HTTPGone
410
HTTPLengthRequired
411
HTTPPreconditionFailed
412
HTTPRequestEntityTooLarge
413
HTTPRequestURITooLong
414
HTTPUnsupportedMediaType
415
HTTPRequestedRangeNotSatisfiable
416
HTTPExpectationFailed
417
HTTPUnprocessableEntity
422
HTTPLocked
423
HTTPFailedDependency
424
HTTPUpgradeRequired
426
HTTPPreconditionRequired
428
HTTPTooManyRequests
429
HTTPRequestHeaderFieldsTooLarge
431
HTTPUnavailableForLegalReasons
451
HTTPServerError
5xx
HTTPInternalServerError
500
HTTPNotImplemented
501
HTTPBadGateway
502
HTTPServiceUnavailable
503
HTTPGatewayTimeOut
504
HTTPVersionNotSupported
505
HTTPInsufficientStorage
507
HTTPNetworkAuthenticationRequired
511
There is also the Net::HTTPBadResponse exception which is raised when there is a protocol error.
See Net::HTTPGenericRequest for attributes and methods.
See Net::HTTPGenericRequest for attributes and methods. See Net::HTTP for usage examples.
See Net::HTTPGenericRequest for attributes and methods. See Net::HTTP for usage examples.
See Net::HTTPGenericRequest for attributes and methods. See Net::HTTP for usage examples.
See Net::HTTPGenericRequest for attributes and methods.
See Net::HTTPGenericRequest for attributes and methods.
See Net::HTTPGenericRequest for attributes and methods.
See Net::HTTPGenericRequest for attributes and methods.
See Net::HTTPGenericRequest for attributes and methods.
See Net::HTTPGenericRequest for attributes and methods. See Net::HTTP for usage examples.
See Net::HTTPGenericRequest for attributes and methods.
See Net::HTTPGenericRequest for attributes and methods.
See Net::HTTPGenericRequest for attributes and methods. See Net::HTTP for usage examples.
See Net::HTTPGenericRequest for attributes and methods.
See Net::HTTPGenericRequest for attributes and methods.
HTTPGenericRequest is the parent of the HTTPRequest class. Do not use this directly; use a subclass of HTTPRequest.
Mixes in the HTTPHeader module to provide easier access to HTTP headers.
444 No Response - Nginx 449 Retry With - Microsoft 450 Blocked by Windows Parental Controls - Microsoft 499 Client Closed Request - Nginx
418 I'm a teapot - RFC 2324; a joke RFC 420 Enhance Your Calm - Twitter
509 Bandwidth Limit Exceeded - Apache bw/limited extension
HTTP request class. This class wraps together the request header and the request path. You cannot use this class directly. Instead, you should use one of its subclasses: Net::HTTP::Get, Net::HTTP::Post, Net::HTTP::Head.
HTTP response class.
This class wraps together the response header and the response body (the entity requested).
It mixes in the HTTPHeader module, which provides access to response header values both via hash-like methods and via individual readers.
Note that each possible HTTP response code defines its own HTTPResponse subclass. These are listed below.
All classes are defined under the Net module. Indentation indicates inheritance. For a list of the classes see Net::HTTP.
306 Switch Proxy - no longer unused
www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
425 Unordered Collection - existed only in draft
Net::IMAP implements Internet Message Access Protocol (IMAP) client functionality. The protocol is described in [IMAP].
IMAP Overview¶ ↑
An IMAP client connects to a server, and then authenticates itself using either authenticate() or login(). Having authenticated itself, there is a range of commands available to it. Most work with mailboxes, which may be arranged in an hierarchical namespace, and each of which contains zero or more messages. How this is implemented on the server is implementation-dependent; on a UNIX server, it will frequently be implemented as files in mailbox format within a hierarchy of directories.
To work on the messages within a mailbox, the client must first select that mailbox, using either select() or (for read-only access) examine(). Once the client has successfully selected a mailbox, they enter selected state, and that mailbox becomes the current mailbox, on which mail-item related commands implicitly operate.
Messages have two sorts of identifiers: message sequence numbers and UIDs.
Message sequence numbers number messages within a mailbox from 1 up to the number of items in the mailbox. If a new message arrives during a session, it receives a sequence number equal to the new size of the mailbox. If messages are expunged from the mailbox, remaining messages have their sequence numbers “shuffled down” to fill the gaps.
UIDs, on the other hand, are permanently guaranteed not to identify another message within the same mailbox, even if the existing message is deleted. UIDs are required to be assigned in ascending (but not necessarily sequential) order within a mailbox; this means that if a non-IMAP client rearranges the order of mailitems within a mailbox, the UIDs have to be reassigned. An IMAP client thus cannot rearrange message orders.
Examples of Usage¶ ↑
List sender and subject of all recent messages in the default mailbox¶ ↑
imap = Net::IMAP.new('mail.example.com')
imap.authenticate('LOGIN', 'joe_user', 'joes_password')
imap.examine('INBOX')
imap.search(["RECENT"]).each do |message_id|
envelope = imap.fetch(message_id, "ENVELOPE")[0].attr["ENVELOPE"]
puts "#{envelope.from[0].name}: \t#{envelope.subject}"
end
Move all messages from April 2003 from “Mail/sent-mail” to “Mail/sent-apr03”¶ ↑
imap = Net::IMAP.new('mail.example.com')
imap.authenticate('LOGIN', 'joe_user', 'joes_password')
imap.select('Mail/sent-mail')
if not imap.list('Mail/', 'sent-apr03')
imap.create('Mail/sent-apr03')
end
imap.search(["BEFORE", "30-Apr-2003", "SINCE", "1-Apr-2003"]).each do |message_id|
imap.copy(message_id, "Mail/sent-apr03")
imap.store(message_id, "+FLAGS", [:Deleted])
end
imap.expunge
Thread Safety¶ ↑
Net::IMAP supports concurrent threads. For example,
imap = Net::IMAP.new("imap.foo.net", "imap2")
imap.authenticate("cram-md5", "bar", "password")
imap.select("inbox")
fetch_thread = Thread.start { imap.fetch(1..-1, "UID") }
search_result = imap.search(["BODY", "hello"])
fetch_result = fetch_thread.value
imap.disconnect
This script invokes the FETCH command and the SEARCH command concurrently.
Errors¶ ↑
An IMAP server can send three different types of responses to indicate failure:
NO
the attempted command could not be successfully completed. For instance, the username/password used for logging in are incorrect; the selected mailbox does not exist; etc.
BAD
the request from the client does not follow the server's understanding of the IMAP protocol. This includes attempting commands from the wrong client state; for instance, attempting to perform a SEARCH command without having SELECTed a current mailbox. It can also signal an internal server failure (such as a disk crash) has occurred.
BYE
the server is saying goodbye. This can be part of a normal logout sequence, and can be used as part of a login sequence to indicate that the server is (for some reason) unwilling to accept your connection. As a response to any other command, it indicates either that the server is shutting down, or that the server is timing out the client connection due to inactivity.
These three error response are represented by the errors Net::IMAP::NoResponseError, Net::IMAP::BadResponseError, and Net::IMAP::ByeResponseError, all of which are subclasses of Net::IMAP::ResponseError. Essentially, all methods that involve sending a request to the server can generate one of these errors. Only the most pertinent instances have been documented below.
Because the IMAP class uses Sockets for communication, its methods are also susceptible to the various errors that can occur when working with sockets. These are generally represented as Errno errors. For instance, any method that involves sending a request to the server and/or receiving a response from it could raise an Errno::EPIPE error if the network connection unexpectedly goes down. See the socket(7), ip(7), tcp(7), socket(2), connect(2), and associated man pages.
Finally, a Net::IMAP::DataFormatError is thrown if low-level data is found to be in an incorrect format (for instance, when converting between UTF-8 and UTF-16), and Net::IMAP::ResponseParseError is thrown if a server response is non-parseable.
References¶ ↑
[IMAP]
Crispin, “INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1”,
RFC 2060, December 1996. (Note: since obsoleted by RFC 3501)
[LANGUAGE-TAGS]
Alvestrand, H., “Tags for the Identification of Languages”, RFC 1766, March 1995.
[MD5]
Myers, J., and M. Rose, “The Content-MD5 Header Field”, RFC 1864, October 1995.
[MIME-IMB]
Freed, N., and N. Borenstein, “MIME (Multipurpose Internet Mail Extensions) Part One: Format of Internet Message Bodies”, RFC 2045, November 1996.
[RFC-822]
Crocker, D., “Standard for the Format of ARPA Internet Text Messages”, STD 11, RFC 822, University of Delaware, August 1982.
[RFC-2087]
Myers, J., “IMAP4 QUOTA extension”, RFC 2087, January 1997.
[RFC-2086]
Myers, J., “IMAP4 ACL extension”, RFC 2086, January 1997.
[RFC-2195]
Klensin, J., Catoe, R., and Krumviede, P., “IMAP/POP AUTHorize Extension for Simple Challenge/Response”, RFC 2195, September 1997.
[SORT-THREAD-EXT]
Crispin, M., “INTERNET MESSAGE ACCESS PROTOCOL - SORT and THREAD Extensions”, draft-ietf-imapext-sort, May 2003.
[OSSL]
www.openssl.org
[RSSL]
savannah.gnu.org/projects/rubypki
[UTF7]
Goldsmith, D. and Davis, M., “UTF-7: A Mail-Safe Transformation Format of Unicode”, RFC 2152, May 1997.
Error raised upon a “BAD” response from the server, indicating that the client command violated the IMAP protocol, or an internal server failure has occurred.
Net::IMAP::BodyTypeAttachment represents attachment body structures of messages.
Fields:¶ ↑
media_type
Returns the content media type name.
subtype
Returns nil.
param
Returns a hash that represents parameters.
multipart?
Returns false.
Net::IMAP::BodyTypeBasic represents basic body structures of messages.
Fields:¶ ↑
media_type
Returns the content media type name as defined in [MIME-IMB].
subtype
Returns the content subtype name as defined in [MIME-IMB].
param
Returns a hash that represents parameters as defined in [MIME-IMB].
content_id
Returns a string giving the content id as defined in [MIME-IMB].
description
Returns a string giving the content description as defined in [MIME-IMB].
encoding
Returns a string giving the content transfer encoding as defined in [MIME-IMB].
size
Returns a number giving the size of the body in octets.
md5
Returns a string giving the body MD5 value as defined in [MD5].
disposition
Returns a Net::IMAP::ContentDisposition object giving the content disposition.
language
Returns a string or an array of strings giving the body language value as defined in [LANGUAGE-TAGS].
extension
Returns extension data.
multipart?
Returns false.
Net::IMAP::BodyTypeMessage represents MESSAGE/RFC822 body structures of messages.
Fields:¶ ↑
envelope
Returns a Net::IMAP::Envelope giving the envelope structure.
body
Returns an object giving the body structure.
And Net::IMAP::BodyTypeMessage has all methods of Net::IMAP::BodyTypeText.
Net::IMAP::BodyTypeMultipart represents multipart body structures of messages.
Fields:¶ ↑
media_type
Returns the content media type name as defined in [MIME-IMB].
subtype
Returns the content subtype name as defined in [MIME-IMB].
parts
Returns multiple parts.
param
Returns a hash that represents parameters as defined in [MIME-IMB].
disposition
Returns a Net::IMAP::ContentDisposition object giving the content disposition.
language
Returns a string or an array of strings giving the body language value as defined in [LANGUAGE-TAGS].
extension
Returns extension data.
multipart?
Returns true.
Net::IMAP::BodyTypeText represents TEXT body structures of messages.
Fields:¶ ↑
lines
Returns the size of the body in text lines.
And Net::IMAP::BodyTypeText has all fields of Net::IMAP::BodyTypeBasic.
Error raised upon a “BYE” response from the server, indicating that the client is not being allowed to login, or has been timed out due to inactivity.
Authenticator for the “CRAM-MD5” authentication type. See authenticate().
Error raised when data is in the incorrect format.
Authenticator for the “DIGEST-MD5” authentication type. See authenticate().
Superclass of IMAP errors.
Error raised when too many flags are interned to symbols.
Authenticator for the “LOGIN” authentication type. See authenticate().
Error raised upon a “NO” response from the server, indicating that the client command could not be completed successfully.
Authenticator for the “PLAIN” authentication type. See authenticate().
Superclass of all errors used to encapsulate “fail” responses from the server.
Error raised when a response from the server is non-parseable.
OpenTimeout, a subclass of Timeout::Error, is raised if a connection cannot be created within the open_timeout.
What is This Library?¶ ↑
This library provides functionality for retrieving email via POP3, the Post Office Protocol version 3. For details of POP3, see [RFC1939] (www.ietf.org/rfc/rfc1939.txt).
Examples¶ ↑
Retrieving Messages¶ ↑
This example retrieves messages from the server and deletes them on the server.
Messages are written to files named 'inbox/1', 'inbox/2', .… Replace 'pop.example.com' with your POP3 server address, and 'YourAccount' and 'YourPassword' with the appropriate account details.
require 'net/pop'
pop = Net::POP3.new('pop.example.com')
pop.start('YourAccount', 'YourPassword') # (1)
if pop.mails.empty?
puts 'No mail.'
else
i = 0
pop.each_mail do |m| # or "pop.mails.each ..." # (2)
File.open("inbox/#{i}", 'w') do |f|
f.write m.pop
end
m.delete
i += 1
end
puts "#{pop.mails.size} mails popped."
end
pop.finish # (3)
Call Net::POP3#start and start POP session.
Access messages by using POP3#each_mail and/or POP3#mails.
Close POP session by calling POP3#finish or use the block form of start.
Shortened Code¶ ↑
The example above is very verbose. You can shorten the code by using some utility methods. First, the block form of Net::POP3.start can be used instead of POP3.new, POP3#start and POP3#finish.
require 'net/pop'
Net::POP3.start('pop.example.com', 110,
'YourAccount', 'YourPassword') do |pop|
if pop.mails.empty?
puts 'No mail.'
else
i = 0
pop.each_mail do |m| # or "pop.mails.each ..."
File.open("inbox/#{i}", 'w') do |f|
f.write m.pop
end
m.delete
i += 1
end
puts "#{pop.mails.size} mails popped."
end
end
POP3#delete_all is an alternative for each_mail and delete.
require 'net/pop'
Net::POP3.start('pop.example.com', 110,
'YourAccount', 'YourPassword') do |pop|
if pop.mails.empty?
puts 'No mail.'
else
i = 1
pop.delete_all do |m|
File.open("inbox/#{i}", 'w') do |f|
f.write m.pop
end
i += 1
end
end
end
And here is an even shorter example.
require 'net/pop'
i = 0
Net::POP3.delete_all('pop.example.com', 110,
'YourAccount', 'YourPassword') do |m|
File.open("inbox/#{i}", 'w') do |f|
f.write m.pop
end
i += 1
end
Memory Space Issues¶ ↑
All the examples above get each message as one big string. This example avoids this.
require 'net/pop'
i = 1
Net::POP3.delete_all('pop.example.com', 110,
'YourAccount', 'YourPassword') do |m|
File.open("inbox/#{i}", 'w') do |f|
m.pop do |chunk| # get a message little by little.
f.write chunk
end
i += 1
end
end
Using APOP¶ ↑
The net/pop library supports APOP authentication. To use APOP, use the Net::APOP class instead of the Net::POP3 class. You can use the utility method, Net::POP3.APOP(). For example:
require 'net/pop'
# Use APOP authentication if $isapop == true
pop = Net::POP3.APOP($isapop).new('apop.example.com', 110)
pop.start('YourAccount', 'YourPassword') do |pop|
# Rest of the code is the same.
end
Fetch Only Selected Mail Using 'UIDL' POP Command¶ ↑
If your POP server provides UIDL functionality, you can grab only selected mails from the POP server. e.g.
def need_pop?( id )
# determine if we need pop this mail...
end
Net::POP3.start('pop.example.com', 110,
'Your account', 'Your password') do |pop|
pop.mails.select { |m| need_pop?(m.unique_id) }.each do |m|
do_something(m.pop)
end
end
The POPMail#unique_id() method returns the unique-id of the message as a String. Normally the unique-id is a hash of the message.
POP3 authentication error.
Unexpected response from the server.
Non-authentication POP3 protocol error (reply code “-ERR”, except authentication).
This class represents a message which exists on the POP server. Instances of this class are created by the POP3 class; they should not be directly created by the user.
ReadTimeout, a subclass of Timeout::Error, is raised if a chunk of the response cannot be read within the read_timeout.
What is This Library?¶ ↑
This library provides functionality to send internet mail via SMTP, the Simple Mail Transfer Protocol. For details of SMTP itself, see [RFC2821] (www.ietf.org/rfc/rfc2821.txt).
What is This Library NOT?¶ ↑
This library does NOT provide functions to compose internet mails. You must create them by yourself. If you want better mail support, try RubyMail or TMail or search for alternatives in RubyGems.org or The Ruby Toolbox.
FYI: the official documentation on internet mail is: [RFC2822] (www.ietf.org/rfc/rfc2822.txt).
Examples¶ ↑
Sending Messages¶ ↑
You must open a connection to an SMTP server before sending messages. The first argument is the address of your SMTP server, and the second argument is the port number. Using SMTP.start with a block is the simplest way to do this. This way, the SMTP connection is closed automatically after the block is executed.
require 'net/smtp'
Net::SMTP.start('your.smtp.server', 25) do |smtp|
# Use the SMTP object smtp only in this block.
end
Replace 'your.smtp.server' with your SMTP server. Normally your system manager or internet provider supplies a server for you.
Then you can send messages.
msgstr = <<END_OF_MESSAGE
From: Your Name <[email protected]>
To: Destination Address <[email protected]>
Subject: test message
Date: Sat, 23 Jun 2001 16:26:43 +0900
Message-Id: <[email protected]>
This is a test message.
END_OF_MESSAGE
require 'net/smtp'
Net::SMTP.start('your.smtp.server', 25) do |smtp|
smtp.send_message msgstr,
'[email protected]',
'[email protected]'
end
Closing the Session¶ ↑
You MUST close the SMTP session after sending messages, by calling the finish method:
# using SMTP#finish
smtp = Net::SMTP.start('your.smtp.server', 25)
smtp.send_message msgstr, 'from@address', 'to@address'
smtp.finish
You can also use the block form of SMTP.start/SMTP#start. This closes the SMTP session automatically:
# using block form of SMTP.start
Net::SMTP.start('your.smtp.server', 25) do |smtp|
smtp.send_message msgstr, 'from@address', 'to@address'
end
I strongly recommend this scheme. This form is simpler and more robust.
HELO domain¶ ↑
In almost all situations, you must provide a third argument to SMTP.start/SMTP#start. This is the domain name which you are on (the host to send mail from). It is called the “HELO domain”. The SMTP server will judge whether it should send or reject the SMTP session by inspecting the HELO domain.
Net::SMTP.start('your.smtp.server', 25,
'mail.from.domain') { |smtp| ... }
SMTP Authentication¶ ↑
The Net::SMTP class supports three authentication schemes; PLAIN, LOGIN and CRAM MD5. (SMTP Authentication: [RFC2554]) To use SMTP authentication, pass extra arguments to SMTP.start/SMTP#start.
# PLAIN
Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain',
'Your Account', 'Your Password', :plain)
# LOGIN
Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain',
'Your Account', 'Your Password', :login)
# CRAM MD5
Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain',
'Your Account', 'Your Password', :cram_md5)
This class represents a response received by the SMTP server. Instances of this class are created by the SMTP class; they should not be directly created by the user. For more information on SMTP responses, view Section 4.2 of RFC 5321
Represents an SMTP authentication error.
Represents a fatal SMTP error (error code 5xx, except for 500)
Represents SMTP error code 420 or 450, a temporary error.
Represents an SMTP command syntax error (error code 500)
Unexpected reply code returned from server.
Command is not supported on server.
The writer adapter class
WriteTimeout, a subclass of Timeout::Error, is raised if a chunk of the response cannot be written within the write_timeout. Not raised on Windows.
The class of the singleton object nil.
Raised when memory allocation fails.
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 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.
Numeric is the class from which all higher-level numeric classes should inherit.
Numeric allows instantiation of heap-allocated objects. Other core numeric classes such as Integer are implemented as immediates, which means that each Integer is a single immutable object which is always passed by value.
a = 1
1.object_id == a.object_id #=> true
There can only ever be one instance of the integer 1, for example. Ruby ensures this by preventing instantiation. If duplication is attempted, the same instance is returned.
Integer.new(1) #=> NoMethodError: undefined method `new' for Integer:Class
1.dup #=> 1
1.object_id == 1.dup.object_id #=> true
For this reason, Numeric should be used when defining other numeric classes.
Classes which inherit from Numeric must implement coerce, which returns a two-member Array containing an object that has been coerced into an instance of the new class and self (see coerce).
Inheriting classes should also implement arithmetic operator methods (+, -, * and /) and the <=> operator (see Comparable). These methods may rely on coerce to ensure interoperability with instances of other numeric classes.
class Tally < Numeric
def initialize(string)
@string = string
end
def to_s
@string
end
def to_i
@string.size
end
def coerce(other)
[self.class.new('|' * other.to_i), self]
end
def <=>(other)
to_i <=> other.to_i
end
def +(other)
self.class.new('|' * (to_i + other.to_i))
end
def -(other)
self.class.new('|' * (to_i - other.to_i))
end
def *(other)
self.class.new('|' * (to_i * other.to_i))
end
def /(other)
self.class.new('|' * (to_i / other.to_i))
end
end
tally = Tally.new('||')
puts tally * 2 #=> "||||"
puts tally > 1 #=> true
OLEProperty helper class of Property with arguments.
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).
Raised by Timeout.timeout when the block times out.
This class is used as a return value from ObjectSpace::reachable_objects_from.
When ObjectSpace::reachable_objects_from returns an object with references to an internal object, an instance of this class is returned.
You can use the type method to check the type of the internal object.
An ObjectSpace::WeakMap object holds references to any objects, but those objects can get garbage collected.
This class is mostly used internally by WeakRef, please use lib/weakref.rb for the public interface.
The top-level class representing any ASN.1 object. When parsed by ASN1.decode, tagged values are always represented by an instance of ASN1Data.
The role of ASN1Data for parsing tagged values¶ ↑
When encoding an ASN.1 type it is inherently clear what original type (e.g. INTEGER, OCTET STRING etc.) this value has, regardless of its tagging. But opposed to the time an ASN.1 type is to be encoded, when parsing them it is not possible to deduce the “real type” of tagged values. This is why tagged values are generally parsed into ASN1Data instances, but with a different outcome for implicit and explicit tagging.
Example of a parsed implicitly tagged value¶ ↑
An implicitly 1-tagged INTEGER value will be parsed as an ASN1Data with
tag equal to 1
tag_class equal to :CONTEXT_SPECIFIC
value equal to a String that carries the raw encoding of the INTEGER.
This implies that a subsequent decoding step is required to completely decode implicitly tagged values.
Example of a parsed explicitly tagged value¶ ↑
An explicitly 1-tagged INTEGER value will be parsed as an ASN1Data with
tag equal to 1
tag_class equal to :CONTEXT_SPECIFIC
value equal to an Array with one single element, an instance of OpenSSL::ASN1::Integer, i.e. the inner element is the non-tagged primitive value, and the tagging is represented in the outer ASN1Data
Example - Decoding an implicitly tagged INTEGER¶ ↑
int = OpenSSL::ASN1::Integer.new(1, 0, :IMPLICIT) # implicit 0-tagged
seq = OpenSSL::ASN1::Sequence.new( [int] )
der = seq.to_der
asn1 = OpenSSL::ASN1.decode(der)
# pp asn1 => #<OpenSSL::ASN1::Sequence:0x87326e0
# @indefinite_length=false,
# @tag=16,
# @tag_class=:UNIVERSAL,
# @tagging=nil,
# @value=
# [#<OpenSSL::ASN1::ASN1Data:0x87326f4
# @indefinite_length=false,
# @tag=0,
# @tag_class=:CONTEXT_SPECIFIC,
# @value="\x01">]>
raw_int = asn1.value[0]
# manually rewrite tag and tag class to make it an UNIVERSAL value
raw_int.tag = OpenSSL::ASN1::INTEGER
raw_int.tag_class = :UNIVERSAL
int2 = OpenSSL::ASN1.decode(raw_int)
puts int2.value # => 1
Example - Decoding an explicitly tagged INTEGER¶ ↑
int = OpenSSL::ASN1::Integer.new(1, 0, :EXPLICIT) # explicit 0-tagged
seq = OpenSSL::ASN1::Sequence.new( [int] )
der = seq.to_der
asn1 = OpenSSL::ASN1.decode(der)
# pp asn1 => #<OpenSSL::ASN1::Sequence:0x87326e0
# @indefinite_length=false,
# @tag=16,
# @tag_class=:UNIVERSAL,
# @tagging=nil,
# @value=
# [#<OpenSSL::ASN1::ASN1Data:0x87326f4
# @indefinite_length=false,
# @tag=0,
# @tag_class=:CONTEXT_SPECIFIC,
# @value=
# [#<OpenSSL::ASN1::Integer:0x85bf308
# @indefinite_length=false,
# @tag=2,
# @tag_class=:UNIVERSAL
# @tagging=nil,
# @value=1>]>]>
int2 = asn1.value[0].value[0]
puts int2.value # => 1
Generic error class for all errors raised in ASN1 and any of the classes defined in it.
The parent class for all constructed encodings. The value attribute of a Constructive is always an Array. Attributes are the same as for ASN1Data, with the addition of tagging.
SET and SEQUENCE¶ ↑
Most constructed encodings come in the form of a SET or a SEQUENCE. These encodings are represented by one of the two sub-classes of Constructive:
OpenSSL::ASN1::Set
OpenSSL::ASN1::Sequence
Please note that tagged sequences and sets are still parsed as instances of ASN1Data. Find further details on tagged values there.
Example - constructing a SEQUENCE¶ ↑
int = OpenSSL::ASN1::Integer.new(1)
str = OpenSSL::ASN1::PrintableString.new('abc')
sequence = OpenSSL::ASN1::Sequence.new( [ int, str ] )
Example - constructing a SET¶ ↑
int = OpenSSL::ASN1::Integer.new(1)
str = OpenSSL::ASN1::PrintableString.new('abc')
set = OpenSSL::ASN1::Set.new( [ int, str ] )
Represents the primitive object id for OpenSSL::ASN1
The parent class for all primitive encodings. Attributes are the same as for ASN1Data, with the addition of tagging. Primitive values can never be encoded with indefinite length form, thus it is not possible to set the indefinite_length attribute for Primitive and its sub-classes.
Primitive sub-classes and their mapping to Ruby classes¶ ↑
OpenSSL::ASN1::EndOfContent <=> value is always nil
OpenSSL::ASN1::Boolean <=> value is true or false
OpenSSL::ASN1::Integer <=> value is an OpenSSL::BN
OpenSSL::ASN1::BitString <=> value is a String
OpenSSL::ASN1::OctetString <=> value is a String
OpenSSL::ASN1::Null <=> value is always nil
OpenSSL::ASN1::Object <=> value is a String
OpenSSL::ASN1::Enumerated <=> value is an OpenSSL::BN
OpenSSL::ASN1::UTF8String <=> value is a String
OpenSSL::ASN1::NumericString <=> value is a String
OpenSSL::ASN1::PrintableString <=> value is a String
OpenSSL::ASN1::T61String <=> value is a String
OpenSSL::ASN1::VideotexString <=> value is a String
OpenSSL::ASN1::IA5String <=> value is a String
OpenSSL::ASN1::UTCTime <=> value is a Time
OpenSSL::ASN1::GeneralizedTime <=> value is a Time
OpenSSL::ASN1::GraphicString <=> value is a String
OpenSSL::ASN1::ISO64String <=> value is a String
OpenSSL::ASN1::GeneralString <=> value is a String
OpenSSL::ASN1::UniversalString <=> value is a String
OpenSSL::ASN1::BMPString <=> value is a String
OpenSSL::ASN1::BitString¶ ↑
Additional attributes¶ ↑
unused_bits: if the underlying BIT STRING's length is a multiple of 8 then unused_bits is 0. Otherwise unused_bits indicates the number of bits that are to be ignored in the final octet of the BitString's value.
OpenSSL::ASN1::ObjectId¶ ↑
NOTE: While OpenSSL::ASN1::ObjectId.new will allocate a new ObjectId, it is not typically allocated this way, but rather that are received from parsed ASN1 encodings.
Additional attributes¶ ↑
sn: the short name as defined in <openssl/objects.h>.
ln: the long name as defined in <openssl/objects.h>.
oid: the object identifier as a String, e.g. “1.2.3.4.5”
short_name: alias for sn.
long_name: alias for ln.
Examples¶ ↑
With the Exception of OpenSSL::ASN1::EndOfContent, each Primitive class constructor takes at least one parameter, the value.
Creating EndOfContent¶ ↑
eoc = OpenSSL::ASN1::EndOfContent.new
Creating any other Primitive¶ ↑
prim = <class>.new(value) # <class> being one of the sub-classes except EndOfContent
prim_zero_tagged_implicit = <class>.new(value, 0, :IMPLICIT)
prim_zero_tagged_explicit = <class>.new(value, 0, :EXPLICIT)
Generic Error for all of OpenSSL::BN (big num)
Provides symmetric algorithms for encryption and decryption. The algorithms that are available depend on the particular version of OpenSSL that is installed.
Listing all supported algorithms¶ ↑
A list of supported algorithms can be obtained by
puts OpenSSL::Cipher.ciphers
Instantiating a Cipher¶ ↑
There are several ways to create a Cipher instance. Generally, a Cipher algorithm is categorized by its name, the key length in bits and the cipher mode to be used. The most generic way to create a Cipher is the following
cipher = OpenSSL::Cipher.new('<name>-<key length>-<mode>')
That is, a string consisting of the hyphenated concatenation of the individual components name, key length and mode. Either all uppercase or all lowercase strings may be used, for example:
cipher = OpenSSL::Cipher.new('AES-128-CBC')
For each algorithm supported, there is a class defined under the Cipher class that goes by the name of the cipher, e.g. to obtain an instance of AES, you could also use
# these are equivalent
cipher = OpenSSL::Cipher::AES.new(128, :CBC)
cipher = OpenSSL::Cipher::AES.new(128, 'CBC')
cipher = OpenSSL::Cipher::AES.new('128-CBC')
Finally, due to its wide-spread use, there are also extra classes defined for the different key sizes of AES
cipher = OpenSSL::Cipher::AES128.new(:CBC)
cipher = OpenSSL::Cipher::AES192.new(:CBC)
cipher = OpenSSL::Cipher::AES256.new(:CBC)
Choosing either encryption or decryption mode¶ ↑
Encryption and decryption are often very similar operations for symmetric algorithms, this is reflected by not having to choose different classes for either operation, both can be done using the same class. Still, after obtaining a Cipher instance, we need to tell the instance what it is that we intend to do with it, so we need to call either
cipher.encrypt
or
cipher.decrypt
on the Cipher instance. This should be the first call after creating the instance, otherwise configuration that has already been set could get lost in the process.
Choosing a key¶ ↑
Symmetric encryption requires a key that is the same for the encrypting and for the decrypting party and after initial key establishment should be kept as private information. There are a lot of ways to create insecure keys, the most notable is to simply take a password as the key without processing the password further. A simple and secure way to create a key for a particular Cipher is
cipher = OpenSSL::AES256.new(:CFB)
cipher.encrypt
key = cipher.random_key # also sets the generated key on the Cipher
If you absolutely need to use passwords as encryption keys, you should use Password-Based Key Derivation Function 2 (PBKDF2) by generating the key with the help of the functionality provided by OpenSSL::PKCS5.pbkdf2_hmac_sha1 or OpenSSL::PKCS5.pbkdf2_hmac.
Although there is Cipher#pkcs5_keyivgen, its use is deprecated and it should only be used in legacy applications because it does not use the newer PKCS#5 v2 algorithms.
Choosing an IV¶ ↑
The cipher modes CBC, CFB, OFB and CTR all need an “initialization vector”, or short, IV. ECB mode is the only mode that does not require an IV, but there is almost no legitimate use case for this mode because of the fact that it does not sufficiently hide plaintext patterns. Therefore
You should never use ECB mode unless you are absolutely sure that you absolutely need it
Because of this, you will end up with a mode that explicitly requires an IV in any case. Although the IV can be seen as public information, i.e. it may be transmitted in public once generated, it should still stay unpredictable to prevent certain kinds of attacks. Therefore, ideally
Always create a secure random IV for every encryption of your Cipher
A new, random IV should be created for every encryption of data. Think of the IV as a nonce (number used once) - it's public but random and unpredictable. A secure random IV can be created as follows
cipher = ...
cipher.encrypt
key = cipher.random_key
iv = cipher.random_iv # also sets the generated IV on the Cipher
Although the key is generally a random value, too, it is a bad choice as an IV. There are elaborate ways how an attacker can take advantage of such an IV. As a general rule of thumb, exposing the key directly or indirectly should be avoided at all cost and exceptions only be made with good reason.
Calling Cipher#final¶ ↑
ECB (which should not be used) and CBC are both block-based modes. This means that unlike for the other streaming-based modes, they operate on fixed-size blocks of data, and therefore they require a “finalization” step to produce or correctly decrypt the last block of data by appropriately handling some form of padding. Therefore it is essential to add the output of OpenSSL::Cipher#final to your encryption/decryption buffer or you will end up with decryption errors or truncated data.
Although this is not really necessary for streaming-mode ciphers, it is still recommended to apply the same pattern of adding the output of Cipher#final there as well - it also enables you to switch between modes more easily in the future.
Encrypting and decrypting some data¶ ↑
data = "Very, very confidential data"
cipher = OpenSSL::Cipher::AES.new(128, :CBC)
cipher.encrypt
key = cipher.random_key
iv = cipher.random_iv
encrypted = cipher.update(data) + cipher.final
...
decipher = OpenSSL::Cipher::AES.new(128, :CBC)
decipher.decrypt
decipher.key = key
decipher.iv = iv
plain = decipher.update(encrypted) + decipher.final
puts data == plain #=> true
Authenticated Encryption and Associated Data (AEAD)¶ ↑
If the OpenSSL version used supports it, an Authenticated Encryption mode (such as GCM or CCM) should always be preferred over any unauthenticated mode. Currently, OpenSSL supports AE only in combination with Associated Data (AEAD) where additional associated data is included in the encryption process to compute a tag at the end of the encryption. This tag will also be used in the decryption process and by verifying its validity, the authenticity of a given ciphertext is established.
This is superior to unauthenticated modes in that it allows to detect if somebody effectively changed the ciphertext after it had been encrypted. This prevents malicious modifications of the ciphertext that could otherwise be exploited to modify ciphertexts in ways beneficial to potential attackers.
An associated data is used where there is additional information, such as headers or some metadata, that must be also authenticated but not necessarily need to be encrypted. If no associated data is needed for encryption and later decryption, the OpenSSL library still requires a value to be set - “” may be used in case none is available.
An example using the GCM (Galois/Counter Mode). You have 16 bytes key, 12 bytes (96 bits) nonce and the associated data auth_data. Be sure not to reuse the key and nonce pair. Reusing an nonce ruins the security guarantees of GCM mode.
cipher = OpenSSL::Cipher::AES.new(128, :GCM).encrypt
cipher.key = key
cipher.iv = nonce
cipher.auth_data = auth_data
encrypted = cipher.update(data) + cipher.final
tag = cipher.auth_tag # produces 16 bytes tag by default
Now you are the receiver. You know the key and have received nonce, auth_data, encrypted and tag through an untrusted network. Note that GCM accepts an arbitrary length tag between 1 and 16 bytes. You may additionally need to check that the received tag has the correct length, or you allow attackers to forge a valid single byte tag for the tampered ciphertext with a probability of 1/256.
raise "tag is truncated!" unless tag.bytesize == 16
decipher = OpenSSL::Cipher::AES.new(128, :GCM).decrypt
decipher.key = key
decipher.iv = nonce
decipher.auth_tag = tag
decipher.auth_data = auth_data
decrypted = decipher.update(encrypted) + decipher.final
puts data == decrypted #=> true
Deprecated.
This class is only provided for backwards compatibility. Use OpenSSL::Cipher.
OpenSSL::Config¶ ↑
Configuration for the openssl library.
Many system's installation of openssl library will depend on your system configuration. See the value of OpenSSL::Config::DEFAULT_CONFIG_FILE for the location of the file for your host.
See also www.openssl.org/docs/apps/config.html
General error for openssl library configuration files. Including formatting, parsing errors, etc.
OpenSSL::Digest allows you to compute message digests (sometimes interchangeably called “hashes”) of arbitrary data that are cryptographically secure, i.e. a Digest implements a secure one-way function.
One-way functions offer some useful properties. E.g. given two distinct inputs the probability that both yield the same output is highly unlikely. Combined with the fact that every message digest algorithm has a fixed-length output of just a few bytes, digests are often used to create unique identifiers for arbitrary data. A common example is the creation of a unique id for binary documents that are stored in a database.
Another useful characteristic of one-way functions (and thus the name) is that given a digest there is no indication about the original data that produced it, i.e. the only way to identify the original input is to “brute-force” through every possible combination of inputs.
These characteristics make one-way functions also ideal companions for public key signature algorithms: instead of signing an entire document, first a hash of the document is produced with a considerably faster message digest algorithm and only the few bytes of its output need to be signed using the slower public key algorithm. To validate the integrity of a signed document, it suffices to re-compute the hash and verify that it is equal to that in the signature.
Among the supported message digest algorithms are:
SHA, SHA1, SHA224, SHA256, SHA384 and SHA512
MD2, MD4, MDC2 and MD5
RIPEMD160
DSS, DSS1 (Pseudo algorithms to be used for DSA signatures. DSS is equal to SHA and DSS1 is equal to SHA1)
For each of these algorithms, there is a sub-class of Digest that can be instantiated as simply as e.g.
digest = OpenSSL::Digest::SHA1.new
Mapping between Digest class and sn/ln¶ ↑
The sn (short names) and ln (long names) are defined in <openssl/object.h> and <openssl/obj_mac.h>. They are textual representations of ASN.1 OBJECT IDENTIFIERs. Each supported digest algorithm has an OBJECT IDENTIFIER associated to it and those again have short/long names assigned to them. E.g. the OBJECT IDENTIFIER for SHA-1 is 1.3.14.3.2.26 and its sn is “SHA1” and its ln is “sha1”.
MD2¶ ↑
sn: MD2
ln: md2
MD4¶ ↑
sn: MD4
ln: md4
MD5¶ ↑
sn: MD5
ln: md5
SHA¶ ↑
sn: SHA
ln: SHA
SHA-1¶ ↑
sn: SHA1
ln: sha1
SHA-224¶ ↑
sn: SHA224
ln: sha224
SHA-256¶ ↑
sn: SHA256
ln: sha256
SHA-384¶ ↑
sn: SHA384
ln: sha384
SHA-512¶ ↑
sn: SHA512
ln: sha512
“Breaking” a message digest algorithm means defying its one-way function characteristics, i.e. producing a collision or finding a way to get to the original data by means that are more efficient than brute-forcing etc. Most of the supported digest algorithms can be considered broken in this sense, even the very popular MD5 and SHA1 algorithms. Should security be your highest concern, then you should probably rely on SHA224, SHA256, SHA384 or SHA512.
Hashing a file¶ ↑
data = File.read('document')
sha256 = OpenSSL::Digest::SHA256.new
digest = sha256.digest(data)
Hashing several pieces of data at once¶ ↑
data1 = File.read('file1')
data2 = File.read('file2')
data3 = File.read('file3')
sha256 = OpenSSL::Digest::SHA256.new
sha256 << data1
sha256 << data2
sha256 << data3
digest = sha256.digest
Reuse a Digest instance¶ ↑
data1 = File.read('file1')
sha256 = OpenSSL::Digest::SHA256.new
digest1 = sha256.digest(data1)
data2 = File.read('file2')
sha256.reset
digest2 = sha256.digest(data2)
Generic Exception class that is raised if an error occurs during a Digest operation.
This class is the access to openssl's ENGINE cryptographic module implementation.
See also, www.openssl.org/docs/crypto/engine.html
This is the generic exception for OpenSSL::Engine related errors
OpenSSL::HMAC allows computing Hash-based Message Authentication Code (HMAC). It is a type of message authentication code (MAC) involving a hash function in combination with a key. HMAC can be used to verify the integrity of a message as well as the authenticity.
OpenSSL::HMAC has a similar interface to OpenSSL::Digest.
HMAC-SHA256 using one-shot interface¶ ↑
key = "key"
data = "message-to-be-authenticated"
mac = OpenSSL::HMAC.hexdigest("SHA256", key, data)
#=> "cddb0db23f469c8bf072b21fd837149bd6ace9ab771cceef14c9e517cc93282e"
HMAC-SHA256 using incremental interface¶ ↑
data1 = File.read("file1")
data2 = File.read("file2")
key = "key"
digest = OpenSSL::Digest::SHA256.new
hmac = OpenSSL::HMAC.new(key, digest)
hmac << data1
hmac << data2
mac = hmac.digest
Document-class: OpenSSL::HMAC
OpenSSL::HMAC allows computing Hash-based Message Authentication Code (HMAC). It is a type of message authentication code (MAC) involving a hash function in combination with a key. HMAC can be used to verify the integrity of a message as well as the authenticity.
OpenSSL::HMAC has a similar interface to OpenSSL::Digest.
HMAC-SHA256 using one-shot interface¶ ↑
key = "key"
data = "message-to-be-authenticated"
mac = OpenSSL::HMAC.hexdigest("SHA256", key, data)
#=> "cddb0db23f469c8bf072b21fd837149bd6ace9ab771cceef14c9e517cc93282e"
HMAC-SHA256 using incremental interface¶ ↑
data1 = File.read("file1")
data2 = File.read("file2")
key = "key"
digest = OpenSSL::Digest::SHA256.new
hmac = OpenSSL::HMAC.new(key, digest)
hmac << data1
hmac << data2
mac = hmac.digest
Generic exception class raised if an error occurs in OpenSSL::KDF module.
A Simple Public Key Infrastructure implementation (pronounced “spooky”). The structure is defined as
PublicKeyAndChallenge ::= SEQUENCE {
spki SubjectPublicKeyInfo,
challenge IA5STRING
}
SignedPublicKeyAndChallenge ::= SEQUENCE {
publicKeyAndChallenge PublicKeyAndChallenge,
signatureAlgorithm AlgorithmIdentifier,
signature BIT STRING
}
where the definitions of SubjectPublicKeyInfo and AlgorithmIdentifier can be found in RFC5280. SPKI is typically used in browsers for generating a public/private key pair and a subsequent certificate request, using the HTML <keygen> element.
Examples¶ ↑
Creating an SPKI¶ ↑
key = OpenSSL::PKey::RSA.new 2048
spki = OpenSSL::Netscape::SPKI.new
spki.challenge = "RandomChallenge"
spki.public_key = key.public_key
spki.sign(key, OpenSSL::Digest::SHA256.new)
#send a request containing this to a server generating a certificate
Verifying an SPKI request¶ ↑
request = #...
spki = OpenSSL::Netscape::SPKI.new request
unless spki.verify(spki.public_key)
# signature is invalid
end
#proceed
Generic Exception class that is raised if an error occurs during an operation on an instance of OpenSSL::Netscape::SPKI.
An OpenSSL::OCSP::BasicResponse contains the status of a certificate check which is created from an OpenSSL::OCSP::Request. A BasicResponse is more detailed than a Response.
An OpenSSL::OCSP::CertificateId identifies a certificate to the CA so that a status check can be performed.
OCSP error class.
An OpenSSL::OCSP::Request contains the certificate information for determining if a certificate has been revoked or not. A Request can be created for a certificate or from a DER-encoded request created elsewhere.
An OpenSSL::OCSP::Response contains the status of a certificate check which is created from an OpenSSL::OCSP::Request.
An OpenSSL::OCSP::SingleResponse represents an OCSP SingleResponse structure, which contains the basic information of the status of the certificate.
Generic error, common for all classes under OpenSSL module
Defines a file format commonly used to store private keys with accompanying public key certificates, protected with a password-based symmetric key.
An implementation of the Diffie-Hellman key exchange protocol based on discrete logarithms in finite fields, the same basis that DSA is built on.
Accessor methods for the Diffie-Hellman parameters¶ ↑
DH#p
The prime (an OpenSSL::BN) of the Diffie-Hellman parameters.
DH#g
The generator (an OpenSSL::BN) g of the Diffie-Hellman parameters.
DH#pub_key
The per-session public key (an OpenSSL::BN) matching the private key. This needs to be passed to DH#compute_key.
DH#priv_key
The per-session private key, an OpenSSL::BN.
Example of a key exchange¶ ↑
dh1 = OpenSSL::PKey::DH.new(2048)
der = dh1.public_key.to_der #you may send this publicly to the participating party
dh2 = OpenSSL::PKey::DH.new(der)
dh2.generate_key! #generate the per-session key pair
symm_key1 = dh1.compute_key(dh2.pub_key)
symm_key2 = dh2.compute_key(dh1.pub_key)
puts symm_key1 == symm_key2 # => true
Generic exception that is raised if an operation on a DH PKey fails unexpectedly or in case an instantiation of an instance of DH fails due to non-conformant input data.
DSA, the Digital Signature Algorithm, is specified in NIST's FIPS 186-3. It is an asymmetric public key algorithm that may be used similar to e.g. RSA.
Generic exception that is raised if an operation on a DSA PKey fails unexpectedly or in case an instantiation of an instance of DSA fails due to non-conformant input data.
OpenSSL::PKey::EC provides access to Elliptic Curve Digital Signature Algorithm (ECDSA) and Elliptic Curve Diffie-Hellman (ECDH).
Key exchange¶ ↑
ec1 = OpenSSL::PKey::EC.generate("prime256v1")
ec2 = OpenSSL::PKey::EC.generate("prime256v1")
# ec1 and ec2 have own private key respectively
shared_key1 = ec1.dh_compute_key(ec2.public_key)
shared_key2 = ec2.dh_compute_key(ec1.public_key)
p shared_key1 == shared_key2 #=> true
An abstract class that bundles signature creation (PKey#sign) and validation (PKey#verify) that is common to all implementations except OpenSSL::PKey::DH
OpenSSL::PKey::RSA
OpenSSL::PKey::DSA
OpenSSL::PKey::EC
Raised when errors occur during PKey#sign or PKey#verify.
RSA is an asymmetric public key algorithm that has been formalized in RFC 3447. It is in widespread use in public key infrastructures (PKI) where certificates (cf. OpenSSL::X509::Certificate) often are issued on the basis of a public/private RSA key pair. RSA is used in a wide field of applications such as secure (symmetric) key exchange, e.g. when establishing a secure TLS/SSL connection. It is also used in various digital signature schemes.
Generic exception that is raised if an operation on an RSA PKey fails unexpectedly or in case an instantiation of an instance of RSA fails due to non-conformant input data.
An SSLContext is used to set various options regarding certificates, algorithms, verification, session caching, etc. The SSLContext is used to create an SSLSocket.
All attributes must be set before creating an SSLSocket as the SSLContext will be frozen afterward.
Generic error class raised by SSLSocket and SSLContext.
SSLServer represents a TCP/IP server socket with Secure Sockets Layer.
Implementation of an X.509 certificate as specified in RFC 5280. Provides access to a certificate's attributes and allows certificates to be read from a string, but also supports the creation of new certificates from scratch.
Reading a certificate from a file¶ ↑
Certificate is capable of handling DER-encoded certificates and certificates encoded in OpenSSL's PEM format.
raw = File.read "cert.cer" # DER- or PEM-encoded
certificate = OpenSSL::X509::Certificate.new raw
Saving a certificate to a file¶ ↑
A certificate may be encoded in DER format
cert = ...
File.open("cert.cer", "wb") { |f| f.print cert.to_der }
or in PEM format
cert = ...
File.open("cert.pem", "wb") { |f| f.print cert.to_pem }
X.509 certificates are associated with a private/public key pair, typically a RSA, DSA or ECC key (see also OpenSSL::PKey::RSA, OpenSSL::PKey::DSA and OpenSSL::PKey::EC), the public key itself is stored within the certificate and can be accessed in form of an OpenSSL::PKey. Certificates are typically used to be able to associate some form of identity with a key pair, for example web servers serving pages over HTTPs use certificates to authenticate themselves to the user.
The public key infrastructure (PKI) model relies on trusted certificate authorities (“root CAs”) that issue these certificates, so that end users need to base their trust just on a selected few authorities that themselves again vouch for subordinate CAs issuing their certificates to end users.
The OpenSSL::X509 module provides the tools to set up an independent PKI, similar to scenarios where the 'openssl' command line tool is used for issuing certificates in a private PKI.
Creating a root CA certificate and an end-entity certificate¶ ↑
First, we need to create a “self-signed” root certificate. To do so, we need to generate a key first. Please note that the choice of “1” as a serial number is considered a security flaw for real certificates. Secure choices are integers in the two-digit byte range and ideally not sequential but secure random numbers, steps omitted here to keep the example concise.
root_key = OpenSSL::PKey::RSA.new 2048 # the CA's public/private key
root_ca = OpenSSL::X509::Certificate.new
root_ca.version = 2 # cf. RFC 5280 - to make it a "v3" certificate
root_ca.serial = 1
root_ca.subject = OpenSSL::X509::Name.parse "/DC=org/DC=ruby-lang/CN=Ruby CA"
root_ca.issuer = root_ca.subject # root CA's are "self-signed"
root_ca.public_key = root_key.public_key
root_ca.not_before = Time.now
root_ca.not_after = root_ca.not_before + 2 * 365 * 24 * 60 * 60 # 2 years validity
ef = OpenSSL::X509::ExtensionFactory.new
ef.subject_certificate = root_ca
ef.issuer_certificate = root_ca
root_ca.add_extension(ef.create_extension("basicConstraints","CA:TRUE",true))
root_ca.add_extension(ef.create_extension("keyUsage","keyCertSign, cRLSign", true))
root_ca.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
root_ca.add_extension(ef.create_extension("authorityKeyIdentifier","keyid:always",false))
root_ca.sign(root_key, OpenSSL::Digest::SHA256.new)
The next step is to create the end-entity certificate using the root CA certificate.
key = OpenSSL::PKey::RSA.new 2048
cert = OpenSSL::X509::Certificate.new
cert.version = 2
cert.serial = 2
cert.subject = OpenSSL::X509::Name.parse "/DC=org/DC=ruby-lang/CN=Ruby certificate"
cert.issuer = root_ca.subject # root CA is the issuer
cert.public_key = key.public_key
cert.not_before = Time.now
cert.not_after = cert.not_before + 1 * 365 * 24 * 60 * 60 # 1 years validity
ef = OpenSSL::X509::ExtensionFactory.new
ef.subject_certificate = cert
ef.issuer_certificate = root_ca
cert.add_extension(ef.create_extension("keyUsage","digitalSignature", true))
cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
cert.sign(root_key, OpenSSL::Digest::SHA256.new)
An X.509 name represents a hostname, email address or other entity associated with a public key.
You can create a Name by parsing a distinguished name String or by supplying the distinguished name as an Array.
name = OpenSSL::X509::Name.parse 'CN=nobody/DC=example'
name = OpenSSL::X509::Name.new [['CN', 'nobody'], ['DC', 'example']]
The X509 certificate store holds trusted CA certificates used to verify peer certificates.
The easiest way to create a useful certificate store is:
cert_store = OpenSSL::X509::Store.new
cert_store.set_default_paths
This will use your system's built-in certificates.
If your system does not have a default set of certificates you can obtain a set extracted from Mozilla CA certificate store by cURL maintainers here: curl.haxx.se/docs/caextract.html (You may wish to use the firefox-db2pem.sh script to extract the certificates from a local install to avoid man-in-the-middle attacks.)
After downloading or generating a cacert.pem from the above link you can create a certificate store from the pem file like this:
cert_store = OpenSSL::X509::Store.new
cert_store.add_file 'cacert.pem'
The certificate store can be used with an SSLSocket like this:
ssl_context = OpenSSL::SSL::SSLContext.new
ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
ssl_context.cert_store = cert_store
tcp_socket = TCPSocket.open 'example.com', 443
ssl_socket = OpenSSL::SSL::SSLSocket.new tcp_socket, ssl_context
A StoreContext is used while validating a single certificate and holds the status involved.
An OpenStruct is a data structure, similar to a Hash, that allows the definition of arbitrary attributes with their accompanying values. This is accomplished by using Ruby's metaprogramming to define methods on the class itself.
Examples¶ ↑
require "ostruct"
person = OpenStruct.new
person.name = "John Smith"
person.age = 70
person.name # => "John Smith"
person.age # => 70
person.address # => nil
An OpenStruct employs a Hash internally to store the attributes and values and can even be initialized with one:
australia = OpenStruct.new(:country => "Australia", :capital => "Canberra")
# => #<OpenStruct country="Australia", capital="Canberra">
Hash keys with spaces or characters that could normally not be used for method calls (e.g. ()[]*) will not be immediately available on the OpenStruct object as a method for retrieval or assignment, but can still be reached through the Object#send method.
measurements = OpenStruct.new("length (in inches)" => 24)
measurements.send("length (in inches)") # => 24
message = OpenStruct.new(:queued? => true)
message.queued? # => true
message.send("queued?=", false)
message.queued? # => false
Removing the presence of an attribute requires the execution of the delete_field method as setting the property value to nil will not remove the attribute.
first_pet = OpenStruct.new(:name => "Rowdy", :owner => "John Smith")
second_pet = OpenStruct.new(:name => "Rowdy")
first_pet.owner = nil
first_pet # => #<OpenStruct name="Rowdy", owner=nil>
first_pet == second_pet # => false
first_pet.delete_field(:owner)
first_pet # => #<OpenStruct name="Rowdy">
first_pet == second_pet # => true
Implementation¶ ↑
An OpenStruct utilizes Ruby's method lookup structure to find and define the necessary methods for properties. This is accomplished through the methods method_missing and define_singleton_method.
This should be a consideration if there is a concern about the performance of the objects that are created, as there is much more overhead in the setting of these properties compared to using a Hash or a Struct.
Raised on redirection, only occurs when redirect option for HTTP is false.
OptionParser¶ ↑
Introduction¶ ↑
OptionParser is a class for command-line option analysis. It is much more advanced, yet also easier to use, than GetoptLong, and is a more Ruby-oriented solution.
Features¶ ↑
The argument specification and the code to handle it are written in the same place.
It can output an option summary; you don't need to maintain this string separately.
Optional and mandatory arguments are specified very gracefully.
Arguments can be automatically converted to a specified class.
Arguments can be restricted to a certain set.
All of these features are demonstrated in the examples below. See make_switch for full documentation.
Minimal example¶ ↑
require 'optparse'
options = {}
OptionParser.new do |opts|
opts.banner = "Usage: example.rb [options]"
opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
options[:verbose] = v
end
end.parse!
p options
p ARGV
Generating Help¶ ↑
OptionParser can be used to automatically generate help for the commands you write:
require 'optparse'
Options = Struct.new(:name)
class Parser
def self.parse(options)
args = Options.new("world")
opt_parser = OptionParser.new do |opts|
opts.banner = "Usage: example.rb [options]"
opts.on("-nNAME", "--name=NAME", "Name to say hello to") do |n|
args.name = n
end
opts.on("-h", "--help", "Prints this help") do
puts opts
exit
end
end
opt_parser.parse!(options)
return args
end
end
options = Parser.parse %w[--help]
#=>
# Usage: example.rb [options]
# -n, --name=NAME Name to say hello to
# -h, --help Prints this help
Required Arguments¶ ↑
For options that require an argument, option specification strings may include an option name in all caps. If an option is used without the required argument, an exception will be raised.
require 'optparse'
options = {}
OptionParser.new do |parser|
parser.on("-r", "--require LIBRARY",
"Require the LIBRARY before executing your script") do |lib|
puts "You required #{lib}!"
end
end.parse!
Used:
$ ruby optparse-test.rb -r
optparse-test.rb:9:in `<main>': missing argument: -r (OptionParser::MissingArgument)
$ ruby optparse-test.rb -r my-library
You required my-library!
Type Coercion¶ ↑
OptionParser supports the ability to coerce command line arguments into objects for us.
OptionParser comes with a few ready-to-use kinds of type coercion. They are:
Date – Anything accepted by Date.parse
DateTime – Anything accepted by DateTime.parse
Time – Anything accepted by Time.httpdate or Time.parse
URI – Anything accepted by URI.parse
Shellwords – Anything accepted by Shellwords.shellwords
String – Any non-empty string
Integer – Any integer. Will convert octal. (e.g. 124, -3, 040)
Float – Any float. (e.g. 10, 3.14, -100E+13)
Numeric – Any integer, float, or rational (1, 3.4, 1/3)
DecimalInteger – Like Integer, but no octal format.
OctalInteger – Like Integer, but no decimal format.
DecimalNumeric – Decimal integer or float.
TrueClass – Accepts '+, yes, true, -, no, false' and defaults as true
FalseClass – Same as TrueClass, but defaults to false
Array – Strings separated by ',' (e.g. 1,2,3)
Regexp – Regular expressions. Also includes options.
We can also add our own coercions, which we will cover soon.
Using Built-in Conversions¶ ↑
As an example, the built-in Time conversion is used. The other built-in conversions behave in the same way. OptionParser will attempt to parse the argument as a Time. If it succeeds, that time will be passed to the handler block. Otherwise, an exception will be raised.
require 'optparse'
require 'optparse/time'
OptionParser.new do |parser|
parser.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time|
p time
end
end.parse!
Used:
$ ruby optparse-test.rb -t nonsense
... invalid argument: -t nonsense (OptionParser::InvalidArgument)
$ ruby optparse-test.rb -t 10-11-12
2010-11-12 00:00:00 -0500
$ ruby optparse-test.rb -t 9:30
2014-08-13 09:30:00 -0400
Creating Custom Conversions¶ ↑
The accept method on OptionParser may be used to create converters. It specifies which conversion block to call whenever a class is specified. The example below uses it to fetch a User object before the on handler receives it.
require 'optparse'
User = Struct.new(:id, :name)
def find_user id
not_found = ->{ raise "No User Found for id #{id}" }
[ User.new(1, "Sam"),
User.new(2, "Gandalf") ].find(not_found) do |u|
u.id == id
end
end
op = OptionParser.new
op.accept(User) do |user_id|
find_user user_id.to_i
end
op.on("--user ID", User) do |user|
puts user
end
op.parse!
Used:
$ ruby optparse-test.rb --user 1
#<struct User id=1, name="Sam">
$ ruby optparse-test.rb --user 2
#<struct User id=2, name="Gandalf">
$ ruby optparse-test.rb --user 3
optparse-test.rb:15:in `block in find_user': No User Found for id 3 (RuntimeError)
Store options to a Hash¶ ↑
The into option of order, parse and so on methods stores command line options into a Hash.
require 'optparse'
params = {}
OptionParser.new do |opts|
opts.on('-a')
opts.on('-b NUM', Integer)
opts.on('-v', '--verbose')
end.parse!(into: params)
p params
Used:
$ ruby optparse-test.rb -a
{:a=>true}
$ ruby optparse-test.rb -a -v
{:a=>true, :verbose=>true}
$ ruby optparse-test.rb -a -b 100
{:a=>true, :b=>100}
Complete example¶ ↑
The following example is a complete Ruby program. You can run it and see the effect of specifying various options. This is probably the best way to learn the features of optparse.
require 'optparse'
require 'optparse/time'
require 'ostruct'
require 'pp'
class OptparseExample
Version = '1.0.0'
CODES = %w[iso-2022-jp shift_jis euc-jp utf8 binary]
CODE_ALIASES = { "jis" => "iso-2022-jp", "sjis" => "shift_jis" }
class ScriptOptions
attr_accessor :library, :inplace, :encoding, :transfer_type,
:verbose, :extension, :delay, :time, :record_separator,
:list
def initialize
self.library = []
self.inplace = false
self.encoding = "utf8"
self.transfer_type = :auto
self.verbose = false
end
def define_options(parser)
parser.banner = "Usage: example.rb [options]"
parser.separator ""
parser.separator "Specific options:"
# add additional options
perform_inplace_option(parser)
delay_execution_option(parser)
execute_at_time_option(parser)
specify_record_separator_option(parser)
list_example_option(parser)
specify_encoding_option(parser)
optional_option_argument_with_keyword_completion_option(parser)
boolean_verbose_option(parser)
parser.separator ""
parser.separator "Common options:"
# No argument, shows at tail. This will print an options summary.
# Try it and see!
parser.on_tail("-h", "--help", "Show this message") do
puts parser
exit
end
# Another typical switch to print the version.
parser.on_tail("--version", "Show version") do
puts Version
exit
end
end
def perform_inplace_option(parser)
# Specifies an optional option argument
parser.on("-i", "--inplace [EXTENSION]",
"Edit ARGV files in place",
"(make backup if EXTENSION supplied)") do |ext|
self.inplace = true
self.extension = ext || ''
self.extension.sub!(/\A\.?(?=.)/, ".") # Ensure extension begins with dot.
end
end
def delay_execution_option(parser)
# Cast 'delay' argument to a Float.
parser.on("--delay N", Float, "Delay N seconds before executing") do |n|
self.delay = n
end
end
def execute_at_time_option(parser)
# Cast 'time' argument to a Time object.
parser.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time|
self.time = time
end
end
def specify_record_separator_option(parser)
# Cast to octal integer.
parser.on("-F", "--irs [OCTAL]", OptionParser::OctalInteger,
"Specify record separator (default \\0)") do |rs|
self.record_separator = rs
end
end
def list_example_option(parser)
# List of arguments.
parser.on("--list x,y,z", Array, "Example 'list' of arguments") do |list|
self.list = list
end
end
def specify_encoding_option(parser)
# Keyword completion. We are specifying a specific set of arguments (CODES
# and CODE_ALIASES - notice the latter is a Hash), and the user may provide
# the shortest unambiguous text.
code_list = (CODE_ALIASES.keys + CODES).join(', ')
parser.on("--code CODE", CODES, CODE_ALIASES, "Select encoding",
"(#{code_list})") do |encoding|
self.encoding = encoding
end
end
def optional_option_argument_with_keyword_completion_option(parser)
# Optional '--type' option argument with keyword completion.
parser.on("--type [TYPE]", [:text, :binary, :auto],
"Select transfer type (text, binary, auto)") do |t|
self.transfer_type = t
end
end
def boolean_verbose_option(parser)
# Boolean switch.
parser.on("-v", "--[no-]verbose", "Run verbosely") do |v|
self.verbose = v
end
end
end
#
# Return a structure describing the options.
#
def parse(args)
# The options specified on the command line will be collected in
# *options*.
@options = ScriptOptions.new
@args = OptionParser.new do |parser|
@options.define_options(parser)
parser.parse!(args)
end
@options
end
attr_reader :parser, :options
end # class OptparseExample
example = OptparseExample.new
options = example.parse(ARGV)
pp options # example.options
pp ARGV
Shell Completion¶ ↑
For modern shells (e.g. bash, zsh, etc.), you can use shell completion for command line options.
Further documentation¶ ↑
The above examples should be enough to learn how to use this class. If you have any questions, file a ticket at bugs.ruby-lang.org.
Raises when the given argument word can't be completed uniquely.
Raises when ambiguously completable string is encountered.
Hash with completion search feature. See OptionParser::Completion.
Raises when the given argument does not match required format.
Raises when switch is undefined.
Simple option list providing mapping from short and/or long option string to OptionParser::Switch and mapping from acceptable argument to matching pattern and converter pair. Also provides summary feature.
Raises when a switch with mandatory argument has no argument.
Raises when there is an argument for a switch which takes no argument.
Map from option/keyword string to object with completion.
Base class of exceptions from OptionParser.
Individual switch class. Not important to the user.
Defined within Switch are several Switch-derived classes: NoArgument, RequiredArgument, etc.
Switch that takes no arguments.
Switch that can omit argument.
Switch that takes an argument, which does not begin with '-'.
Switch that takes an argument.
A pretty-printer for Ruby objects.
What PP Does¶ ↑
Standard output by p returns this:
#<PP:0x81fedf0 @genspace=#<Proc:0x81feda0>, @group_queue=#<PrettyPrint::GroupQueue:0x81fed3c @queue=[[#<PrettyPrint::Group:0x81fed78 @breakables=[], @depth=0, @break=false>], []]>, @buffer=[], @newline="\n", @group_stack=[#<PrettyPrint::Group:0x81fed78 @breakables=[], @depth=0, @break=false>], @buffer_width=0, @indent=0, @maxwidth=79, @output_width=2, @output=#<IO:0x8114ee4>>
Pretty-printed output returns this:
#<PP:0x81fedf0
@buffer=[],
@buffer_width=0,
@genspace=#<Proc:0x81feda0>,
@group_queue=
#<PrettyPrint::GroupQueue:0x81fed3c
@queue=
[[#<PrettyPrint::Group:0x81fed78 @break=false, @breakables=[], @depth=0>],
[]]>,
@group_stack=
[#<PrettyPrint::Group:0x81fed78 @break=false, @breakables=[], @depth=0>],
@indent=0,
@maxwidth=79,
@newline="\n",
@output=#<IO:0x8114ee4>,
@output_width=2>
Usage¶ ↑
pp(obj) #=> obj
pp obj #=> obj
pp(obj1, obj2, ...) #=> [obj1, obj2, ...]
pp() #=> nil
Output obj(s) to $> in pretty printed format.
It returns obj(s).
Output Customization¶ ↑
To define a customized pretty printing function for your classes, redefine method #pretty_print(pp) in the class.
#pretty_print takes the pp argument, which is an instance of the PP class. The method uses text, breakable, nest, group and pp to print the object.
Pretty-Print JSON¶ ↑
To pretty-print JSON refer to JSON#pretty_generate.
Author¶ ↑
Tanaka Akira <[email protected]>
PStore implements a file based persistence mechanism based on a Hash. User code can store hierarchies of Ruby objects (values) into the data store file by name (keys). An object hierarchy may be just a single object. User code may later read values back from the data store or even update data, as needed.
The transactional behavior ensures that any changes succeed or fail together. This can be used to ensure that the data store is not left in a transitory state, where some values were updated but others were not.
Behind the scenes, Ruby objects are stored to the data store file with Marshal. That carries the usual limitations. Proc objects cannot be marshalled, for example.
Usage example:¶ ↑
require "pstore"
# a mock wiki object...
class WikiPage
def initialize( page_name, author, contents )
@page_name = page_name
@revisions = Array.new
add_revision(author, contents)
end
attr_reader :page_name
def add_revision( author, contents )
@revisions << { :created => Time.now,
:author => author,
:contents => contents }
end
def wiki_page_references
[@page_name] + @revisions.last[:contents].scan(/\b(?:[A-Z]+[a-z]+){2,}/)
end
# ...
end
# create a new page...
home_page = WikiPage.new( "HomePage", "James Edward Gray II",
"A page about the JoysOfDocumentation..." )
# then we want to update page data and the index together, or not at all...
wiki = PStore.new("wiki_pages.pstore")
wiki.transaction do # begin transaction; do all of this or none of it
# store page...
wiki[home_page.page_name] = home_page
# ensure that an index has been created...
wiki[:wiki_index] ||= Array.new
# update wiki index...
wiki[:wiki_index].push(*home_page.wiki_page_references)
end # commit changes to wiki data store file
### Some time later... ###
# read wiki data...
wiki.transaction(true) do # begin read-only transaction, no changes allowed
wiki.roots.each do |data_root_name|
p data_root_name
p wiki[data_root_name]
end
end
Transaction modes¶ ↑
By default, file integrity is only ensured as long as the operating system (and the underlying hardware) doesn't raise any unexpected I/O errors. If an I/O error occurs while PStore is writing to its file, then the file will become corrupted.
You can prevent this by setting pstore.ultra_safe = true. However, this results in a minor performance loss, and only works on platforms that support atomic file renames. Please consult the documentation for ultra_safe for details.
Needless to say, if you're storing valuable data with PStore, then you should backup the PStore files from time to time.
The error type thrown by all PStore methods.
Thrown when PTY::check is called for a pid that represents a process that has exited.
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.
Examples¶ ↑
Example 1: Using 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| _ }
Example 2: Using standard Ruby¶ ↑
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| _ }
Example 3: Special features¶ ↑
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, ...]
Breakdown of functionality¶ ↑
Core methods¶ ↑
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.
+
join
parent
root?
absolute?
relative?
relative_path_from
each_filename
cleanpath
realpath
realdirpath
children
each_child
mountpoint?
File status predicate methods¶ ↑
These methods are a facade for FileTest:
blockdev?
chardev?
directory?
executable?
executable_real?
exist?
file?
grpowned?
owned?
pipe?
readable?
world_readable?
readable_real?
setgid?
setuid?
size
size?
socket?
sticky?
symlink?
writable?
world_writable?
writable_real?
zero?
File property and manipulation methods¶ ↑
These methods are a facade for File:
atime
birthtime
ctime
mtime
chmod(mode)
lchmod(mode)
chown(owner, group)
lchown(owner, group)
fnmatch(pattern, *args)
fnmatch?(pattern, *args)
ftype
make_link(old)
open(*args, &block)
readlink
rename(to)
stat
lstat
make_symlink(old)
truncate(length)
utime(atime, mtime)
basename(*args)
dirname
extname
expand_path(*args)
split
Directory methods¶ ↑
These methods are a facade for Dir:
Pathname.glob(*args)
Pathname.getwd / Pathname.pwd
rmdir
entries
each_entry(&block)
mkdir(*args)
opendir(*args)
IO¶ ↑
These methods are a facade for IO:
each_line(*args, &block)
read(*args)
binread(*args)
readlines(*args)
sysopen(*args)
Utilities¶ ↑
These methods are a mixture of Find, FileUtils, and others:
find(&block)
mkpath
rmtree
unlink / delete
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.
This class implements a pretty printing algorithm. It finds line breaks and nice indentations for grouped structure.
By default, the class assumes that primitive elements are strings and each byte in the strings have single column in width. But it can be used for other situations by giving suitable arguments for some methods:
newline object and space generation block for PrettyPrint.new
optional width argument for PrettyPrint#text
PrettyPrint#breakable
There are several candidate uses:
text formatting using proportional fonts
multibyte characters which has columns different to number of bytes
non-string formatting
Bugs¶ ↑
Box based formatting?
Other (better) model/algorithm?
Report any bugs at bugs.ruby-lang.org
References¶ ↑
Christian Lindig, Strictly Pretty, March 2000, www.st.cs.uni-sb.de/~lindig/papers/#pretty
Philip Wadler, A prettier printer, March 1998, homepages.inf.ed.ac.uk/wadler/topics/language-design.html#prettier
Author¶ ↑
Tanaka Akira <[email protected]>
PrettyPrint::SingleLine is used by PrettyPrint.singleline_format
It is passed to be similar to a PrettyPrint object itself, by responding to:
text
breakable
nest
group
flush
first?
but instead, the output has no line breaks
The set of all prime numbers.
Example¶ ↑
Prime.each(100) do |prime|
p prime #=> 2, 3, 5, 7, 11, ...., 97
end
Prime is Enumerable:
Prime.first 5 # => [2, 3, 5, 7, 11]
Retrieving the instance¶ ↑
For convenience, each instance method of Prime.instance can be accessed as a class method of Prime.
e.g.
Prime.instance.prime?(2) #=> true
Prime.prime?(2) #=> true
Generators¶ ↑
A “generator” provides an implementation of enumerating pseudo-prime numbers and it remembers the position of enumeration and upper bound. Furthermore, it is an external iterator of prime enumeration which is compatible with an Enumerator.
Prime::PseudoPrimeGenerator is the base class for generators. There are few implementations of generator.
Prime::EratosthenesGenerator
Uses eratosthenes' sieve.
Prime::TrialDivisionGenerator
Uses the trial division method.
Prime::Generator23
Generates all positive integers which are not divisible by either 2 or 3. This sequence is very bad as a pseudo-prime sequence. But this is faster and uses much less memory than the other generators. So, it is suitable for factorizing an integer which is not large but has many prime factors. e.g. for Prime#prime? .
An implementation of PseudoPrimeGenerator.
Uses EratosthenesSieve.
Internal use. An implementation of Eratosthenes' sieve
Generates all integers which are greater than 2 and are not divisible by either 2 or 3.
This is a pseudo-prime generator, suitable on checking primality of an integer by brute force method.
An abstract class for enumerating pseudo-prime numbers.
Concrete subclasses should override succ, next, rewind.
Internal use. An implementation of prime table by trial division method.
An implementation of PseudoPrimeGenerator which uses a prime table generated by trial division.
A Proc object is an encapsulation of a block of code, which can be stored in a local variable, passed to a method or another Proc, and can be called. Proc is an essential concept in Ruby and a core of its functional programming features.
square = Proc.new {|x| x**2 }
square.call(3) #=> 9
# shorthands:
square.(3) #=> 9
square[3] #=> 9
Proc objects are closures, meaning they remember and can use the entire context in which they were created.
def gen_times(factor)
Proc.new {|n| n*factor } # remembers the value of factor at the moment of creation
end
times3 = gen_times(3)
times5 = gen_times(5)
times3.call(12) #=> 36
times5.call(5) #=> 25
times3.call(times5.call(4)) #=> 60
Creation¶ ↑
There are several methods to create a Proc
Use the Proc class constructor:
proc1 = Proc.new {|x| x**2 }
Use the Kernel#proc method as a shorthand of Proc.new:
proc2 = proc {|x| x**2 }
Receiving a block of code into proc argument (note the &):
def make_proc(&block)
block
end
proc3 = make_proc {|x| x**2 }
Construct a proc with lambda semantics using the Kernel#lambda method (see below for explanations about lambdas):
lambda1 = lambda {|x| x**2 }
Use the Lambda literal syntax (also constructs a proc with lambda semantics):
lambda2 = ->(x) { x**2 }
Lambda and non-lambda semantics¶ ↑
Procs are coming in two flavors: lambda and non-lambda (regular procs). Differences are:
In lambdas, return means exit from this lambda;
In regular procs, return means exit from embracing method (and will throw LocalJumpError if invoked outside the method);
In lambdas, arguments are treated in the same way as in methods: strict, with ArgumentError for mismatching argument number, and no additional argument processing;
Regular procs accept arguments more generously: missing arguments are filled with nil, single Array arguments are deconstructed if the proc has multiple arguments, and there is no error raised on extra arguments.
Examples:
p = proc {|x, y| "x=#{x}, y=#{y}" }
p.call(1, 2) #=> "x=1, y=2"
p.call([1, 2]) #=> "x=1, y=2", array deconstructed
p.call(1, 2, 8) #=> "x=1, y=2", extra argument discarded
p.call(1) #=> "x=1, y=", nil substituted instead of error
l = lambda {|x, y| "x=#{x}, y=#{y}" }
l.call(1, 2) #=> "x=1, y=2"
l.call([1, 2]) # ArgumentError: wrong number of arguments (given 1, expected 2)
l.call(1, 2, 8) # ArgumentError: wrong number of arguments (given 3, expected 2)
l.call(1) # ArgumentError: wrong number of arguments (given 1, expected 2)
def test_return
-> { return 3 }.call # just returns from lambda into method body
proc { return 4 }.call # returns from method
return 5
end
test_return # => 4, return from proc
Lambdas are useful as self-sufficient functions, in particular useful as arguments to higher-order functions, behaving exactly like Ruby methods.
Procs are useful for implementing iterators:
def test
[[1, 2], [3, 4], [5, 6]].map {|a, b| return a if a + b > 10 }
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
end
Inside map, the block of code is treated as a regular (non-lambda) proc, which means that the internal arrays will be deconstructed to pairs of arguments, and return will exit from the method test. That would not be possible with a stricter lambda.
You can tell a lambda from a regular proc by using the lambda? instance method.
Lambda semantics is typically preserved during the proc lifetime, including &-deconstruction to a block of code:
p = proc {|x, y| x }
l = lambda {|x, y| x }
[[1, 2], [3, 4]].map(&p) #=> [1, 2]
[[1, 2], [3, 4]].map(&l) # ArgumentError: wrong number of arguments (given 1, expected 2)
The only exception is dynamic method definition: even if defined by passing a non-lambda proc, methods still have normal semantics of argument checking.
class C
define_method(:e, &proc {})
end
C.new.e(1,2) #=> ArgumentError
C.new.method(:e).to_proc.lambda? #=> true
This exception ensures that methods never have unusual argument passing conventions, and makes it easy to have wrappers defining methods that behave as usual.
class C
def self.def2(name, &body)
define_method(name, &body)
end
def2(:f) {}
end
C.new.f(1,2) #=> ArgumentError
The wrapper def2 receives body as a non-lambda proc, yet defines a method which has normal semantics.
Conversion of other objects to procs¶ ↑
Any object that implements the to_proc method can be converted into a proc by the & operator, and therefore con be consumed by iterators.
class Greater
def initialize(greating)
@greating = greating
end
def to_proc
proc {|name| "#{@greating}, #{name}!" }
end
end
hi = Greater.new("Hi")
hey = Greater.new("Hey")
["Bob", "Jane"].map(&hi) #=> ["Hi, Bob!", "Hi, Jane!"]
["Bob", "Jane"].map(&hey) #=> ["Hey, Bob!", "Hey, Jane!"]
Of the Ruby core classes, this method is implemented by Symbol, Method, and Hash.
:to_s.to_proc.call(1) #=> "1"
[1, 2].map(&:to_s) #=> ["1", "2"]
method(:puts).to_proc.call(1) # prints 1
[1, 2].each(&method(:puts)) # prints 1, 2
{test: 1}.to_proc.call(:test) #=> 1
%i[test many keys].map(&{test: 1}) #=> [1, nil, nil]
Process::Status encapsulates the information on the status of a running or terminated system process. The built-in variable $? is either nil or a Process::Status object.
fork { exit 99 } #=> 26557
Process.wait #=> 26557
$?.class #=> Process::Status
$?.to_i #=> 25344
$? >> 8 #=> 99
$?.stopped? #=> false
$?.exited? #=> true
$?.exitstatus #=> 99
Posix systems record information on processes using a 16-bit integer. The lower bits record the process status (stopped, exited, signaled) and the upper bits possibly contain additional information (for example the program's return code in the case of exited processes). Pre Ruby 1.8, these bits were exposed directly to the Ruby program. Ruby now encapsulates these in a Process::Status object. To maximize compatibility, however, these objects retain a bit-oriented interface. In the descriptions that follow, when we talk about the integer value of stat, we're referring to this 16 bit value.
If an object defines encode_with, then an instance of Psych::Coder will be passed to the method when the object is being serialized. The Coder automatically assumes a Psych::Nodes::Mapping is being emitted. Other objects like Sequence and Scalar may be emitted if seq= or scalar= are called, respectively.
Psych::Handler is an abstract base class that defines the events used when dealing with Psych::Parser. Clients who want to use Psych::Parser should implement a class that inherits from Psych::Handler and define events that they can handle.
Psych::Handler defines all events that Psych::Parser can possibly send to event handlers.
See Psych::Parser for more details
Configuration options for dumping YAML.
This handler will capture an event and record the event. Recorder events are available vial Psych::Handlers::Recorder#events.
For example:
recorder = Psych::Handlers::Recorder.new
parser = Psych::Parser.new recorder
parser.parse '--- foo'
recorder.events # => [list of events]
# Replay the events
emitter = Psych::Emitter.new $stdout
recorder.events.each do |m, args|
emitter.send m, *args
end
Psych::JSON::TreeBuilder is an event based AST builder. Events are sent to an instance of Psych::JSON::TreeBuilder and a JSON AST is constructed.
This class represents a YAML Alias. It points to an anchor.
A Psych::Nodes::Alias is a terminal node and may have no children.
This represents a YAML Document. This node must be a child of Psych::Nodes::Stream. A Psych::Nodes::Document must have one child, and that child may be one of the following:
Psych::Nodes::Sequence
Psych::Nodes::Mapping
Psych::Nodes::Scalar
This class represents a YAML Mapping.
A Psych::Nodes::Mapping node may have 0 or more children, but must have an even number of children. Here are the valid children a Psych::Nodes::Mapping node may have:
Psych::Nodes::Sequence
Psych::Nodes::Mapping
Psych::Nodes::Scalar
Psych::Nodes::Alias
The base class for any Node in a YAML parse tree. This class should never be instantiated.
This class represents a YAML Scalar.
This node type is a terminal node and should not have any children.
This class represents a YAML sequence.
A YAML sequence is basically a list, and looks like this:
%YAML 1.1
---
- I am
- a Sequence
A YAML sequence may have an anchor like this:
%YAML 1.1
---
&A [
"This sequence",
"has an anchor"
]
A YAML sequence may also have a tag like this:
%YAML 1.1
---
!!seq [
"This sequence",
"has a tag"
]
This class represents a sequence in a YAML document. A Psych::Nodes::Sequence node may have 0 or more children. Valid children for this node are:
Psych::Nodes::Sequence
Psych::Nodes::Mapping
Psych::Nodes::Scalar
Psych::Nodes::Alias
Represents a YAML stream. This is the root node for any YAML parse tree. This node must have one or more child nodes. The only valid child node for a Psych::Nodes::Stream node is Psych::Nodes::Document.
YAML event parser class. This class parses a YAML document and calls events on the handler that is passed to the constructor. The events can be used for things such as constructing a YAML AST or deserializing YAML documents. It can even be fed back to Psych::Emitter to emit the same document that was parsed.
See Psych::Handler for documentation on the events that Psych::Parser emits.
Here is an example that prints out ever scalar found in a YAML document:
# Handler for detecting scalar values
class ScalarHandler < Psych::Handler
def scalar value, anchor, tag, plain, quoted, style
puts value
end
end
parser = Psych::Parser.new(ScalarHandler.new)
parser.parse(yaml_document)
Here is an example that feeds the parser back in to Psych::Emitter. The YAML document is read from STDIN and written back out to STDERR:
parser = Psych::Parser.new(Psych::Emitter.new($stderr))
parser.parse($stdin)
Psych uses Psych::Parser in combination with Psych::TreeBuilder to construct an AST of the parsed YAML document.
Scan scalars for built in types
Psych::Stream is a streaming YAML emitter. It will not buffer your YAML, but send it straight to an IO.
Here is an example use:
stream = Psych::Stream.new($stdout)
stream.start
stream.push({:foo => 'bar'})
stream.finish
YAML will be immediately emitted to $stdout with no buffering.
Psych::Stream#start will take a block and ensure that Psych::Stream#finish is called, so you can do this form:
stream = Psych::Stream.new($stdout)
stream.start do |em|
em.push(:foo => 'bar')
end
This class works in conjunction with Psych::Parser to build an in-memory parse tree that represents a YAML document.
Example¶ ↑
parser = Psych::Parser.new Psych::TreeBuilder.new
parser.parse('--- foo')
tree = parser.handler.root
See Psych::Handler for documentation on the event methods used in this class.
This class walks a YAML AST, converting each node to Ruby
YAMLTree builds a YAML ast given a Ruby object. For example:
builder = Psych::Visitors::YAMLTree.new
builder << { :foo => 'bar' }
builder.tree # => #<Psych::Nodes::Stream .. }
The Queue class implements multi-producer, multi-consumer queues. It is especially useful in threaded programming when information must be exchanged safely between multiple threads. The Queue class implements all the required locking semantics.
The class implements FIFO type of queue. In a FIFO queue, the first tasks added are the first retrieved.
Example:
queue = Queue.new
producer = Thread.new do
5.times do |i|
sleep rand(i) # simulate expense
queue << i
puts "#{i} produced"
end
end
consumer = Thread.new do
5.times do |i|
value = queue.pop
sleep rand(i/2) # simulate expense
puts "consumed #{value}"
end
end
consumer.join
RDoc produces documentation for Ruby source files by parsing the source and extracting the definition for classes, modules, methods, includes and requires. It associates these with optional documentation contained in an immediately preceding comment block then renders the result using an output formatter.
For a simple introduction to writing or generating documentation using RDoc see the README.
Roadmap¶ ↑
If you think you found a bug in RDoc see Bugs at CONTRIBUTING
If you want to use RDoc to create documentation for your Ruby source files, see RDoc::Markup and refer to rdoc --help for command line usage.
If you want to set the default markup format see Supported Formats at RDoc::Markup
If you want to store rdoc configuration in your gem (such as the default markup format) see Saved Options at RDoc::Options
If you want to write documentation for Ruby files see RDoc::Parser::Ruby
If you want to write documentation for extensions written in C see RDoc::Parser::C
If you want to generate documentation using rake see RDoc::Task.
If you want to drive RDoc programmatically, see RDoc::RDoc.
If you want to use the library to format text blocks into HTML or other formats, look at RDoc::Markup.
If you want to make an RDoc plugin such as a generator or directive handler see RDoc::RDoc.
If you want to write your own output generator see RDoc::Generator.
If you want an overview of how RDoc works see Bugs at CONTRIBUTING
Credits¶ ↑
RDoc is currently being maintained by Eric Hodel <[email protected]>.
Dave Thomas <[email protected]> is the original author of RDoc.
The Ruby parser in rdoc/parse.rb is based heavily on the outstanding work of Keiju ISHITSUKA of Nippon Rational Inc, who produced the Ruby parser for irb and the rtags package.
Represent an alias, which is an old_name/new_name pair associated with a particular context
An anonymous class like:
c = Class.new do end
AnonClass is currently not used.
AnyMethod is the base class for objects representing methods
An attribute created by #attr, #attr_reader, #attr_writer or #attr_accessor
ClassModule is the base class for objects representing either a class or a module.
Base class for the RDoc code tree.
We contain the common stuff for contexts (which are containers) and other elements (methods, attributes and so on)
Here's the tree of the CodeObject subclasses:
RDoc::Context
RDoc::TopLevel
RDoc::ClassModule
RDoc::AnonClass (never used so far)
RDoc::NormalClass
RDoc::NormalModule
RDoc::SingleClass
RDoc::MethodAttr
RDoc::Attr
RDoc::AnyMethod
RDoc::GhostMethod
RDoc::MetaMethod
RDoc::Alias
RDoc::Constant
RDoc::Mixin
RDoc::Require
RDoc::Include
A comment holds the text comment for a RDoc::CodeObject and provides a unified way of cleaning it up and parsing it into an RDoc::Markup::Document.
Each comment may have a different markup format set by format=. By default 'rdoc' is used. The :markup: directive tells RDoc which format to use.
See Other directives at RDoc::Markup for instructions on adding an alternate format.
A constant
A Context is something that can hold modules, classes, methods, attributes, aliases, requires, and includes. Classes, modules, and files are all Contexts.
RDoc::CrossReference is a reusable way to create cross references for names.
A subclass of ERB that writes directly to an IO. Credit to Aaron Patterson and Masatoshi SEKI.
To use:
erbio = RDoc::ERBIO.new '<%= "hello world" %>', nil, nil
File.open 'hello.txt', 'w' do |io|
erbio.result binding
end
Note that binding must enclose the io you wish to output on.
Allows an ERB template to be rendered in the context (binding) of an existing ERB template evaluation.
Exception thrown by any rdoc error.
A Module extension to a class with #extend
RDoc::Extend.new 'Enumerable', 'comment ...'
GhostMethod represents a method referenced only by a comment
A Module included in a class with #include
RDoc::Include.new 'Enumerable', 'comment ...'
RDoc::Markdown as described by the markdown syntax.
To choose Markdown as your only default format see Saved Options at RDoc::Options for instructions on setting up a .doc_options file to store your project default.
Usage¶ ↑
Here is a brief example of using this parse to read a markdown file by hand.
data = File.read("README.md")
formatter = RDoc::Markup::ToHtml.new(RDoc::Options.new, nil)
html = RDoc::Markdown.parse(data).accept(formatter)
# do something with html
Extensions¶ ↑
The following markdown extensions are supported by the parser, but not all are used in RDoc output by default.
RDoc¶ ↑
The RDoc Markdown parser has the following built-in behaviors that cannot be disabled.
Underscores embedded in words are never interpreted as emphasis. (While the markdown dingus emphasizes in-word underscores, neither the Markdown syntax nor MarkdownTest mention this behavior.)
For HTML output, RDoc always auto-links bare URLs.
Break on Newline¶ ↑
The break_on_newline extension converts all newlines into hard line breaks as in Github Flavored Markdown. This extension is disabled by default.
CSS¶ ↑
The css extension enables CSS blocks to be included in the output, but they are not used for any built-in RDoc output format. This extension is disabled by default.
Example:
<style type="text/css">
h1 { font-size: 3em }
</style>
Definition Lists¶ ↑
The definition_lists extension allows definition lists using the PHP Markdown Extra syntax, but only one label and definition are supported at this time. This extension is enabled by default.
Example:
cat
: A small furry mammal
that seems to sleep a lot
ant
: A little insect that is known
to enjoy picnics
Produces:
cat
A small furry mammal that seems to sleep a lot
ant
A little insect that is known to enjoy picnics
Strike¶ ↑
Example:
This is ~~striked~~.
Produces:
This is ~striked~.
Github¶ ↑
The github extension enables a partial set of Github Flavored Markdown. This extension is enabled by default.
Supported github extensions include:
Fenced code blocks¶ ↑
Use ``` around a block of code instead of indenting it four spaces.
Syntax highlighting¶ ↑
Use ``` ruby as the start of a code fence to add syntax highlighting. (Currently only ruby syntax is supported).
HTML¶ ↑
Enables raw HTML to be included in the output. This extension is enabled by default.
Example:
<table>
...
</table>
Notes¶ ↑
The notes extension enables footnote support. This extension is enabled by default.
Example:
Here is some text[^1] including an inline footnote ^[for short footnotes]
...
[^1]: With the footnote text down at the bottom
Produces:
Here is some text1 including an inline footnote 2
Limitations¶ ↑
Link titles are not used
Footnotes are collapsed into a single paragraph
Author¶ ↑
This markdown parser is a port to kpeg from peg-markdown by John MacFarlane.
It is used under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
The port to kpeg was performed by Eric Hodel and Evan Phoenix
1 With the footnote text down at the bottom
2 for short footnotes
RDoc::Markup parses plain text documents and attempts to decompose them into their constituent parts. Some of these parts are high-level: paragraphs, chunks of verbatim text, list entries and the like. Other parts happen at the character level: a piece of bold text, a word in code font. This markup is similar in spirit to that used on WikiWiki webs, where folks create web pages using a simple set of formatting rules.
RDoc::Markup and other markup formats do no output formatting, this is handled by the RDoc::Markup::Formatter subclasses.
Supported Formats¶ ↑
Besides the RDoc::Markup format, the following formats are built in to RDoc:
markdown
The markdown format as described by daringfireball.net/projects/markdown/. See RDoc::Markdown for details on the parser and supported extensions.
rd
The rdtool format. See RDoc::RD for details on the parser and format.
tomdoc
The TomDoc format as described by tomdoc.org/. See RDoc::TomDoc for details on the parser and supported extensions.
You can choose a markup format using the following methods:
per project
If you build your documentation with rake use RDoc::Task#markup.
If you build your documentation by hand run:
rdoc --markup your_favorite_format --write-options
and commit .rdoc_options and ship it with your packaged gem.
per file
At the top of the file use the :markup: directive to set the default format for the rest of the file.
per comment
Use the :markup: directive at the top of a comment you want to write in a different format.
RDoc::Markup¶ ↑
RDoc::Markup is extensible at runtime: you can add new markup elements to be recognized in the documents that RDoc::Markup parses.
RDoc::Markup is intended to be the basis for a family of tools which share the common requirement that simple, plain-text should be rendered in a variety of different output formats and media. It is envisaged that RDoc::Markup could be the basis for formatting RDoc style comment blocks, Wiki entries, and online FAQs.
Synopsis¶ ↑
This code converts input_string to HTML. The conversion takes place in the convert method, so you can use the same RDoc::Markup converter to convert multiple input strings.
require 'rdoc'
h = RDoc::Markup::ToHtml.new(RDoc::Options.new)
puts h.convert(input_string)
You can extend the RDoc::Markup parser to recognize new markup sequences, and to add regexp handling. Here we make WikiWords significant to the parser, and also make the sequences {word} and <no>text…</no> signify strike-through text. We then subclass the HTML output class to deal with these:
require 'rdoc'
class WikiHtml < RDoc::Markup::ToHtml
def handle_regexp_WIKIWORD(target)
"<font color=red>" + target.text + "</font>"
end
end
markup = RDoc::Markup.new
markup.add_word_pair("{", "}", :STRIKE)
markup.add_html("no", :STRIKE)
markup.add_regexp_handling(/\b([A-Z][a-z]+[A-Z]\w+)/, :WIKIWORD)
wh = WikiHtml.new RDoc::Options.new, markup
wh.add_tag(:STRIKE, "<strike>", "</strike>")
puts "<body>#{wh.convert ARGF.read}</body>"
Encoding¶ ↑
Where Encoding support is available, RDoc will automatically convert all documents to the same output encoding. The output encoding can be set via RDoc::Options#encoding and defaults to Encoding.default_external.
RDoc Markup Reference¶ ↑
Block Markup¶ ↑
Paragraphs and Verbatim¶ ↑
The markup engine looks for a document's natural left margin. This is used as the initial margin for the document.
Consecutive lines starting at this margin are considered to be a paragraph. Empty lines separate paragraphs.
Any line that starts to the right of the current margin is treated as verbatim text. This is useful for code listings:
3.times { puts "Ruby" }
In verbatim text, two or more blank lines are collapsed into one, and trailing blank lines are removed:
This is the first line
This is the second non-blank line,
after 2 blank lines in the source markup.
There were two trailing blank lines right above this paragraph, that have been removed. In addition, the verbatim text has been shifted left, so the amount of indentation of verbatim text is unimportant.
For HTML output RDoc makes a small effort to determine if a verbatim section contains Ruby source code. If so, the verbatim block will be marked up as HTML. Triggers include “def”, “class”, “module”, “require”, the “hash rocket”# (=>) or a block call with a parameter.
Headers¶ ↑
A line starting with an equal sign (=) is treated as a heading. Level one headings have one equals sign, level two headings have two, and so on until level six, which is the maximum (seven hyphens or more result in a level six heading).
For example, the above header was obtained with:
=== Headers
In HTML output headers have an id matching their name. The above example's HTML is:
<h3 id="label-Headers">Headers</h3>
If a heading is inside a method body the id will be prefixed with the method's id. If the above header where in the documentation for a method such as:
##
# This method does fun things
#
# = Example
#
# Example of fun things goes here ...
def do_fun_things
end
The header's id would be:
<h1 id="method-i-do_fun_things-label-Example">Example</h1>
The label can be linked-to using SomeClass@Headers. See Links for further details.
Rules¶ ↑
A line starting with three or more hyphens (at the current indent) generates a horizontal rule.
---
produces:
Simple Lists¶ ↑
If a paragraph starts with a “*”, “-”, “<digit>.” or “<letter>.”, then it is taken to be the start of a list. The margin is increased to be the first non-space following the list start flag. Subsequent lines should be indented to this new margin until the list ends. For example:
* this is a list with three paragraphs in
the first item. This is the first paragraph.
And this is the second paragraph.
1. This is an indented, numbered list.
2. This is the second item in that list
This is the third conventional paragraph in the
first list item.
* This is the second item in the original list
produces:
this is a list with three paragraphs in the first item. This is the first paragraph.
And this is the second paragraph.
This is an indented, numbered list.
This is the second item in that list
This is the third conventional paragraph in the first list item.
This is the second item in the original list
Labeled Lists¶ ↑
You can also construct labeled lists, sometimes called description or definition lists. Do this by putting the label in square brackets and indenting the list body:
[cat] a small furry mammal
that seems to sleep a lot
[ant] a little insect that is known
to enjoy picnics
produces:
cat
a small furry mammal that seems to sleep a lot
ant
a little insect that is known to enjoy picnics
If you want the list bodies to line up to the left of the labels, use two colons:
cat:: a small furry mammal
that seems to sleep a lot
ant:: a little insect that is known
to enjoy picnics
produces:
cat
a small furry mammal that seems to sleep a lot
ant
a little insect that is known to enjoy picnics
Notice that blank lines right after the label are ignored in labeled lists:
[one]
definition 1
[two]
definition 2
produces the same output as
[one] definition 1
[two] definition 2
Lists and Verbatim¶ ↑
If you want to introduce a verbatim section right after a list, it has to be less indented than the list item bodies, but more indented than the list label, letter, digit or bullet. For instance:
* point 1
* point 2, first paragraph
point 2, second paragraph
verbatim text inside point 2
point 2, third paragraph
verbatim text outside of the list (the list is therefore closed)
regular paragraph after the list
produces:
point 1
point 2, first paragraph
point 2, second paragraph
verbatim text inside point 2
point 2, third paragraph
verbatim text outside of the list (the list is therefore closed)
regular paragraph after the list
Text Markup¶ ↑
Bold, Italic, Typewriter Text¶ ↑
You can use markup within text (except verbatim) to change the appearance of parts of that text. Out of the box, RDoc::Markup supports word-based and general markup.
Word-based markup uses flag characters around individual words:
*word*
displays word in a bold font
_word_
displays word in an emphasized font
+word+
displays word in a code font
General markup affects text between a start delimiter and an end delimiter. Not surprisingly, these delimiters look like HTML markup.
<b>text</b>
displays text in a bold font
<em>text</em>
displays text in an emphasized font (alternate tag: <i>)
<tt>text</tt>
displays text in a code font (alternate tag: <code>)
Unlike conventional Wiki markup, general markup can cross line boundaries. You can turn off the interpretation of markup by preceding the first character with a backslash (see Escaping Text Markup, below).
Links¶ ↑
Links to starting with http:, https:, mailto:, ftp: or www. are recognized. An HTTP url that references an external image is converted into an inline image element.
Classes and methods will be automatically linked to their definition. For example, RDoc::Markup will link to this documentation. By default methods will only be automatically linked if they contain an _ (all methods can be automatically linked through the --hyperlink-all command line option).
Single-word methods can be linked by using the # character for instance methods or :: for class methods. For example, #convert links to convert. A class or method may be combined like RDoc::Markup#convert.
A heading inside the documentation can be linked by following the class or method by an @ then the heading name. RDoc::Markup@Links will link to this section like this: Links at RDoc::Markup. Spaces in headings with multiple words must be escaped with + like RDoc::Markup@Escaping+Text+Markup. Punctuation and other special characters must be escaped like CGI.escape.
The @ can also be used to link to sections. If a section and a heading share the same name the section is preferred for the link.
Links can also be of the form label[url], in which case label is used in the displayed text, and url is used as the target. If label contains multiple words, put it in braces: {multi word label}[url]. The url may be an http:-type link or a cross-reference to a class, module or method with a label.
Links with the rdoc-image: scheme will create an image tag for HTML output. Only fully-qualified URLs are supported.
Links with the rdoc-ref: scheme will link to the referenced class, module, method, file, etc. If the referenced item is does not exist no link will be generated and rdoc-ref: will be removed from the resulting text.
Links starting with rdoc-label:label_name will link to the label_name. You can create a label for the current link (for bidirectional links) by supplying a name for the current link like rdoc-label:label-other:label-mine.
Links starting with link: refer to local files whose path is relative to the --op directory. Use rdoc-ref: instead of link: to link to files generated by RDoc as the link target may be different across RDoc generators.
Example links:
https://github.com/ruby/rdoc
mailto:[email protected]
{RDoc Documentation}[http://rdoc.rubyforge.org]
{RDoc Markup}[rdoc-ref:RDoc::Markup]
Escaping Text Markup¶ ↑
Text markup can be escaped with a backslash, as in <tt>, which was obtained with \<tt>. Except in verbatim sections and between <tt> tags, to produce a backslash you have to double it unless it is followed by a space, tab or newline. Otherwise, the HTML formatter will discard it, as it is used to escape potential links:
* The \ must be doubled if not followed by white space: \\.
* But not in \<tt> tags: in a Regexp, <tt>\S</tt> matches non-space.
* This is a link to {ruby-lang}[www.ruby-lang.org].
* This is not a link, however: \{ruby-lang.org}[www.ruby-lang.org].
* This will not be linked to \RDoc::RDoc#document
generates:
The \ must be doubled if not followed by white space: \.
But not in <tt> tags: in a Regexp, \S matches non-space.
This is a link to ruby-lang
This is not a link, however: {ruby-lang.org}[www.ruby-lang.org]
This will not be linked to RDoc::RDoc#document
Inside <tt> tags, more precisely, leading backslashes are removed only if followed by a markup character (<*_+), a backslash, or a known link reference (a known class or method). So in the example above, the backslash of \S would be removed if there was a class or module named S in the current context.
This behavior is inherited from RDoc version 1, and has been kept for compatibility with existing RDoc documentation.
Conversion of characters¶ ↑
HTML will convert two/three dashes to an em-dash. Other common characters are converted as well:
em-dash:: -- or ---
ellipsis:: ...
single quotes:: 'text' or `text'
double quotes:: "text" or ``text''
copyright:: (c)
registered trademark:: (r)
produces:
em-dash
– or —
ellipsis
…
single quotes
'text' or `text'
double quotes
“text” or “text''
copyright
©
registered trademark
®
Documenting Source Code¶ ↑
Comment blocks can be written fairly naturally, either using # on successive lines of the comment, or by including the comment in a =begin/=end block. If you use the latter form, the =begin line must be flagged with an rdoc tag:
=begin rdoc
Documentation to be processed by RDoc.
...
=end
RDoc stops processing comments if it finds a comment line starting with -- right after the # character (otherwise, it will be treated as a rule if it has three dashes or more). This can be used to separate external from internal comments, or to stop a comment being associated with a method, class, or module. Commenting can be turned back on with a line that starts with ++.
##
# Extract the age and calculate the date-of-birth.
#--
# FIXME: fails if the birthday falls on February 29th
#++
# The DOB is returned as a Time object.
def get_dob(person)
# ...
end
Names of classes, files, and any method names containing an underscore or preceded by a hash character are automatically linked from comment text to their description. This linking works inside the current class or module, and with ancestor methods (in included modules or in the superclass).
Method parameter lists are extracted and displayed with the method description. If a method calls yield, then the parameters passed to yield will also be displayed:
def fred
...
yield line, address
This will get documented as:
fred() { |line, address| ... }
You can override this using a comment containing ':yields: …' immediately after the method definition
def fred # :yields: index, position
# ...
yield line, address
which will get documented as
fred() { |index, position| ... }
:yields: is an example of a documentation directive. These appear immediately after the start of the document element they are modifying.
RDoc automatically cross-references words with underscores or camel-case. To suppress cross-references, prefix the word with a \ character. To include special characters like “\n”, you'll need to use two \ characters in normal text, but only one in <tt> text:
"\\n" or "<tt>\n</tt>"
produces:
“\n” or “\n”
Directives¶ ↑
Directives are keywords surrounded by “:” characters.
Controlling what is documented¶ ↑
:nodoc: / :nodoc: all
This directive prevents documentation for the element from being generated. For classes and modules, methods, aliases, constants, and attributes directly within the affected class or module also will be omitted. By default, though, modules and classes within that class or module will be documented. This is turned off by adding the all modifier.
module MyModule # :nodoc:
class Input
end
end
module OtherModule # :nodoc: all
class Output
end
end
In the above code, only class MyModule::Input will be documented.
The :nodoc: directive, like :enddoc:, :stopdoc: and :startdoc: presented below, is local to the current file: if you do not want to document a module that appears in several files, specify :nodoc: on each appearance, at least once per file.
:stopdoc: / :startdoc:
Stop and start adding new documentation elements to the current container. For example, if a class has a number of constants that you don't want to document, put a :stopdoc: before the first, and a :startdoc: after the last. If you don't specify a :startdoc: by the end of the container, disables documentation for the rest of the current file.
:doc:
Forces a method or attribute to be documented even if it wouldn't be otherwise. Useful if, for example, you want to include documentation of a particular private method.
:enddoc:
Document nothing further at the current level: directives :startdoc: and :doc: that appear after this will not be honored for the current container (file, class or module), in the current file.
:notnew: / :not_new: / :not-new:
Only applicable to the initialize instance method. Normally RDoc assumes that the documentation and parameters for initialize are actually for the new method, and so fakes out a new for the class. The :notnew: directive stops this. Remember that initialize is private, so you won't see the documentation unless you use the -a command line option.
Method arguments¶ ↑
:arg: or :args: parameters
Overrides the default argument handling with exactly these parameters.
##
# :args: a, b
def some_method(*a)
end
:yield: or :yields: parameters
Overrides the default yield discovery with these parameters.
##
# :yields: key, value
def each_thing &block
@things.each(&block)
end
:call-seq:
Lines up to the next blank line or lines with a common prefix in the comment are treated as the method's calling sequence, overriding the default parsing of method parameters and yield arguments.
Multiple lines may be used.
# :call-seq:
# ARGF.readlines(sep=$/) -> array
# ARGF.readlines(limit) -> array
# ARGF.readlines(sep, limit) -> array
#
# ARGF.to_a(sep=$/) -> array
# ARGF.to_a(limit) -> array
# ARGF.to_a(sep, limit) -> array
#
# The remaining lines are documentation ...
Sections¶ ↑
Sections allow you to group methods in a class into sensible containers. If you use the sections 'Public', 'Internal' and 'Deprecated' (the three allowed method statuses from TomDoc) the sections will be displayed in that order placing the most useful methods at the top. Otherwise, sections will be displayed in alphabetical order.
:category: section
Adds this item to the named section overriding the current section. Use this to group methods by section in RDoc output while maintaining a sensible ordering (like alphabetical).
# :category: Utility Methods
#
# CGI escapes +text+
def convert_string text
CGI.escapeHTML text
end
An empty category will place the item in the default category:
# :category:
#
# This method is in the default category
def some_method
# ...
end
Unlike the :section: directive, :category: is not sticky. The category only applies to the item immediately following the comment.
Use the :section: directive to provide introductory text for a section of documentation.
:section: title
Provides section introductory text in RDoc output. The title following :section: is used as the section name and the remainder of the comment containing the section is used as introductory text. A section's comment block must be separated from following comment blocks. Use an empty title to switch to the default section.
The :section: directive is sticky, so subsequent methods, aliases, attributes, and classes will be contained in this section until the section is changed. The :category: directive will override the :section: directive.
A :section: comment block may have one or more lines before the :section: directive. These will be removed, and any identical lines at the end of the block are also removed. This allows you to add visual cues to the section.
Example:
# ----------------------------------------
# :section: My Section
# This is the section that I wrote.
# See it glisten in the noon-day sun.
# ----------------------------------------
##
# Comment for some_method
def some_method
# ...
end
Other directives¶ ↑
:markup: type
Overrides the default markup type for this comment with the specified markup type. For Ruby files, if the first comment contains this directive it is applied automatically to all comments in the file.
Unless you are converting between markup formats you should use a .rdoc_options file to specify the default documentation format for your entire project. See Saved Options at RDoc::Options for instructions.
At the top of a file the :markup: directive applies to the entire file:
# coding: UTF-8
# :markup: TomDoc
# TomDoc comment here ...
class MyClass
# ...
For just one comment:
# ...
end
# :markup: RDoc
#
# This is a comment in RDoc markup format ...
def some_method
# ...
See CONTRIBUTING at Markup for instructions on adding a new markup format.
:include: filename
Include the contents of the named file at this point. This directive must appear alone on one line, possibly preceded by spaces. In this position, it can be escaped with a \ in front of the first colon.
The file will be searched for in the directories listed by the --include option, or in the current directory by default. The contents of the file will be shifted to have the same indentation as the ':' at the start of the :include: directive.
:title: text
Sets the title for the document. Equivalent to the --title command line parameter. (The command line parameter overrides any :title: directive in the source).
:main: name
Equivalent to the --main command line parameter.
MetaMethod represents a meta-programmed method
Abstract class representing either a method or an attribute.
A Mixin adds features from a module into another context. RDoc::Include and RDoc::Extend are both mixins.
A normal class, neither singleton nor anonymous
A normal module, like NormalClass
RDoc::Options handles the parsing and storage of options
Saved Options¶ ↑
You can save some options like the markup format in the .rdoc_options file in your gem. The easiest way to do this is:
rdoc --markup tomdoc --write-options
Which will automatically create the file and fill it with the options you specified.
The following options will not be saved since they interfere with the user's preferences or with the normal operation of RDoc:
--coverage-report
--dry-run
--encoding
--force-update
--format
--pipe
--quiet
--template
--verbose
Custom Options¶ ↑
Generators can hook into RDoc::Options to add generator-specific command line options.
When --format is encountered in ARGV, RDoc calls ::setup_options on the generator class to add extra options to the option parser. Options for custom generators must occur after --format. rdoc --help will list options for all installed generators.
Example:
class RDoc::Generator::Spellcheck
RDoc::RDoc.add_generator self
def self.setup_options rdoc_options
op = rdoc_options.option_parser
op.on('--spell-dictionary DICTIONARY',
RDoc::Options::Path) do |dictionary|
rdoc_options.spell_dictionary = dictionary
end
end
end
Of course, RDoc::Options does not respond to spell_dictionary by default so you will need to add it:
class RDoc::Options
##
# The spell dictionary used by the spell-checking plugin.
attr_accessor :spell_dictionary
end
Option Validators¶ ↑
OptionParser validators will validate and cast user input values. In addition to the validators that ship with OptionParser (String, Integer, Float, TrueClass, FalseClass, Array, Regexp, Date, Time, URI, etc.), RDoc::Options adds Path, PathArray and Template.
A parser is simple a class that subclasses RDoc::Parser and implements scan to fill in an RDoc::TopLevel with parsed data.
The initialize method takes an RDoc::TopLevel to fill with parsed content, the name of the file to be parsed, the content of the file, an RDoc::Options object and an RDoc::Stats object to inform the user of parsed items. The scan method is then called to parse the file and must return the RDoc::TopLevel object. By calling super these items will be set for you.
In order to be used by RDoc the parser needs to register the file extensions it can parse. Use ::parse_files_matching to register extensions.
require 'rdoc'
class RDoc::Parser::Xyz < RDoc::Parser
parse_files_matching /\.xyz$/
def initialize top_level, file_name, content, options, stats
super
# extra initialization if needed
end
def scan
# parse file and fill in @top_level
end
end
RDoc::RD implements the RD format from the rdtool gem.
To choose RD as your only default format see Saved Options at RDoc::Options for instructions on setting up a .doc_options file to store your project default.
LICENSE¶ ↑
The grammar that produces RDoc::RD::BlockParser and RDoc::RD::InlineParser is included in RDoc under the Ruby License.
You can find the original source for rdtool at github.com/uwabami/rdtool/
You can use, re-distribute or change these files under Ruby's License or GPL.
You may make and give away verbatim copies of the source form of the software without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers.
You may modify your copy of the software in any way, provided that you do at least ONE of the following:
place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or by allowing the author to include your modifications in the software.
use the modified software only within your corporation or organization.
give non-standard binaries non-standard names, with instructions on where to get the original software distribution.
make other distribution arrangements with the author.
You may distribute the software in object code or binary form, provided that you do at least ONE of the following:
distribute the binaries and library files of the software, together with instructions (in the manual page or equivalent) on where to get the original distribution.
accompany the distribution with the machine-readable source of the software.
give non-standard binaries non-standard names, with instructions on where to get the original software distribution.
make other distribution arrangements with the author.
You may modify and include the part of the software into any other software (possibly commercial). But some files in the distribution are not written by the author, so that they are not under these terms.
For the list of those files and their copying conditions, see the file LEGAL.
The scripts and library files supplied as input to or produced as output from the software do not automatically fall under the copyright of the software, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this software.
THIS SOFTWARE IS PROVIDED “AS IS” AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
This is the driver for generating RDoc output. It handles file parsing and generation of output.
To use this class to generate RDoc output via the API, the recommended way is:
rdoc = RDoc::RDoc.new
options = rdoc.load_options # returns an RDoc::Options instance
# set extra options
rdoc.document options
You can also generate output like the rdoc executable:
rdoc = RDoc::RDoc.new
rdoc.document argv
Where argv is an array of strings, each corresponding to an argument you'd give rdoc on the command line. See <tt>rdoc –help<tt> for details.
Base RI error class
A file loaded by #require
Gem::RDoc provides methods to generate RDoc and ri data for installed gems upon gem installation.
This file is automatically required by RubyGems 1.9 and newer.
This is a WEBrick servlet that allows you to browse ri documentation.
You can show documentation through either `ri –server` or, with RubyGems 2.0 or newer, `gem server`. For ri, the server runs on port 8214 by default. For RubyGems the server runs on port 8808 by default.
You can use this servlet in your own project by mounting it on a WEBrick server:
require 'webrick'
server = WEBrick::HTTPServer.new Port: 8000
server.mount '/', RDoc::Servlet
If you want to mount the servlet some other place than the root, provide the base path when mounting:
server.mount '/rdoc', RDoc::Servlet, '/rdoc'
A singleton class
RDoc statistics collector which prints a summary and report of a project's documentation totals.
A set of rdoc data for a single project (gem, path, etc.).
The store manages reading and writing ri data for a project and maintains a cache of methods, classes and ancestors in the store.
The store maintains a cache of its contents for faster lookup. After adding items to the store it must be flushed using save_cache. The cache contains the following structures:
@cache = {
:ancestors => {}, # class name => ancestor names
:attributes => {}, # class name => attributes
:class_methods => {}, # class name => class methods
:instance_methods => {}, # class name => instance methods
:modules => [], # classes and modules in this store
:pages => [], # page names
}
Errors raised from loading or saving the store
Raised when a stored file for a class, module, page or method is missing.
RDoc::Task creates the following rake tasks to generate and clean up RDoc output:
rdoc
Main task for this RDoc task.
clobber_rdoc
Delete all the rdoc files. This target is automatically added to the main clobber target.
rerdoc
Rebuild the rdoc files from scratch, even if they are not out of date.
Simple Example:
require 'rdoc/task'
RDoc::Task.new do |rdoc|
rdoc.main = "README.rdoc"
rdoc.rdoc_files.include("README.rdoc", "lib /*.rb")
end
The rdoc object passed to the block is an RDoc::Task object. See the attributes list for the RDoc::Task class for available customization options.
Specifying different task names¶ ↑
You may wish to give the task a different name, such as if you are generating two sets of documentation. For instance, if you want to have a development set of documentation including private methods:
require 'rdoc/task'
RDoc::Task.new :rdoc_dev do |rdoc|
rdoc.main = "README.doc"
rdoc.rdoc_files.include("README.rdoc", "lib/ *.rb")
rdoc.options << "--all"
end
The tasks would then be named :rdoc_dev, :clobber_rdoc_dev, and :rerdoc_dev.
If you wish to have completely different task names, then pass a Hash as first argument. With the :rdoc, :clobber_rdoc and :rerdoc options, you can customize the task names to your liking.
For example:
require 'rdoc/task'
RDoc::Task.new(:rdoc => "rdoc", :clobber_rdoc => "rdoc:clean",
:rerdoc => "rdoc:force")
This will create the tasks :rdoc, :rdoc:clean and :rdoc:force.
A parser for TomDoc based on TomDoc 1.0.0-rc1 (02adef9b5a)
The TomDoc specification can be found at:
tomdoc.org
The latest version of the TomDoc specification can be found at:
github.com/mojombo/tomdoc/blob/master/tomdoc.md
To choose TomDoc as your only default format see Saved Options at RDoc::Options for instructions on setting up a .rdoc_options file to store your project default.
There are a few differences between this parser and the specification. A best-effort was made to follow the specification as closely as possible but some choices to deviate were made.
A future version of RDoc will warn when a MUST or MUST NOT is violated and may warn when a SHOULD or SHOULD NOT is violated. RDoc will always try to emit documentation even if given invalid TomDoc.
Here are some implementation choices this parser currently makes:
This parser allows rdoc-style inline markup but you should not depended on it.
This parser allows a space between the comment and the method body.
This parser does not require the default value to be described for an optional argument.
This parser does not examine the order of sections. An Examples section may precede the Arguments section.
This class is documented in TomDoc format. Since this is a subclass of the RDoc markup parser there isn't much to see here, unfortunately.
A TopLevel context is a representation of the contents of a single file
RDoc::Task creates the following rake tasks to generate and clean up RDoc output:
rdoc
Main task for this RDoc task.
clobber_rdoc
Delete all the rdoc files. This target is automatically added to the main clobber target.
rerdoc
Rebuild the rdoc files from scratch, even if they are not out of date.
Simple Example:
require 'rdoc/task'
RDoc::Task.new do |rdoc|
rdoc.main = "README.rdoc"
rdoc.rdoc_files.include("README.rdoc", "lib /*.rb")
end
The rdoc object passed to the block is an RDoc::Task object. See the attributes list for the RDoc::Task class for available customization options.
Specifying different task names¶ ↑
You may wish to give the task a different name, such as if you are generating two sets of documentation. For instance, if you want to have a development set of documentation including private methods:
require 'rdoc/task'
RDoc::Task.new :rdoc_dev do |rdoc|
rdoc.main = "README.doc"
rdoc.rdoc_files.include("README.rdoc", "lib/ *.rb")
rdoc.options << "--all"
end
The tasks would then be named :rdoc_dev, :clobber_rdoc_dev, and :rerdoc_dev.
If you wish to have completely different task names, then pass a Hash as first argument. With the :rdoc, :clobber_rdoc and :rerdoc options, you can customize the task names to your liking.
For example:
require 'rdoc/task'
RDoc::Task.new(:rdoc => "rdoc", :clobber_rdoc => "rdoc:clean",
:rerdoc => "rdoc:force")
This will create the tasks :rdoc, :rdoc:clean and :rdoc:force.
This class needs:
Documentation
Work! Not all types of attlists are intelligently parsed, so we just
spew back out what we get in. This works, but it would be better if we formatted the output ourselves.
AttlistDecls provide just enough support to allow namespace declarations. If you need some sort of generalized support, or have an interesting idea about how to map the hideous, terrible design of DTD AttlistDecls onto an intuitive Ruby interface, let me know. I'm desperate for anything to make DTDs more palateable.
Defines an Element Attribute; IE, a attribute=value pair, as in: <element attribute=“value”/>. Attributes can be in their own namespaces. General users of REXML will not interact with the Attribute class much.
A class that defines the set of Attributes of an Element and provides operations for accessing elements in that set.
A Child object is something contained by a parent, and this class contains methods to support that. Most user code will not use this class directly.
Represents an XML comment; that is, text between <!– … –>
This is an abstract class. You never use this directly; it serves as a parent class for the specific declarations.
Represents an XML DOCTYPE declaration; that is, the contents of <!DOCTYPE … >. DOCTYPES can be used to declare the DTD of a document, as well as being used to declare entities used in the document.
Represents a full XML document, including PIs, a doctype, etc. A Document has a single child that can be accessed by root(). Note that if you want to have an XML declaration written for a document you create, you must add one; REXML documents do not write a default declaration for you. See |DECLARATION| and |write|.
Represents a tagged XML element. Elements are characterized by having children, attributes, and names, and can themselves be children.
A class which provides filtering of children for Elements, and XPath search support. You are expected to only encounter this class as the element.elements object. Therefore, you are not expected to instantiate this yourself.
Pretty-prints an XML document. This destroys whitespace in text nodes and will insert carriage returns and indentations.
TODO: Add an option to print attributes on new lines
The Transitive formatter writes an XML document that parses to an identical document as the source document. This means that no extra whitespace nodes are inserted, and whitespace within text nodes is preserved. Within these constraints, the document is pretty-printed, with whitespace inserted into the metadata to introduce formatting.
Note that this is only useful if the original XML is not already formatted. Since this formatter does not alter whitespace nodes, the results of formatting already formatted XML will be odd.
A Source that wraps an IO. See the Source class for method documentation
Represents an XML Instruction; IE, <? … ?> TODO: Add parent arg (3rd arg) to constructor
Represents a tagged XML element. Elements are characterized by having children, attributes, and names, and can themselves be children.
A parent has children, and has methods for accessing them. The Parent class is never encountered except as the superclass for some other object.
Using the Pull Parser¶ ↑
This API is experimental, and subject to change.
parser = PullParser.new( "<a>text<b att='val'/>txet</a>" )
while parser.has_next?
res = parser.next
puts res[1]['att'] if res.start_tag? and res[0] == 'b'
end
See the PullEvent class for information on the content of the results. The data is identical to the arguments passed for the various events to the StreamListener API.
Notice that:
parser = PullParser.new( "<a>BAD DOCUMENT" )
while parser.has_next?
res = parser.next
raise res[1] if res.error?
end
Nat Price gave me some good ideas for the API.
A parsing event. The contents of the event are accessed as an +Array?, and the type is given either by the …? methods, or by accessing the type accessor. The contents of this object vary from event to event, but are identical to the arguments passed to +StreamListener+s for each event.
Using the Pull Parser¶ ↑
This API is experimental, and subject to change.
parser = PullParser.new( "<a>text<b att='val'/>txet</a>" )
while parser.has_next?
res = parser.next
puts res[1]['att'] if res.start_tag? and res[0] == 'b'
end
See the PullEvent class for information on the content of the results. The data is identical to the arguments passed for the various events to the StreamListener API.
Notice that:
parser = PullParser.new( "<a>BAD DOCUMENT" )
while parser.has_next?
res = parser.next
raise res[1] if res.error?
end
Nat Price gave me some good ideas for the API.
SAX2Parser
You don't want to use this class. Really. Use XPath, which is a wrapper for this class. Believe me. You don't want to poke around in here. There is strange, dark magic at work in this code. Beware. Go back! Go back while you still can!
A Source can be searched for patterns, and wraps buffers and other objects and provides consumption of text
Generates Source-s. USE THIS CLASS.
Represents text nodes in an XML document
Implemented:
empty
element
attribute
text
optional
choice
oneOrMore
zeroOrMore
group
value
interleave
mixed
ref
grammar
start
define
Not implemented:
data
param
include
externalRef
notAllowed
anyName
nsName
except
name
NEEDS DOCUMENTATION
Wrapper class. Use this class to access the XPath functions.
@private
You don't want to use this class. Really. Use XPath, which is a wrapper for this class. Believe me. You don't want to poke around in here. There is strange, dark magic at work in this code. Beware. Go back! Go back while you still can!
Defines a top-level Atom Entry element, used as the document element of a stand-alone Atom Entry Document. It has the following attributes:
author
category
categories
content
contributor
id
link
published
rights
source
summary
title
updated
Reference: validator.w3.org/feed/docs/rfc4287.html#element.entry]
Defines the top-level element of an Atom Feed Document. It consists of a number of children Entry elements, and has the following attributes:
author
categories
category
content
contributor
entries (aliased as items)
entry
generator
icon
id
link
logo
rights
subtitle
title
updated
Reference: validator.w3.org/feed/docs/rfc4287.html#element.feed
PersonConstruct that contains information regarding the author of a Feed or Entry.
Reference: validator.w3.org/feed/docs/rfc4287.html#element.author
Contains information about a category associated with a Feed or Entry. It has the following attributes:
term
scheme
label
Reference: validator.w3.org/feed/docs/rfc4287.html#element.category
PersonConstruct that contains information regarding the contributors of a Feed or Entry.
Reference: validator.w3.org/feed/docs/rfc4287.html#element.contributor
Defines a child Atom Entry element of an Atom Feed element. It has the following attributes:
author
category
categories
content
contributor
id
link
published
rights
source
summary
title
updated
Reference: validator.w3.org/feed/docs/rfc4287.html#element.entry
Contains or links to the content of the Entry. It has the following attributes:
type
src
Reference: validator.w3.org/feed/docs/rfc4287.html#element.content
DateConstruct that usually indicates the time of the initial creation of an Entry.
Reference: validator.w3.org/feed/docs/rfc4287.html#element.published
Defines a Atom Source element. It has the following attributes:
author
category
categories
content
contributor
generator
icon
id
link
logo
rights
subtitle
title
updated
Reference: validator.w3.org/feed/docs/rfc4287.html#element.source
TextConstruct that describes a summary of the Entry.
Reference: validator.w3.org/feed/docs/rfc4287.html#element.summary
Contains information on the agent used to generate the feed.
Reference: validator.w3.org/feed/docs/rfc4287.html#element.generator
Defines an image that provides a visual identification for a eed. The image should have an aspect ratio of 1:1.
Reference: validator.w3.org/feed/docs/rfc4287.html#element.icon
Defines the Universally Unique Identifier (UUID) for a Feed or Entry.
Reference: validator.w3.org/feed/docs/rfc4287.html#element.id
Defines a reference to a Web resource. It has the following attributes:
href
rel
type
hreflang
title
length
Reference: validator.w3.org/feed/docs/rfc4287.html#element.link
Defines an image that provides a visual identification for the Feed. The image should have an aspect ratio of 2:1 (horizontal:vertical).
Reference: validator.w3.org/feed/docs/rfc4287.html#element.logo
TextConstruct that contains copyright information regarding the content in an Entry or Feed. It should not be used to convey machine readable licensing information.
Reference: validator.w3.org/feed/docs/rfc4287.html#element.rights
TextConstruct that conveys a description or subtitle for a Feed.
Reference: validator.w3.org/feed/docs/rfc4287.html#element.subtitle
TextConstruct that conveys a description or title for a Feed or Entry.
Reference: validator.w3.org/feed/docs/rfc4287.html#element.title
DateConstruct indicating the most recent time when a Feed or Entry was modified in a way the publisher considers significant.
Reference: validator.w3.org/feed/docs/rfc4287.html#element.updated
The email of the person or entity.
Reference: validator.w3.org/feed/docs/rfc4287.html#element.email
The name of the person or entity.
Reference: validator.w3.org/feed/docs/rfc4287.html#element.name
The URI of the person or entity.
Reference: validator.w3.org/feed/docs/rfc4287.html#element.uri
Raised when a conversion failure occurs.
The basic error all other RSS errors stem from. Rescue this error if you want to handle any given RSS error and you don't care about the details.
The InvalidRSSError error is the base class for a variety of errors related to a poorly-formed RSS feed. Rescue this error if you only care that a file could be invalid, but don't care how it is invalid.
Certain attributes are required on specific tags in an RSS feed. If a feed is missing one of these attributes, a MissingAttributeError is raised.
Since RSS is based on XML, it must have opening and closing tags that match. If they don't, a MissingTagError will be raised.
Attributes are in key-value form, and if there's no value provided for an attribute, a NotAvailableValueError will be raised.
Raised when an unexpected tag is encountered.
Raised when a required variable is not set.
RSS, being an XML-based format, has namespace support. If two namespaces are declared with the same name, an OverlappedPrefixError will be raised.
Some tags must only exist a specific number of times in a given RSS feed. If a feed has too many occurrences of one of these tags, a TooMuchTagError will be raised.
Raised when an unknown conversion error occurs.
RSS does not allow for free-form tag names, so if an RSS feed contains a tag that we don't know about, an UnknownTagError is raised.
Raised when a RSS::Maker attempts to use an unknown maker.
Random provides an interface to Ruby's pseudo-random number generator, or PRNG. The PRNG produces a deterministic sequence of bits which approximate true randomness. The sequence may be represented by integers, floats, or binary strings.
The generator may be initialized with either a system-generated or user-supplied seed value by using Random.srand.
The class method Random.rand provides the base functionality of Kernel.rand along with better handling of floating point values. These are both interfaces to Random::DEFAULT, the Ruby system PRNG.
Random.new will create a new PRNG with a state independent of Random::DEFAULT, allowing multiple generators with different seed values or sequence positions to exist simultaneously. Random objects can be marshaled, allowing sequences to be saved and resumed.
PRNGs are currently implemented as a modified Mersenne Twister with a period of 2**19937-1.
A Range represents an interval—a set of values with a beginning and an end. Ranges may be constructed using the s..e and s...e literals, or with Range::new. Ranges constructed using .. run from the beginning to the end inclusively. Those created using ... exclude the end value. When used as an iterator, ranges return each value in the sequence.
(-1..-5).to_a #=> []
(-5..-1).to_a #=> [-5, -4, -3, -2, -1]
('a'..'e').to_a #=> ["a", "b", "c", "d", "e"]
('a'...'e').to_a #=> ["a", "b", "c", "d"]
Endless Ranges¶ ↑
An “endless range” represents a semi-infinite range. Literal notation for an endless range is:
(1..)
# or similarly
(1...)
Which is equivalent to
(1..nil) # or similarly (1...nil)
Range.new(1, nil) # or Range.new(1, nil, true)
Endless ranges are useful, for example, for idiomatic slicing of arrays:
[1, 2, 3, 4, 5][2...] # => [3, 4, 5]
Some implementation details:
end of endless range is nil;
each of endless range enumerates infinite sequence (may be useful in combination with Enumerable#take_while or similar methods);
(1..) and (1...) are not equal, although technically representing the same sequence.
Custom Objects in Ranges¶ ↑
Ranges can be constructed using any objects that can be compared using the <=> operator. Methods that treat the range as a sequence (#each and methods inherited from Enumerable) expect the begin object to implement a succ method to return the next object in sequence. The step and include? methods require the begin object to implement succ or to be numeric.
In the Xs class below both <=> and succ are implemented so Xs can be used to construct ranges. Note that the Comparable module is included so the == method is defined in terms of <=>.
class Xs # represent a string of 'x's
include Comparable
attr :length
def initialize(n)
@length = n
end
def succ
Xs.new(@length + 1)
end
def <=>(other)
@length <=> other.length
end
def to_s
sprintf "%2d #{inspect}", @length
end
def inspect
'x' * @length
end
end
An example of using Xs to construct a range:
r = Xs.new(3)..Xs.new(6) #=> xxx..xxxxxx
r.to_a #=> [xxx, xxxx, xxxxx, xxxxxx]
r.member?(Xs.new(5)) #=> true
Raised when a given numerical value is out of range.
[1, 2, 3].drop(1 << 100)
raises the exception:
RangeError: bignum too big to convert into `long'
A rational number can be represented as a pair of integer numbers: a/b (b>0), where a is the numerator and b is the denominator. Integer a equals rational a/1 mathematically.
In Ruby, you can create rational objects with the Kernel#Rational, to_r, or rationalize methods or by suffixing r to a literal. The return values will be irreducible fractions.
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 objects 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 programs 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 includes an inexact component (numerical value or operation), it 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)
A Regexp holds a regular expression, used to match a pattern against strings. Regexps are created using the /.../ and %r{...} literals, and by the Regexp::new constructor.
Regular expressions (regexps) are patterns which describe the contents of a string. They're used for testing whether a string contains a given pattern, or extracting the portions that match. They are created with the /pat/ and %r{pat} literals or the Regexp.new constructor.
A regexp is usually delimited with forward slashes (/). For example:
/hay/ =~ 'haystack' #=> 0
/y/.match('haystack') #=> #<MatchData "y">
If a string contains the pattern it is said to match. A literal string matches itself.
Here 'haystack' does not contain the pattern 'needle', so it doesn't match:
/needle/.match('haystack') #=> nil
Here 'haystack' contains the pattern 'hay', so it matches:
/hay/.match('haystack') #=> #<MatchData "hay">
Specifically, /st/ requires that the string contains the letter s followed by the letter t, so it matches haystack, also.
=~ and Regexp#match¶ ↑
Pattern matching may be achieved by using =~ operator or Regexp#match method.
=~ operator¶ ↑
=~ is Ruby's basic pattern-matching operator. When one operand is a regular expression and the other is a string then the regular expression is used as a pattern to match against the string. (This operator is equivalently defined by Regexp and String so the order of String and Regexp do not matter. Other classes may have different implementations of =~.) If a match is found, the operator returns index of first match in string, otherwise it returns nil.
/hay/ =~ 'haystack' #=> 0
'haystack' =~ /hay/ #=> 0
/a/ =~ 'haystack' #=> 1
/u/ =~ 'haystack' #=> nil
Using =~ operator with a String and Regexp the $~ global variable is set after a successful match. $~ holds a MatchData object. Regexp.last_match is equivalent to $~.
Regexp#match method¶ ↑
The match method returns a MatchData object:
/st/.match('haystack') #=> #<MatchData "st">
Metacharacters and Escapes¶ ↑
The following are metacharacters (, ), [, ], {, }, ., ?, +, *. They have a specific meaning when appearing in a pattern. To match them literally they must be backslash-escaped. To match a backslash literally, backslash-escape it: \\.
/1 \+ 2 = 3\?/.match('Does 1 + 2 = 3?') #=> #<MatchData "1 + 2 = 3?">
/a\\\\b/.match('a\\\\b') #=> #<MatchData "a\\b">
Patterns behave like double-quoted strings so can contain the same backslash escapes.
/\s\u{6771 4eac 90fd}/.match("Go to 東京都")
#=> #<MatchData " 東京都">
Arbitrary Ruby expressions can be embedded into patterns with the #{...} construct.
place = "東京都"
/#{place}/.match("Go to 東京都")
#=> #<MatchData "東京都">
Character Classes¶ ↑
A character class is delimited with square brackets ([, ]) and lists characters that may appear at that point in the match. /[ab]/ means a or b, as opposed to /ab/ which means a followed by b.
/W[aeiou]rd/.match("Word") #=> #<MatchData "Word">
Within a character class the hyphen (-) is a metacharacter denoting an inclusive range of characters. [abcd] is equivalent to [a-d]. A range can be followed by another range, so [abcdwxyz] is equivalent to [a-dw-z]. The order in which ranges or individual characters appear inside a character class is irrelevant.
/[0-9a-f]/.match('9f') #=> #<MatchData "9">
/[9f]/.match('9f') #=> #<MatchData "9">
If the first character of a character class is a caret (^) the class is inverted: it matches any character except those named.
/[^a-eg-z]/.match('f') #=> #<MatchData "f">
A character class may contain another character class. By itself this isn't useful because [a-z[0-9]] describes the same set as [a-z0-9]. However, character classes also support the && operator which performs set intersection on its arguments. The two can be combined as follows:
/[a-w&&[^c-g]z]/ # ([a-w] AND ([^c-g] OR z))
This is equivalent to:
/[abh-w]/
The following metacharacters also behave like character classes:
/./ - Any character except a newline.
/./m - Any character (the m modifier enables multiline mode)
/\w/ - A word character ([a-zA-Z0-9_])
/\W/ - A non-word character ([^a-zA-Z0-9_]). Please take a look at Bug #4044 if using /\W/ with the /i modifier.
/\d/ - A digit character ([0-9])
/\D/ - A non-digit character ([^0-9])
/\h/ - A hexdigit character ([0-9a-fA-F])
/\H/ - A non-hexdigit character ([^0-9a-fA-F])
/\s/ - A whitespace character: /[ \t\r\n\f\v]/
/\S/ - A non-whitespace character: /[^ \t\r\n\f\v]/
POSIX bracket expressions are also similar to character classes. They provide a portable alternative to the above, with the added benefit that they encompass non-ASCII characters. For instance, /\d/ matches only the ASCII decimal digits (0-9); whereas /[[:digit:]]/ matches any character in the Unicode Nd category.
/[[:alnum:]]/ - Alphabetic and numeric character
/[[:alpha:]]/ - Alphabetic character
/[[:blank:]]/ - Space or tab
/[[:cntrl:]]/ - Control character
/[[:digit:]]/ - Digit
/[[:graph:]]/ - Non-blank character (excludes spaces, control characters, and similar)
/[[:lower:]]/ - Lowercase alphabetical character
/[[:print:]]/ - Like [:graph:], but includes the space character
/[[:punct:]]/ - Punctuation character
/[[:space:]]/ - Whitespace character ([:blank:], newline, carriage return, etc.)
/[[:upper:]]/ - Uppercase alphabetical
/[[:xdigit:]]/ - Digit allowed in a hexadecimal number (i.e., 0-9a-fA-F)
Ruby also supports the following non-POSIX character classes:
/[[:word:]]/ - A character in one of the following Unicode general categories Letter, Mark, Number, Connector_Punctuation
/[[:ascii:]]/ - A character in the ASCII character set
# U+06F2 is "EXTENDED ARABIC-INDIC DIGIT TWO"
/[[:digit:]]/.match("\u06F2") #=> #<MatchData "\u{06F2}">
/[[:upper:]][[:lower:]]/.match("Hello") #=> #<MatchData "He">
/[[:xdigit:]][[:xdigit:]]/.match("A6") #=> #<MatchData "A6">
Repetition¶ ↑
The constructs described so far match a single character. They can be followed by a repetition metacharacter to specify how many times they need to occur. Such metacharacters are called quantifiers.
* - Zero or more times
+ - One or more times
? - Zero or one times (optional)
{n} - Exactly n times
{n,} - n or more times
{,m} - m or less times
{n,m} - At least n and at most m times
At least one uppercase character ('H'), at least one lowercase character ('e'), two 'l' characters, then one 'o':
"Hello".match(/[[:upper:]]+[[:lower:]]+l{2}o/) #=> #<MatchData "Hello">
Repetition is greedy by default: as many occurrences as possible are matched while still allowing the overall match to succeed. By contrast, lazy matching makes the minimal amount of matches necessary for overall success. A greedy metacharacter can be made lazy by following it with ?.
Both patterns below match the string. The first uses a greedy quantifier so '.+' matches '<a><b>'; the second uses a lazy quantifier so '.+?' matches '<a>':
/<.+>/.match("<a><b>") #=> #<MatchData "<a><b>">
/<.+?>/.match("<a><b>") #=> #<MatchData "<a>">
A quantifier followed by + matches possessively: once it has matched it does not backtrack. They behave like greedy quantifiers, but having matched they refuse to “give up” their match even if this jeopardises the overall match.
Capturing¶ ↑
Parentheses can be used for capturing. The text enclosed by the n<sup>th</sup> group of parentheses can be subsequently referred to with n. Within a pattern use the backreference \n; outside of the pattern use MatchData[n].
'at' is captured by the first group of parentheses, then referred to later with \1:
/[csh](..) [csh]\1 in/.match("The cat sat in the hat")
#=> #<MatchData "cat sat in" 1:"at">
Regexp#match returns a MatchData object which makes the captured text available with its [] method:
/[csh](..) [csh]\1 in/.match("The cat sat in the hat")[1] #=> 'at'
Capture groups can be referred to by name when defined with the (?<name>) or (?'name') constructs.
/\$(?<dollars>\d+)\.(?<cents>\d+)/.match("$3.67")
#=> #<MatchData "$3.67" dollars:"3" cents:"67">
/\$(?<dollars>\d+)\.(?<cents>\d+)/.match("$3.67")[:dollars] #=> "3"
Named groups can be backreferenced with \k<name>, where name is the group name.
/(?<vowel>[aeiou]).\k<vowel>.\k<vowel>/.match('ototomy')
#=> #<MatchData "ototo" vowel:"o">
Note: A regexp can't use named backreferences and numbered backreferences simultaneously.
When named capture groups are used with a literal regexp on the left-hand side of an expression and the =~ operator, the captured text is also assigned to local variables with corresponding names.
/\$(?<dollars>\d+)\.(?<cents>\d+)/ =~ "$3.67" #=> 0
dollars #=> "3"
Grouping¶ ↑
Parentheses also group the terms they enclose, allowing them to be quantified as one atomic whole.
The pattern below matches a vowel followed by 2 word characters:
/[aeiou]\w{2}/.match("Caenorhabditis elegans") #=> #<MatchData "aen">
Whereas the following pattern matches a vowel followed by a word character, twice, i.e. [aeiou]\w[aeiou]\w: 'enor'.
/([aeiou]\w){2}/.match("Caenorhabditis elegans")
#=> #<MatchData "enor" 1:"or">
The (?:…) construct provides grouping without capturing. That is, it combines the terms it contains into an atomic whole without creating a backreference. This benefits performance at the slight expense of readability.
The first group of parentheses captures 'n' and the second 'ti'. The second group is referred to later with the backreference \2:
/I(n)ves(ti)ga\2ons/.match("Investigations")
#=> #<MatchData "Investigations" 1:"n" 2:"ti">
The first group of parentheses is now made non-capturing with '?:', so it still matches 'n', but doesn't create the backreference. Thus, the backreference \1 now refers to 'ti'.
/I(?:n)ves(ti)ga\1ons/.match("Investigations")
#=> #<MatchData "Investigations" 1:"ti">
Atomic Grouping¶ ↑
Grouping can be made atomic with (?>pat). This causes the subexpression pat to be matched independently of the rest of the expression such that what it matches becomes fixed for the remainder of the match, unless the entire subexpression must be abandoned and subsequently revisited. In this way pat is treated as a non-divisible whole. Atomic grouping is typically used to optimise patterns so as to prevent the regular expression engine from backtracking needlessly.
The " in the pattern below matches the first character of the string, then .* matches Quote“. This causes the overall match to fail, so the text matched by .* is backtracked by one position, which leaves the final character of the string available to match "
/".*"/.match('"Quote"') #=> #<MatchData "\"Quote\"">
If .* is grouped atomically, it refuses to backtrack Quote“, even though this means that the overall match fails
/"(?>.*)"/.match('"Quote"') #=> nil
Subexpression Calls¶ ↑
The \g<name> syntax matches the previous subexpression named name, which can be a group name or number, again. This differs from backreferences in that it re-executes the group rather than simply trying to re-match the same text.
This pattern matches a ( character and assigns it to the paren group, tries to call that the paren sub-expression again but fails, then matches a literal ):
/\A(?<paren>\(\g<paren>*\))*\z/ =~ '()'
/\A(?<paren>\(\g<paren>*\))*\z/ =~ '(())' #=> 0
# ^1
# ^2
# ^3
# ^4
# ^5
# ^6
# ^7
# ^8
# ^9
# ^10
Matches at the beginning of the string, i.e. before the first character.
Enters a named capture group called paren
Matches a literal (, the first character in the string
Calls the paren group again, i.e. recurses back to the second step
Re-enters the paren group
Matches a literal (, the second character in the string
Try to call paren a third time, but fail because doing so would prevent an overall successful match
Match a literal ), the third character in the string. Marks the end of the second recursive call
Match a literal ), the fourth character in the string
Match the end of the string
Alternation¶ ↑
The vertical bar metacharacter (|) combines two expressions into a single one that matches either of the expressions. Each expression is an alternative.
/\w(and|or)\w/.match("Feliformia") #=> #<MatchData "form" 1:"or">
/\w(and|or)\w/.match("furandi") #=> #<MatchData "randi" 1:"and">
/\w(and|or)\w/.match("dissemblance") #=> nil
Character Properties¶ ↑
The \p{} construct matches characters with the named property, much like POSIX bracket classes.
/\p{Alnum}/ - Alphabetic and numeric character
/\p{Alpha}/ - Alphabetic character
/\p{Blank}/ - Space or tab
/\p{Cntrl}/ - Control character
/\p{Digit}/ - Digit
/\p{Graph}/ - Non-blank character (excludes spaces, control characters, and similar)
/\p{Lower}/ - Lowercase alphabetical character
/\p{Print}/ - Like \p{Graph}, but includes the space character
/\p{Punct}/ - Punctuation character
/\p{Space}/ - Whitespace character ([:blank:], newline, carriage return, etc.)
/\p{Upper}/ - Uppercase alphabetical
/\p{XDigit}/ - Digit allowed in a hexadecimal number (i.e., 0-9a-fA-F)
/\p{Word}/ - A member of one of the following Unicode general category Letter, Mark, Number, Connector_Punctuation
/\p{ASCII}/ - A character in the ASCII character set
/\p{Any}/ - Any Unicode character (including unassigned characters)
/\p{Assigned}/ - An assigned character
A Unicode character's General Category value can also be matched with \p{Ab} where Ab is the category's abbreviation as described below:
/\p{L}/ - 'Letter'
/\p{Ll}/ - 'Letter: Lowercase'
/\p{Lm}/ - 'Letter: Mark'
/\p{Lo}/ - 'Letter: Other'
/\p{Lt}/ - 'Letter: Titlecase'
/\p{Lu}/ - 'Letter: Uppercase
/\p{Lo}/ - 'Letter: Other'
/\p{M}/ - 'Mark'
/\p{Mn}/ - 'Mark: Nonspacing'
/\p{Mc}/ - 'Mark: Spacing Combining'
/\p{Me}/ - 'Mark: Enclosing'
/\p{N}/ - 'Number'
/\p{Nd}/ - 'Number: Decimal Digit'
/\p{Nl}/ - 'Number: Letter'
/\p{No}/ - 'Number: Other'
/\p{P}/ - 'Punctuation'
/\p{Pc}/ - 'Punctuation: Connector'
/\p{Pd}/ - 'Punctuation: Dash'
/\p{Ps}/ - 'Punctuation: Open'
/\p{Pe}/ - 'Punctuation: Close'
/\p{Pi}/ - 'Punctuation: Initial Quote'
/\p{Pf}/ - 'Punctuation: Final Quote'
/\p{Po}/ - 'Punctuation: Other'
/\p{S}/ - 'Symbol'
/\p{Sm}/ - 'Symbol: Math'
/\p{Sc}/ - 'Symbol: Currency'
/\p{Sc}/ - 'Symbol: Currency'
/\p{Sk}/ - 'Symbol: Modifier'
/\p{So}/ - 'Symbol: Other'
/\p{Z}/ - 'Separator'
/\p{Zs}/ - 'Separator: Space'
/\p{Zl}/ - 'Separator: Line'
/\p{Zp}/ - 'Separator: Paragraph'
/\p{C}/ - 'Other'
/\p{Cc}/ - 'Other: Control'
/\p{Cf}/ - 'Other: Format'
/\p{Cn}/ - 'Other: Not Assigned'
/\p{Co}/ - 'Other: Private Use'
/\p{Cs}/ - 'Other: Surrogate'
Lastly, \p{} matches a character's Unicode script. The following scripts are supported: Arabic, Armenian, Balinese, Bengali, Bopomofo, Braille, Buginese, Buhid, Canadian_Aboriginal, Carian, Cham, Cherokee, Common, Coptic, Cuneiform, Cypriot, Cyrillic, Deseret, Devanagari, Ethiopic, Georgian, Glagolitic, Gothic, Greek, Gujarati, Gurmukhi, Han, Hangul, Hanunoo, Hebrew, Hiragana, Inherited, Kannada, Katakana, Kayah_Li, Kharoshthi, Khmer, Lao, Latin, Lepcha, Limbu, Linear_B, Lycian, Lydian, Malayalam, Mongolian, Myanmar, New_Tai_Lue, Nko, Ogham, Ol_Chiki, Old_Italic, Old_Persian, Oriya, Osmanya, Phags_Pa, Phoenician, Rejang, Runic, Saurashtra, Shavian, Sinhala, Sundanese, Syloti_Nagri, Syriac, Tagalog, Tagbanwa, Tai_Le, Tamil, Telugu, Thaana, Thai, Tibetan, Tifinagh, Ugaritic, Vai, and Yi.
Unicode codepoint U+06E9 is named “ARABIC PLACE OF SAJDAH” and belongs to the Arabic script:
/\p{Arabic}/.match("\u06E9") #=> #<MatchData "\u06E9">
All character properties can be inverted by prefixing their name with a caret (^).
Letter 'A' is not in the Unicode Ll (Letter; Lowercase) category, so this match succeeds:
/\p{^Ll}/.match("A") #=> #<MatchData "A">
Anchors¶ ↑
Anchors are metacharacter that match the zero-width positions between characters, anchoring the match to a specific position.
^ - Matches beginning of line
$ - Matches end of line
\A - Matches beginning of string.
\Z - Matches end of string. If string ends with a newline, it matches just before newline
\z - Matches end of string
\G - Matches first matching position:
In methods like String#gsub and String#scan, it changes on each iteration. It initially matches the beginning of subject, and in each following iteration it matches where the last match finished.
" a b c".gsub(/ /, '_') #=> "____a_b_c"
" a b c".gsub(/\G /, '_') #=> "____a b c"
In methods like Regexp#match and String#match that take an (optional) offset, it matches where the search begins.
"hello, world".match(/,/, 3) #=> #<MatchData ",">
"hello, world".match(/\G,/, 3) #=> nil
\b - Matches word boundaries when outside brackets; backspace (0x08) when inside brackets
\B - Matches non-word boundaries
(?=pat) - Positive lookahead assertion: ensures that the following characters match pat, but doesn't include those characters in the matched text
(?!pat) - Negative lookahead assertion: ensures that the following characters do not match pat, but doesn't include those characters in the matched text
(?<=pat) - Positive lookbehind assertion: ensures that the preceding characters match pat, but doesn't include those characters in the matched text
(?<!pat) - Negative lookbehind assertion: ensures that the preceding characters do not match pat, but doesn't include those characters in the matched text
If a pattern isn't anchored it can begin at any point in the string:
/real/.match("surrealist") #=> #<MatchData "real">
Anchoring the pattern to the beginning of the string forces the match to start there. 'real' doesn't occur at the beginning of the string, so now the match fails:
/\Areal/.match("surrealist") #=> nil
The match below fails because although 'Demand' contains 'and', the pattern does not occur at a word boundary.
/\band/.match("Demand")
Whereas in the following example 'and' has been anchored to a non-word boundary so instead of matching the first 'and' it matches from the fourth letter of 'demand' instead:
/\Band.+/.match("Supply and demand curve") #=> #<MatchData "and curve">
The pattern below uses positive lookahead and positive lookbehind to match text appearing in tags without including the tags in the match:
/(?<=<b>)\w+(?=<\/b>)/.match("Fortune favours the <b>bold</b>")
#=> #<MatchData "bold">
Options¶ ↑
The end delimiter for a regexp can be followed by one or more single-letter options which control how the pattern can match.
/pat/i - Ignore case
/pat/m - Treat a newline as a character matched by .
/pat/x - Ignore whitespace and comments in the pattern
/pat/o - Perform #{} interpolation only once
i, m, and x can also be applied on the subexpression level with the (?on-off) construct, which enables options on, and disables options off for the expression enclosed by the parentheses:
/a(?i:b)c/.match('aBc') #=> #<MatchData "aBc">
/a(?-i:b)c/i.match('ABC') #=> nil
Additionally, these options can also be toggled for the remainder of the pattern:
/a(?i)bc/.match('abC') #=> #<MatchData "abC">
Options may also be used with Regexp.new:
Regexp.new("abc", Regexp::IGNORECASE) #=> /abc/i
Regexp.new("abc", Regexp::MULTILINE) #=> /abc/m
Regexp.new("abc # Comment", Regexp::EXTENDED) #=> /abc # Comment/x
Regexp.new("abc", Regexp::IGNORECASE | Regexp::MULTILINE) #=> /abc/mi
Free-Spacing Mode and Comments¶ ↑
As mentioned above, the x option enables free-spacing mode. Literal white space inside the pattern is ignored, and the octothorpe (#) character introduces a comment until the end of the line. This allows the components of the pattern to be organized in a potentially more readable fashion.
A contrived pattern to match a number with optional decimal places:
float_pat = /\A
[[:digit:]]+ # 1 or more digits before the decimal point
(\. # Decimal point
[[:digit:]]+ # 1 or more digits after the decimal point
)? # The decimal point and following digits are optional
\Z/x
float_pat.match('3.14') #=> #<MatchData "3.14" 1:".14">
There are a number of strategies for matching whitespace:
Use a pattern such as \s or \p{Space}.
Use escaped whitespace such as \ , i.e. a space preceded by a backslash.
Use a character class such as [ ].
Comments can be included in a non-x pattern with the (?#comment) construct, where comment is arbitrary text ignored by the regexp engine.
Comments in regexp literals cannot include unescaped terminator characters.
Encoding¶ ↑
Regular expressions are assumed to use the source encoding. This can be overridden with one of the following modifiers.
/pat/u - UTF-8
/pat/e - EUC-JP
/pat/s - Windows-31J
/pat/n - ASCII-8BIT
A regexp can be matched against a string when they either share an encoding, or the regexp's encoding is US-ASCII and the string's encoding is ASCII-compatible.
If a match between incompatible encodings is attempted an Encoding::CompatibilityError exception is raised.
The Regexp#fixed_encoding? predicate indicates whether the regexp has a fixed encoding, that is one incompatible with ASCII. A regexp's encoding can be explicitly fixed by supplying Regexp::FIXEDENCODING as the second argument of Regexp.new:
r = Regexp.new("a".force_encoding("iso-8859-1"),Regexp::FIXEDENCODING)
r =~ "a\u3042"
# raises Encoding::CompatibilityError: incompatible encoding regexp match
# (ISO-8859-1 regexp with UTF-8 string)
Special global variables¶ ↑
Pattern matching sets some global variables :
$~ is equivalent to Regexp.last_match;
$& contains the complete matched text;
$` contains string before match;
$' contains string after match;
$1, $2 and so on contain text matching first, second, etc capture group;
$+ contains last capture group.
Example:
m = /s(\w{2}).*(c)/.match('haystack') #=> #<MatchData "stac" 1:"ta" 2:"c">
$~ #=> #<MatchData "stac" 1:"ta" 2:"c">
Regexp.last_match #=> #<MatchData "stac" 1:"ta" 2:"c">
$& #=> "stac"
# same as m[0]
$` #=> "hay"
# same as m.pre_match
$' #=> "k"
# same as m.post_match
$1 #=> "ta"
# same as m[1]
$2 #=> "c"
# same as m[2]
$3 #=> nil
# no third group in pattern
$+ #=> "c"
# same as m[-1]
These global variables are thread-local and method-local variables.
Performance¶ ↑
Certain pathological combinations of constructs can lead to abysmally bad performance.
Consider a string of 25 as, a d, 4 as, and a c.
s = 'a' * 25 + 'd' + 'a' * 4 + 'c'
#=> "aaaaaaaaaaaaaaaaaaaaaaaaadaaaac"
The following patterns match instantly as you would expect:
/(b|a)/ =~ s #=> 0
/(b|a+)/ =~ s #=> 0
/(b|a+)*/ =~ s #=> 0
However, the following pattern takes appreciably longer:
/(b|a+)*c/ =~ s #=> 26
This happens because an atom in the regexp is quantified by both an immediate + and an enclosing * with nothing to differentiate which is in control of any particular character. The nondeterminism that results produces super-linear performance. (Consult Mastering Regular Expressions (3rd ed.), pp 222, by Jeffery Friedl, for an in-depth analysis). This particular case can be fixed by use of atomic grouping, which prevents the unnecessary backtracking:
(start = Time.now) && /(b|a+)*c/ =~ s && (Time.now - start)
#=> 24.702736882
(start = Time.now) && /(?>b|a+)*c/ =~ s && (Time.now - start)
#=> 0.000166571
A similar case is typified by the following example, which takes approximately 60 seconds to execute for me:
Match a string of 29 as against a pattern of 29 optional as followed by 29 mandatory as:
Regexp.new('a?' * 29 + 'a' * 29) =~ 'a' * 29
The 29 optional as match the string, but this prevents the 29 mandatory as that follow from matching. Ruby must then backtrack repeatedly so as to satisfy as many of the optional matches as it can while still matching the mandatory 29. It is plain to us that none of the optional matches can succeed, but this fact unfortunately eludes Ruby.
The best way to improve performance is to significantly reduce the amount of backtracking needed. For this case, instead of individually matching 29 optional as, a range of optional as can be matched all at once with a{0,29}:
Regexp.new('a{0,29}' + 'a' * 29) =~ 'a' * 29
Raised when given an invalid regexp expression.
Regexp.new("?")
raises the exception:
RegexpError: target of repeat operator is not specified: /?/
Resolv is a thread-aware DNS resolver library written in Ruby. Resolv can handle multiple DNS requests concurrently without blocking the entire Ruby interpreter.
See also resolv-replace.rb to replace the libc resolver with Resolv.
Resolv can look up various DNS resources using the DNS module directly.
Examples:
p Resolv.getaddress "www.ruby-lang.org"
p Resolv.getname "210.251.121.214"
Resolv::DNS.open do |dns|
ress = dns.getresources "www.ruby-lang.org", Resolv::DNS::Resource::IN::A
p ress.map(&:address)
ress = dns.getresources "ruby-lang.org", Resolv::DNS::Resource::IN::MX
p ress.map { |r| [r.exchange.to_s, r.preference] }
end
Bugs¶ ↑
NIS is not supported.
/etc/nsswitch.conf is not supported.
Resolv::DNS is a DNS stub resolver.
Information taken from the following places:
STD0013
RFC 1035
ftp.isi.edu/in-notes/iana/assignments/dns-parameters
etc.
Indicates no such domain was found.
Indicates some other unhandled resolver error was encountered.
Indicates that the DNS response was unable to be decoded.
Indicates that the DNS request was unable to be encoded.
A representation of a DNS name.
A DNS query abstract class.
Indicates a problem with the DNS request.
A DNS resource abstract class.
A Query type requesting any RR.
The canonical name for an alias.
Domain Name resource abstract class.
A generic resource abstract class.
Host Information resource.
IPv4 Address resource
An IPv6 address record.
SRV resource record defined in RFC 2782
These records identify the hostname and port that a service is available at.
Well Known Service resource.
Location resource
Mailing list or mailbox information.
Mail Exchanger resource.
An authoritative name server.
A Pointer to another DNS name.
Start Of Authority resource.
Unstructured text resource.
Resolv::Hosts is a hostname resolver that uses the system hosts file.
A Resolv::DNS IPv4 address.
A Resolv::DNS IPv6 address.
A Resolv::LOC::Alt
A Resolv::LOC::Coord
A Resolv::LOC::Size
Resolv::MDNS is a one-shot Multicast DNS (mDNS) resolver. It blindly makes queries to the mDNS addresses without understanding anything about multicast ports.
Information taken form the following places:
RFC 6762
Indicates a failure to resolve a name or address.
Indicates a timeout resolving a name or address.
Documentation?
Raised when a hash-based tuple has an invalid key.
A NotifyTemplateEntry is returned by TupleSpace#notify and is notified of TupleSpace changes. You may receive either your subscribed event or the 'close' event when iterating over notifications.
See TupleSpace#notify_event for valid notification types.
Example¶ ↑
ts = Rinda::TupleSpace.new
observer = ts.notify 'write', [nil]
Thread.start do
observer.each { |t| p t }
end
3.times { |i| ts.write [i] }
Outputs:
['write', [0]]
['write', [1]]
['write', [2]]
Raised when trying to use a canceled tuple.
Raised when trying to use an expired tuple.
Rinda error base class
RingFinger is used by RingServer clients to discover the RingServer's TupleSpace. Typically, all a client needs to do is call RingFinger.primary to retrieve the remote TupleSpace, which it can then begin using.
To find the first available remote TupleSpace:
Rinda::RingFinger.primary
To create a RingFinger that broadcasts to a custom list:
rf = Rinda::RingFinger.new ['localhost', '192.0.2.1']
rf.primary
Rinda::RingFinger also understands multicast addresses and sets them up properly. This allows you to run multiple RingServers on the same host:
rf = Rinda::RingFinger.new ['239.0.0.1']
rf.primary
You can set the hop count (or TTL) for multicast searches using multicast_hops.
If you use IPv6 multicast you may need to set both an address and the outbound interface index:
rf = Rinda::RingFinger.new ['ff02::1']
rf.multicast_interface = 1
rf.primary
At this time there is no easy way to get an interface index by name.
RingProvider uses a RingServer advertised TupleSpace as a name service. TupleSpace clients can register themselves with the remote TupleSpace and look up other provided services via the remote TupleSpace.
Services are registered with a tuple of the format [:name, klass, DRbObject, description].
A RingServer allows a Rinda::TupleSpace to be located via UDP broadcasts. Default service location uses the following steps:
A RingServer begins listening on the network broadcast UDP address.
A RingFinger sends a UDP packet containing the DRb URI where it will listen for a reply.
The RingServer receives the UDP packet and connects back to the provided DRb URI with the DRb service.
A RingServer requires a TupleSpace:
ts = Rinda::TupleSpace.new
rs = Rinda::RingServer.new
RingServer can also listen on multicast addresses for announcements. This allows multiple RingServers to run on the same host. To use network broadcast and multicast:
ts = Rinda::TupleSpace.new
rs = Rinda::RingServer.new ts, %w[Socket::INADDR_ANY, 239.0.0.1 ff02::1]
An SimpleRenewer allows a TupleSpace to check if a TupleEntry is still alive.
Templates are used to match tuples in Rinda.
A TemplateEntry is a Template together with expiry and cancellation data.
A tuple is the elementary object in Rinda programming. Tuples may be matched against templates if the tuple and the template are the same size.
TupleBag is an unordered collection of tuples. It is the basis of Tuplespace.
A TupleEntry is a Tuple (i.e. a possible entry in some Tuplespace) together with expiry and cancellation data.
The Tuplespace manages access to the tuples it contains, ensuring mutual exclusion requirements are met.
The sec option for the write, take, move, read and notify methods may either be a number of seconds or a Renewer object.
TupleSpaceProxy allows a remote Tuplespace to appear as local.
Documentation?
Ripper is a Ruby script parser.
You can get information from the parser with event-based style. Information such as abstract syntax trees or simple lexical analysis of the Ruby program.
Usage¶ ↑
Ripper provides an easy interface for parsing your program into a symbolic expression tree (or S-expression).
Understanding the output of the parser may come as a challenge, it's recommended you use PP to format the output for legibility.
require 'ripper'
require 'pp'
pp Ripper.sexp('def hello(world) "Hello, #{world}!"; end')
#=> [:program,
[[:def,
[:@ident, "hello", [1, 4]],
[:paren,
[:params, [[:@ident, "world", [1, 10]]], nil, nil, nil, nil, nil, nil]],
[:bodystmt,
[[:string_literal,
[:string_content,
[:@tstring_content, "Hello, ", [1, 18]],
[:string_embexpr, [[:var_ref, [:@ident, "world", [1, 27]]]]],
[:@tstring_content, "!", [1, 33]]]]],
nil,
nil,
nil]]]]
You can see in the example above, the expression starts with :program.
From here, a method definition at :def, followed by the method's identifier :@ident. After the method's identifier comes the parentheses :paren and the method parameters under :params.
Next is the method body, starting at :bodystmt (stmt meaning statement), which contains the full definition of the method.
In our case, we're simply returning a String, so next we have the :string_literal expression.
Within our :string_literal you'll notice two @tstring_content, this is the literal part for Hello, and !. Between the two @tstring_content statements is a :string_embexpr, where embexpr is an embedded expression. Our expression consists of a local variable, or var_ref, with the identifier (@ident) of world.
Resources¶ ↑
Ruby Inside
Requirements¶ ↑
ruby 1.9 (support CVS HEAD only)
bison 1.28 or later (Other yaccs do not work)
License¶ ↑
Ruby License.
Minero Aoki
[email protected]
i.loveruby.net
This class handles only scanner events, which are dispatched in the 'right' order (same with input).
The RubyVM module provides some access to Ruby internals. This module is for very limited purposes, such as debugging, prototyping, and research. Normal users must not use it.
RubyVM::AbstractSyntaxTree::Node instances are created by parse methods in RubyVM::AbstractSyntaxTree.
The InstructionSequence class represents a compiled sequence of instructions for the Ruby Virtual Machine.
With it, you can get a handle to the instructions that make up a method or a proc, compile strings of Ruby code down to VM instructions, and disassemble instruction sequences to strings for easy inspection. It is mostly useful if you want to learn how the Ruby VM works, but it also lets you control various settings for the Ruby iseq compiler.
You can find the source for the VM instructions in insns.def in the Ruby source.
The instruction sequence results will almost certainly change as Ruby changes, so example output in this documentation may be different from what you see.
A generic error class raised when an invalid operation is attempted. Kernel#raise will raise a RuntimeError if no Exception class is specified.
raise "ouch"
raises the exception:
RuntimeError: ouch
SDBM provides a simple file-based key-value store, which can only store String keys and values.
Note that Ruby comes with the source code for SDBM, while the DBM and GDBM standard libraries rely on external libraries and headers.
Examples¶ ↑
Insert values:
require 'sdbm'
SDBM.open 'my_database' do |db|
db['apple'] = 'fruit'
db['pear'] = 'fruit'
db['carrot'] = 'vegetable'
db['tomato'] = 'vegetable'
end
Bulk update:
require 'sdbm'
SDBM.open 'my_database' do |db|
db.update('peach' => 'fruit', 'tomato' => 'fruit')
end
Retrieve values:
require 'sdbm'
SDBM.open 'my_database' do |db|
db.each do |key, value|
puts "Key: #{key}, Value: #{value}"
end
end
Outputs:
Key: apple, Value: fruit
Key: pear, Value: fruit
Key: carrot, Value: vegetable
Key: peach, Value: fruit
Key: tomato, Value: fruit
Exception class used to return errors from the sdbm library.
SOCKS is an Internet protocol that routes packets between a client and a server through a proxy server. SOCKS5, if supported, additionally provides authentication so only authorized users may access a server.
ScriptError is the superclass for errors raised when a script can not be executed because of a LoadError, NotImplementedError or a SyntaxError. Note these type of ScriptErrors are not StandardError and will not be rescued unless it is specified explicitly (or its ancestor Exception).
Raised when attempting a potential unsafe operation, typically when the $SAFE level is raised above 0.
foo = "bar"
proc = Proc.new do
$SAFE = 3
foo.untaint
end
proc.call
raises the exception:
SecurityError: Insecure: Insecure operation `untaint' at level 3
Set implements a collection of unordered values with no duplicates. This is a hybrid of Array's intuitive inter-operation facilities and Hash's fast lookup.
Set is easy to use with Enumerable objects (implementing each). Most of the initializer methods and binary operators accept generic Enumerable objects besides sets and arrays. An Enumerable object can be converted to Set using the to_set method.
Set uses Hash as storage, so you must note the following points:
Equality of elements is determined according to Object#eql? and Object#hash. Use Set#compare_by_identity to make a set compare its elements by their identity.
Set assumes that the identity of each element does not change while it is stored. Modifying an element of a set will render the set to an unreliable state.
When a string is to be stored, a frozen copy of the string is stored instead unless the original string is already frozen.
Comparison¶ ↑
The comparison operators <, >, <=, and >= are implemented as shorthand for the {proper_,}{subset?,superset?} methods. However, the <=> operator is intentionally left out because not every pair of sets is comparable ({x, y} vs. {x, z} for example).
Example¶ ↑
require 'set'
s1 = Set[1, 2] #=> #<Set: {1, 2}>
s2 = [1, 2].to_set #=> #<Set: {1, 2}>
s1 == s2 #=> true
s1.add("foo") #=> #<Set: {1, 2, "foo"}>
s1.merge([2, 6]) #=> #<Set: {1, 2, "foo", 6}>
s1.subset?(s2) #=> false
s2.subset?(s1) #=> true
Contact¶ ↑
- Akinori MUSHA <[email protected]> (current maintainer)
Shell implements an idiomatic Ruby interface for common UNIX shell commands.
It provides users the ability to execute commands with filters and pipes, like sh/csh by using native facilities of Ruby.
Examples¶ ↑
Temp file creation¶ ↑
In this example we will create three tmpFile's in three different folders under the /tmp directory.
sh = Shell.cd("/tmp") # Change to the /tmp directory
sh.mkdir "shell-test-1" unless sh.exists?("shell-test-1")
# make the 'shell-test-1' directory if it doesn't already exist
sh.cd("shell-test-1") # Change to the /tmp/shell-test-1 directory
for dir in ["dir1", "dir3", "dir5"]
if !sh.exists?(dir)
sh.mkdir dir # make dir if it doesn't already exist
sh.cd(dir) do
# change to the `dir` directory
f = sh.open("tmpFile", "w") # open a new file in write mode
f.print "TEST\n" # write to the file
f.close # close the file handler
end
print sh.pwd # output the process working directory
end
end
Temp file creation with self¶ ↑
This example is identical to the first, except we're using CommandProcessor#transact.
CommandProcessor#transact executes the given block against self, in this case sh; our Shell object. Within the block we can substitute sh.cd to cd, because the scope within the block uses sh already.
sh = Shell.cd("/tmp")
sh.transact do
mkdir "shell-test-1" unless exists?("shell-test-1")
cd("shell-test-1")
for dir in ["dir1", "dir3", "dir5"]
if !exists?(dir)
mkdir dir
cd(dir) do
f = open("tmpFile", "w")
f.print "TEST\n"
f.close
end
print pwd
end
end
end
Pipe /etc/printcap into a file¶ ↑
In this example we will read the operating system file /etc/printcap, generated by cupsd, and then output it to a new file relative to the pwd of sh.
sh = Shell.new
sh.cat("/etc/printcap") | sh.tee("tee1") > "tee2"
(sh.cat < "/etc/printcap") | sh.tee("tee11") > "tee12"
sh.cat("/etc/printcap") | sh.tee("tee1") >> "tee2"
(sh.cat < "/etc/printcap") | sh.tee("tee11") >> "tee12"
In order to execute a command on your OS, you need to define it as a Shell method.
Alternatively, you can execute any command via Shell::CommandProcessor#system even if it is not defined.
Any result of command execution is a Filter.
This class includes Enumerable, therefore a Filter object can use all Enumerable facilities.
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
A concrete implementation of Delegator, this class provides the means to delegate all supported method calls to the object passed into the constructor and even to change the object being delegated to at a later time with #__setobj__.
class User
def born_on
Date.new(1989, 9, 10)
end
end
class UserDecorator < SimpleDelegator
def birth_year
born_on.year
end
end
decorated_user = UserDecorator.new(User.new)
decorated_user.birth_year #=> 1989
decorated_user.__getobj__ #=> #<User: ...>
A SimpleDelegator instance can take advantage of the fact that SimpleDelegator is a subclass of Delegator to call super to have methods called on the object being delegated to.
class SuperArray < SimpleDelegator
def [](*args)
super + 1
end
end
SuperArray.new([1])[0] #=> 2
Here's a simple example that takes advantage of the fact that SimpleDelegator's delegation object can be changed at any time.
class Stats
def initialize
@source = SimpleDelegator.new([])
end
def stats(records)
@source.__setobj__(records)
"Elements: #{@source.size}\n" +
" Non-Nil: #{@source.compact.size}\n" +
" Unique: #{@source.uniq.size}\n"
end
end
s = Stats.new
puts s.stats(%w{James Edward Gray II})
puts
puts s.stats([1, 2, 3, nil, 4, 5, 1, 2])
Prints:
Elements: 4
Non-Nil: 4
Unique: 4
Elements: 8
Non-Nil: 7
Unique: 6
This class represents queues of specified size capacity. The push operation may be blocked if the capacity is full.
See Queue for an example of how a SizedQueue works.
Class Socket provides access to the underlying operating system socket implementations. It can be used to provide more operating system specific functionality than the protocol-specific socket classes.
The constants defined under Socket::Constants are also defined under Socket. For example, Socket::AF_INET is usable as well as Socket::Constants::AF_INET. See Socket::Constants for the list of constants.
What's a socket?¶ ↑
Sockets are endpoints of a bidirectional communication channel. Sockets can communicate within a process, between processes on the same machine or between different machines. There are many types of socket: TCPSocket, UDPSocket or UNIXSocket for example.
Sockets have their own vocabulary:
domain: The family of protocols:
Socket::PF_INET
Socket::PF_INET6
Socket::PF_UNIX
etc.
type: The type of communications between the two endpoints, typically
Socket::SOCK_STREAM
Socket::SOCK_DGRAM.
protocol: Typically zero. This may be used to identify a variant of a protocol.
hostname: The identifier of a network interface:
a string (hostname, IPv4 or IPv6 address or broadcast which specifies a broadcast address)
a zero-length string which specifies INADDR_ANY
an integer (interpreted as binary address in host byte order).
Quick start¶ ↑
Many of the classes, such as TCPSocket, UDPSocket or UNIXSocket, ease the use of sockets comparatively to the equivalent C programming interface.
Let's create an internet socket using the IPv4 protocol in a C-like manner:
require 'socket'
s = Socket.new Socket::AF_INET, Socket::SOCK_STREAM
s.connect Socket.pack_sockaddr_in(80, 'example.com')
You could also use the TCPSocket class:
s = TCPSocket.new 'example.com', 80
A simple server might look like this:
require 'socket'
server = TCPServer.new 2000 # Server bound to port 2000
loop do
client = server.accept # Wait for a client to connect
client.puts "Hello !"
client.puts "Time is #{Time.now}"
client.close
end
A simple client may look like this:
require 'socket'
s = TCPSocket.new 'localhost', 2000
while line = s.gets # Read lines from socket
puts line # and print them
end
s.close # close socket when done
Exception Handling¶ ↑
Ruby's Socket implementation raises exceptions based on the error generated by the system dependent implementation. This is why the methods are documented in a way that isolate Unix-based system exceptions from Windows based exceptions. If more information on a particular exception is needed, please refer to the Unix manual pages or the Windows WinSock reference.
Convenience methods¶ ↑
Although the general way to create socket is Socket.new, there are several methods of socket creation for most cases.
TCP client socket
Socket.tcp, TCPSocket.open
TCP server socket
Socket.tcp_server_loop, TCPServer.open
UNIX client socket
Socket.unix, UNIXSocket.open
UNIX server socket
Socket.unix_server_loop, UNIXServer.open
Documentation by¶ ↑
Zach Dennis
Sam Roberts
Programming Ruby from The Pragmatic Bookshelf.
Much material in this documentation is taken with permission from Programming Ruby from The Pragmatic Bookshelf.
Socket::AncillaryData represents the ancillary data (control information) used by sendmsg and recvmsg system call. It contains socket family, control message (cmsg) level, cmsg type and cmsg data.
Socket::Ifaddr represents a result of getifaddrs() function.
Socket::Option represents a socket option used by BasicSocket#getsockopt and BasicSocket#setsockopt. A socket option contains the socket family, protocol level, option name optname and option value data.
UDP/IP address information used by Socket.udp_server_loop.
SocketError is the error class for socket.
SortedSet implements a Set that guarantees that its elements are yielded in sorted order (according to the return values of their #<=> methods) when iterating over them.
All elements that are added to a SortedSet must respond to the <=> method for comparison.
Also, all elements must be mutually comparable: el1 <=> el2 must not return nil for any elements el1 and el2, else an ArgumentError will be raised when iterating over the SortedSet.
Example¶ ↑
require "set"
set = SortedSet.new([2, 1, 5, 6, 4, 5, 3, 3, 3])
ary = []
set.each do |obj|
ary << obj
end
p ary # => [1, 2, 3, 4, 5, 6]
set2 = SortedSet.new([1, 2, "3"])
set2.each { |obj| } # => raises ArgumentError: comparison of Fixnum with String failed
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 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!
A String object holds and manipulates an arbitrary sequence of bytes, typically representing characters. String objects may be created using String::new or as literals.
Because of aliasing issues, users of strings should be aware of the methods that modify the contents of a String object. Typically, methods with names ending in “!'' modify their receiver, while those without a “!'' return a new String. However, there are exceptions, such as String#[]=.
Pseudo I/O on String object.
Commonly used to simulate `$stdio` or `$stderr`
Examples¶ ↑
require 'stringio'
io = StringIO.new
io.puts "Hello World"
io.string #=> "Hello World\n"
StringScanner provides for lexical scanning operations on a String. Here is an example of its usage:
s = StringScanner.new('This is an example string')
s.eos? # -> false
p s.scan(/\w+/) # -> "This"
p s.scan(/\w+/) # -> nil
p s.scan(/\s+/) # -> " "
p s.scan(/\s+/) # -> nil
p s.scan(/\w+/) # -> "is"
s.eos? # -> false
p s.scan(/\s+/) # -> " "
p s.scan(/\w+/) # -> "an"
p s.scan(/\s+/) # -> " "
p s.scan(/\w+/) # -> "example"
p s.scan(/\s+/) # -> " "
p s.scan(/\w+/) # -> "string"
s.eos? # -> true
p s.scan(/\s+/) # -> nil
p s.scan(/\w+/) # -> nil
Scanning a string means remembering the position of a scan pointer, which is just an index. The point of scanning is to move forward a bit at a time, so matches are sought after the scan pointer; usually immediately after it.
Given the string “test string”, here are the pertinent scan pointer positions:
t e s t s t r i n g
0 1 2 ... 1
0
When you scan for a pattern (a regular expression), the match must occur at the character after the scan pointer. If you use scan_until, then the match can occur anywhere after the scan pointer. In both cases, the scan pointer moves just beyond the last character of the match, ready to scan again from the next character onwards. This is demonstrated by the example above.
Method Categories¶ ↑
There are other methods besides the plain scanners. You can look ahead in the string without actually scanning. You can access the most recent match. You can modify the string being scanned, reset or terminate the scanner, find out or change the position of the scan pointer, skip ahead, and so on.
Advancing the Scan Pointer¶ ↑
getch
get_byte
scan
scan_until
skip
skip_until
Looking Ahead¶ ↑
check
check_until
exist?
match?
peek
Finding Where we Are¶ ↑
beginning_of_line? (#bol?)
eos?
rest?
rest_size
pos
Setting Where we Are¶ ↑
reset
terminate
pos=
Match Data¶ ↑
matched
matched?
matched_size
pre_match
post_match
Miscellaneous¶ ↑
<<
concat
string
string=
unscan
There are aliases to several of the methods.
A Struct is a convenient way to bundle a number of attributes together, using accessor methods, without having to write an explicit class.
The Struct class generates new subclasses that hold a set of members and their values. For each member a reader and writer method is created similar to Module#attr_accessor.
Customer = Struct.new(:name, :address) do
def greeting
"Hello #{name}!"
end
end
dave = Customer.new("Dave", "123 Main")
dave.name #=> "Dave"
dave.greeting #=> "Hello Dave!"
See Struct::new for further examples of creating struct subclasses and instances.
In the method descriptions that follow, a “member” parameter refers to a struct member which is either a quoted string ("name") or a Symbol (:name).
Symbol objects represent names and some strings inside the Ruby interpreter. They are generated using the :name and :"string" literals syntax, and by the various to_sym methods. The same Symbol object will be created for a given name or string for the duration of a program's execution, regardless of the context or meaning of that name. Thus if Fred is a constant in one context, a method in another, and a class in a third, the Symbol :Fred will be the same object in all three contexts.
module One
class Fred
end
$f1 = :Fred
end
module Two
Fred = 1
$f2 = :Fred
end
def Fred()
end
$f3 = :Fred
$f1.object_id #=> 2514190
$f2.object_id #=> 2514190
$f3.object_id #=> 2514190
A class that provides two-phase lock with a counter. See Sync_m for details.
exceptions
A class that provides two-phase lock with a counter. See Sync_m for details.
Raised when encountering Ruby code with an invalid syntax.
eval("1+1=2")
raises the exception:
SyntaxError: (eval):1: syntax error, unexpected '=', expecting $end
Syslog::Logger is a Logger work-alike that logs via syslog instead of to a file. You can use Syslog::Logger to aggregate logs between multiple machines.
By default, Syslog::Logger uses the program name 'ruby', but this can be changed via the first argument to Syslog::Logger.new.
NOTE! You can only set the Syslog::Logger program name when you initialize Syslog::Logger for the first time. This is a limitation of the way Syslog::Logger uses syslog (and in some ways, a limitation of the way syslog(3) works). Attempts to change Syslog::Logger's program name after the first initialization will be ignored.
Example¶ ↑
The following will log to syslogd on your local machine:
require 'syslog/logger'
log = Syslog::Logger.new 'my_program'
log.info 'this line will be logged via syslog(3)'
Also the facility may be set to specify the facility level which will be used:
log.info 'this line will be logged using Syslog default facility level'
log_local1 = Syslog::Logger.new 'my_program', Syslog::LOG_LOCAL1
log_local1.info 'this line will be logged using local1 facility level'
You may need to perform some syslog.conf setup first. For a BSD machine add the following lines to /etc/syslog.conf:
!my_program
*.* /var/log/my_program.log
Then touch /var/log/my_program.log and signal syslogd with a HUP (killall -HUP syslogd, on FreeBSD).
If you wish to have logs automatically roll over and archive, see the newsyslog.conf(5) and newsyslog(8) man pages.
Default formatter for log messages.
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
Raised by exit to initiate the termination of the script.
Raised in case of a stack overflow.
def me_myself_and_i
me_myself_and_i
end
me_myself_and_i
raises the exception:
SystemStackError: stack level too deep
TCPServer represents a TCP/IP server socket.
A simple TCP server may look like:
require 'socket'
server = TCPServer.new 2000 # Server bind to port 2000
loop do
client = server.accept # Wait for a client to connect
client.puts "Hello !"
client.puts "Time is #{Time.now}"
client.close
end
A more usable server (serving multiple clients):
require 'socket'
server = TCPServer.new 2000
loop do
Thread.start(server.accept) do |client|
client.puts "Hello !"
client.puts "Time is #{Time.now}"
client.close
end
end
TCPSocket represents a TCP/IP client socket.
A simple client may look like:
require 'socket'
s = TCPSocket.new 'localhost', 2000
while line = s.gets # Read lines from socket
puts line # and print them
end
s.close # close socket when done
A StringIO duck-typed class that uses Tempfile instead of String as the backing store.
This is available when rubygems/test_utilities is required.
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.
Synopsis¶ ↑
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
Good practices¶ ↑
Explicit close¶ ↑
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
Unlink after creation¶ ↑
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.
Minor notes¶ ↑
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.
This class watches for termination of multiple threads. Basic functionality (wait until specified threads have terminated) can be accessed through the class method ThreadsWait::all_waits. Finer control can be gained using instance methods.
Example:
ThreadsWait.all_waits(thr1, thr2, ...) do |t|
STDERR.puts "Thread #{t} has terminated."
end
th = ThreadsWait.new(thread1,...)
th.next_wait # next one to be done
Threads are the Ruby implementation for a concurrent programming model.
Programs that require multiple threads of execution are a perfect candidate for Ruby's Thread class.
For example, we can create a new thread separate from the main thread's execution using ::new.
thr = Thread.new { puts "Whats the big deal" }
Then we are able to pause the execution of the main thread and allow our new thread to finish, using join:
thr.join #=> "Whats the big deal"
If we don't call thr.join before the main thread terminates, then all other threads including thr will be killed.
Alternatively, you can use an array for handling multiple threads at once, like in the following example:
threads = []
threads << Thread.new { puts "Whats the big deal" }
threads << Thread.new { 3.times { puts "Threads are fun!" } }
After creating a few threads we wait for them all to finish consecutively.
threads.each { |thr| thr.join }
Thread initialization¶ ↑
In order to create new threads, Ruby provides ::new, ::start, and ::fork. A block must be provided with each of these methods, otherwise a ThreadError will be raised.
When subclassing the Thread class, the initialize method of your subclass will be ignored by ::start and ::fork. Otherwise, be sure to call super in your initialize method.
Thread termination¶ ↑
For terminating threads, Ruby provides a variety of ways to do this.
The class method ::kill, is meant to exit a given thread:
thr = Thread.new { ... }
Thread.kill(thr) # sends exit() to thr
Alternatively, you can use the instance method exit, or any of its aliases kill or terminate.
thr.exit
Thread status¶ ↑
Ruby provides a few instance methods for querying the state of a given thread. To get a string with the current thread's state use status
thr = Thread.new { sleep }
thr.status # => "sleep"
thr.exit
thr.status # => false
You can also use alive? to tell if the thread is running or sleeping, and stop? if the thread is dead or sleeping.
Thread variables and scope¶ ↑
Since threads are created with blocks, the same rules apply to other Ruby blocks for variable scope. Any local variables created within this block are accessible to only this thread.
Fiber-local vs. Thread-local¶ ↑
Each fiber has its own bucket for Thread#[] storage. When you set a new fiber-local it is only accessible within this Fiber. To illustrate:
Thread.new {
Thread.current[:foo] = "bar"
Fiber.new {
p Thread.current[:foo] # => nil
}.resume
}.join
This example uses [] for getting and []= for setting fiber-locals, you can also use keys to list the fiber-locals for a given thread and key? to check if a fiber-local exists.
When it comes to thread-locals, they are accessible within the entire scope of the thread. Given the following example:
Thread.new{
Thread.current.thread_variable_set(:foo, 1)
p Thread.current.thread_variable_get(:foo) # => 1
Fiber.new{
Thread.current.thread_variable_set(:foo, 2)
p Thread.current.thread_variable_get(:foo) # => 2
}.resume
p Thread.current.thread_variable_get(:foo) # => 2
}.join
You can see that the thread-local :foo carried over into the fiber and was changed to 2 by the end of the thread.
This example makes use of thread_variable_set to create new thread-locals, and thread_variable_get to reference them.
There is also thread_variables to list all thread-locals, and thread_variable? to check if a given thread-local exists.
Exception handling¶ ↑
Any thread can raise an exception using the raise instance method, which operates similarly to Kernel#raise.
However, it's important to note that an exception that occurs in any thread except the main thread depends on abort_on_exception. This option is false by default, meaning that any unhandled exception will cause the thread to terminate silently when waited on by either join or value. You can change this default by either abort_on_exception= true or setting $DEBUG to true.
With the addition of the class method ::handle_interrupt, you can now handle exceptions asynchronously with threads.
Scheduling¶ ↑
Ruby provides a few ways to support scheduling threads in your program.
The first way is by using the class method ::stop, to put the current running thread to sleep and schedule the execution of another thread.
Once a thread is asleep, you can use the instance method wakeup to mark your thread as eligible for scheduling.
You can also try ::pass, which attempts to pass execution to another thread but is dependent on the OS whether a running thread will switch or not. The same goes for priority, which lets you hint to the thread scheduler which threads you want to take precedence when passing execution. This method is also dependent on the OS and may be ignored on some platforms.
An object representation of a stack frame, initialized by Kernel#caller_locations.
For example:
# caller_locations.rb
def a(skip)
caller_locations(skip)
end
def b(skip)
a(skip)
end
def c(skip)
b(skip)
end
c(0..2).map do |call|
puts call.to_s
end
Running ruby caller_locations.rb will produce:
caller_locations.rb:2:in `a'
caller_locations.rb:5:in `b'
caller_locations.rb:8:in `c'
Here's another example with a slightly different result:
# foo.rb
class Foo
attr_accessor :locations
def initialize(skip)
@locations = caller_locations(skip)
end
end
Foo.new(0..2).locations.map do |call|
puts call.to_s
end
Now run ruby foo.rb and you should see:
init.rb:4:in `initialize'
init.rb:8:in `new'
init.rb:8:in `<main>'
Raised when an invalid operation is attempted on a thread.
For example, when no other thread has been started:
Thread.stop
This will raises the following exception:
ThreadError: stopping only thread
note: use sleep to stop forever
ThreadGroup provides a means of keeping track of a number of threads as a group.
A given Thread object can only belong to one ThreadGroup at a time; adding a thread to a new group will remove it from any previous group.
Newly created threads belong to the same group as the thread from which they were created.
This class watches for termination of multiple threads. Basic functionality (wait until specified threads have terminated) can be accessed through the class method ThreadsWait::all_waits. Finer control can be gained using instance methods.
Example:
ThreadsWait.all_waits(thr1, thr2, ...) do |t|
STDERR.puts "Thread #{t} has terminated."
end
th = ThreadsWait.new(thread1,...)
th.next_wait # next one to be done
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.
Examples¶ ↑
All of these examples were done using the EST timezone which is GMT-5.
Creating a new 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
You can pass a UTC offset:
Time.new(2002, 10, 31, 2, 2, 2, "+02:00") #=> 2002-10-31 02:02:02 +0200
Or a timezone object:
tz = timezone("Europe/Athens") # Eastern European Time, UTC+2
Time.new(2002, 10, 31, 2, 2, 2, tz) #=> 2002-10-31 02:02:02 +0200
You can also use Time::gm, Time::local and Time::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
Working with an instance of 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 it 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
Timezone argument¶ ↑
A timezone argument must have local_to_utc and utc_to_local methods, and may have name and abbr methods.
The local_to_utc method should convert a Time-like object from the timezone to UTC, and utc_to_local is the opposite. The result also should be a Time or Time-like object (not necessary to be the same class). The zone of the result is just ignored. Time-like argument to these methods is similar to a Time object in UTC without sub-second; it has attribute readers for the parts, e.g. year, month, and so on, and epoch time readers, to_i. The sub-second attributes are fixed as 0, and utc_offset, zone, isdst, and their aliases are same as a Time object in UTC. Also to_time, +, and - methods are defined.
The name method is used for marshaling. If this method is not defined on a timezone object, Time objects using that timezone object can not be dumped by Marshal.
The abbr method is used by '%Z' in strftime.
Auto conversion to Timezone¶ ↑
At loading marshaled data, a timezone name will be converted to a timezone object by find_timezone class method, if the method is defined.
Similary, that class method will be called when a timezone argument does not have the necessary methods mentioned above.
Raised by Timeout.timeout when the block times out.
Raised by Timeout.timeout when the block times out.
A class that provides the functionality of Kernel#set_trace_func in a nice Object-Oriented API.
Example¶ ↑
We can use TracePoint to gather information specifically for exceptions:
trace = TracePoint.new(:raise) do |tp|
p [tp.lineno, tp.event, tp.raised_exception]
end
#=> #<TracePoint:disabled>
trace.enable
#=> false
0 / 0
#=> [5, :raise, #<ZeroDivisionError: divided by 0>]
Events¶ ↑
If you don't specify the type of events you want to listen for, TracePoint will include all available events.
Note do not depend on current event set, as this list is subject to change. Instead, it is recommended you specify the type of events you want to use.
To filter what is traced, you can pass any of the following as events:
:line
execute code on a new line
:class
start a class or module definition
:end
finish a class or module definition
:call
call a Ruby method
:return
return from a Ruby method
:c_call
call a C-language routine
:c_return
return from a C-language routine
:raise
raise an exception
:b_call
event hook at block entry
:b_return
event hook at block ending
:thread_begin
event hook at thread beginning
:thread_end
event hook at thread ending
:fiber_switch
event hook at fiber switch
Outputs a source level execution trace of a Ruby program.
It does this by registering an event handler with Kernel#set_trace_func for processing incoming events. It also provides methods for filtering unwanted trace output (see Tracer.add_filter, Tracer.on, and Tracer.off).
Example¶ ↑
Consider the following Ruby script
class A
def square(a)
return a*a
end
end
a = A.new
a.square(5)
Running the above script using ruby -r tracer example.rb will output the following trace to STDOUT (Note you can also explicitly require 'tracer')
#0:<internal:lib/rubygems/custom_require>:38:Kernel:<: -
#0:example.rb:3::-: class A
#0:example.rb:3::C: class A
#0:example.rb:4::-: def square(a)
#0:example.rb:7::E: end
#0:example.rb:9::-: a = A.new
#0:example.rb:10::-: a.square(5)
#0:example.rb:4:A:>: def square(a)
#0:example.rb:5:A:-: return a*a
#0:example.rb:6:A:<: end
| | | | |
| | | | ---------------------+ event
| | | ------------------------+ class
| | --------------------------+ line
| ------------------------------------+ filename
---------------------------------------+ thread
Symbol table used for displaying incoming events:
+}+
call a C-language routine
+{+
return from a C-language routine
+>+
call a Ruby method
C
start a class or module definition
E
finish a class or module definition
-
execute code on a new line
+^+
raise an exception
+<+
return from a Ruby method
Copyright¶ ↑
by Keiju ISHITSUKA([email protected])
The global value true is the only instance of class TrueClass and represents a logically true value in boolean expressions. The class provides operators allowing true to be used in logical expressions.
Raised when encountering an object that is not of the expected type.
[1, 2, 3].first("two")
raises the exception:
TypeError: no implicit conversion of String into Integer
UDPSocket represents a UDP/IP socket.
UNIXServer represents a UNIX domain stream server socket.
UNIXSocket represents a UNIX domain stream client socket.
URI is valid, bad usage is not.
Base class for all URI exceptions.
FTP URI syntax is defined by RFC1738 section 3.2.
This class will be redesigned because of difference of implementations; the structure of its path. draft-hoffman-ftp-uri-04 is a draft but it is a good summary about the de facto spec. tools.ietf.org/html/draft-hoffman-ftp-uri-04
The “file” URI is defined by RFC8089.
Base class for all URI classes. Implements generic URI syntax as per RFC 2396.
The syntax of HTTP URIs is defined in RFC1738 section 3.3.
Note that the Ruby URI library allows HTTP URLs containing usernames and passwords. This is not legal as per the RFC, but used to be supported in Internet Explorer 5 and 6, before the MS04-004 security update. See <URL:support.microsoft.com/kb/834489>.
The default port for HTTPS URIs is 443, and the scheme is 'https:' rather than 'http:'. Other than that, HTTPS URIs are identical to HTTP URIs; see URI::HTTP.
Not a URI component.
Not a URI.
LDAP URI SCHEMA (described in RFC2255).
The default port for LDAPS URIs is 636, and the scheme is 'ldaps:' rather than 'ldap:'. Other than that, LDAPS URIs are identical to LDAP URIs; see URI::LDAP.
RFC6068, the mailto URL scheme.
Class that parses String's into URI's.
It contains a Hash set of patterns and Regexp's that match and validate.
Class that parses String's into URI's.
It contains a Hash set of patterns and Regexp's that match and validate.
Ruby supports two forms of objectified methods. Class Method is used to represent methods that are associated with a particular object: these method objects are bound to that object. Bound method objects for an object can be created using Object#method.
Ruby also supports unbound methods; methods objects that are not associated with a particular object. These can be created either by calling Module#instance_method or by calling unbind on a bound method object. The result of both of these is an UnboundMethod object.
Unbound methods can only be called after they are bound to an object. That object must be a kind_of? the method's original class.
class Square
def area
@side * @side
end
def initialize(side)
@side = side
end
end
area_un = Square.instance_method(:area)
s = Square.new(12)
area = area_un.bind(s)
area.call #=> 144
Unbound methods are a reference to the method at the time it was objectified: subsequent changes to the underlying class will not affect the unbound method.
class Test
def test
:original
end
end
um = Test.instance_method(:test)
class Test
def test
:modified
end
end
t = Test.new
t.test #=> :modified
um.bind(t).call #=> :original
Raised when throw is called with a tag which does not have corresponding catch block.
throw "foo", "bar"
raises the exception:
UncaughtThrowError: uncaught throw "foo"
The Vector class represents a mathematical vector, which is useful in its own right, and also constitutes a row or column of a Matrix.
Method Catalogue¶ ↑
To create a Vector:
Vector.[](*array)
Vector.elements(array, copy = true)
Vector.basis(size: n, index: k)
Vector.zero(n)
To access elements:
[](i)
To set elements:
[]=(i, v)
To enumerate the elements:
each2(v)
collect2(v)
Properties of vectors:
angle_with(v)
Vector.independent?(*vs)
independent?(*vs)
zero?
Vector arithmetic:
*(x) “is matrix or number”
+(v)
-(v)
#/(v)
+@
-@
Vector functions:
inner_product(v), dot(v)
cross_product(v), cross(v)
collect
collect!
magnitude
map
map!
map2(v)
norm
normalize
r
round
size
Conversion to other data types:
covector
to_a
coerce(other)
String representations:
to_s
inspect
Raised if a parameter such as %e, %i, %o or %n is used without fetching a specific field.
A generic logging class
A CGI library using WEBrick requests and responses.
Example:
class MyCGI < WEBrick::CGI
def do_GET req, res
res.body = 'it worked!'
res.status = 200
end
end
MyCGI.new.start
Processes HTTP cookies
A generic module for daemonizing a process
Base TCP server class. You must subclass GenericServer and provide a run method.
Basic Authentication for WEBrick
Use this class to add basic authentication to a WEBrick servlet.
Here is an example of how to set up a BasicAuth:
config = { :Realm => 'BasicAuth example realm' }
htpasswd = WEBrick::HTTPAuth::Htpasswd.new 'my_password_file', password_hash: :bcrypt
htpasswd.set_passwd config[:Realm], 'username', 'password'
htpasswd.flush
config[:UserDB] = htpasswd
basic_auth = WEBrick::HTTPAuth::BasicAuth.new config
RFC 2617 Digest Access Authentication for WEBrick
Use this class to add digest authentication to a WEBrick servlet.
Here is an example of how to set up DigestAuth:
config = { :Realm => 'DigestAuth example realm' }
htdigest = WEBrick::HTTPAuth::Htdigest.new 'my_password_file'
htdigest.set_passwd config[:Realm], 'username', 'password'
htdigest.flush
config[:UserDB] = htdigest
digest_auth = WEBrick::HTTPAuth::DigestAuth.new config
When using this as with a servlet be sure not to create a new DigestAuth object in the servlet's initialize. By default WEBrick creates a new servlet instance for every request and the DigestAuth object must be used across requests.
Htdigest accesses apache-compatible digest password files. Passwords are matched to a realm where they are valid. For security, the path for a digest password database should be stored outside of the paths available to the HTTP server.
Htdigest is intended for use with WEBrick::HTTPAuth::DigestAuth and stores passwords using cryptographic hashes.
htpasswd = WEBrick::HTTPAuth::Htdigest.new 'my_password_file'
htpasswd.set_passwd 'my realm', 'username', 'password'
htpasswd.flush
Htgroup accesses apache-compatible group files. Htgroup can be used to provide group-based authentication for users. Currently Htgroup is not directly integrated with any authenticators in WEBrick. For security, the path for a digest password database should be stored outside of the paths available to the HTTP server.
Example:
htgroup = WEBrick::HTTPAuth::Htgroup.new 'my_group_file'
htgroup.add 'superheroes', %w[spiderman batman]
htgroup.members('superheroes').include? 'magneto' # => false
Htpasswd accesses apache-compatible password files. Passwords are matched to a realm where they are valid. For security, the path for a password database should be stored outside of the paths available to the HTTP server.
Htpasswd is intended for use with WEBrick::HTTPAuth::BasicAuth.
To create an Htpasswd database with a single user:
htpasswd = WEBrick::HTTPAuth::Htpasswd.new 'my_password_file'
htpasswd.set_passwd 'my realm', 'username', 'password'
htpasswd.flush
Basic authentication for proxy servers. See BasicAuth for details.
Digest authentication for proxy servers. See DigestAuth for details.
An HTTP Proxy server which proxies GET, HEAD and POST requests.
To create a simple proxy server:
require 'webrick'
require 'webrick/httpproxy'
proxy = WEBrick::HTTPProxyServer.new Port: 8000
trap 'INT' do proxy.shutdown end
trap 'TERM' do proxy.shutdown end
proxy.start
See ::new for proxy-specific configuration items.
Modifying proxied responses¶ ↑
To modify content the proxy server returns use the :ProxyContentHandler option:
handler = proc do |req, res|
if res['content-type'] == 'text/plain' then
res.body << "\nThis content was proxied!\n"
end
end
proxy =
WEBrick::HTTPProxyServer.new Port: 8000, ProxyContentHandler: handler
An HTTP request. This is consumed by service and do_* methods in WEBrick servlets
An HTTP response. This is filled in by the service or do_* methods of a WEBrick HTTP Servlet.
An HTTP Server
AbstractServlet allows HTTP server modules to be reused across multiple servers and allows encapsulation of functionality.
By default a servlet will respond to GET, HEAD (through an alias to GET) and OPTIONS requests.
By default a new servlet is initialized for every request. A servlet instance can be reused by overriding ::get_instance in the AbstractServlet subclass.
A Simple Servlet¶ ↑
class Simple < WEBrick::HTTPServlet::AbstractServlet
def do_GET request, response
status, content_type, body = do_stuff_with request
response.status = status
response['Content-Type'] = content_type
response.body = body
end
def do_stuff_with request
return 200, 'text/plain', 'you got a page'
end
end
This servlet can be mounted on a server at a given path:
server.mount '/simple', Simple
Servlet Configuration¶ ↑
Servlets can be configured via initialize. The first argument is the HTTP server the servlet is being initialized for.
class Configurable < Simple
def initialize server, color, size
super server
@color = color
@size = size
end
def do_stuff_with request
content = "<p " \
%q{style="color: #{@color}; font-size: #{@size}"} \
">Hello, World!"
return 200, "text/html", content
end
end
This servlet must be provided two arguments at mount time:
server.mount '/configurable', Configurable, 'red', '2em'
Servlet for handling CGI scripts
Example:
server.mount('/cgi/my_script', WEBrick::HTTPServlet::CGIHandler,
'/path/to/my_script')
Servlet for serving a single file. You probably want to use the FileHandler servlet instead as it handles directories and fancy indexes.
Example:
server.mount('/my_page.txt', WEBrick::HTTPServlet::DefaultFileHandler,
'/path/to/my_page.txt')
This servlet handles If-Modified-Since and Range requests.
ERBHandler evaluates an ERB file and returns the result. This handler is automatically used if there are .rhtml files in a directory served by the FileHandler.
ERBHandler supports GET and POST methods.
The ERB file is evaluated with the local variables servlet_request and servlet_response which are a WEBrick::HTTPRequest and WEBrick::HTTPResponse respectively.
Example .rhtml file:
Request to <%= servlet_request.request_uri %>
Query params <%= servlet_request.query.inspect %>
Serves a directory including fancy indexing and a variety of other options.
Example:
server.mount('/assets', WEBrick::HTTPServlet::FileHandler,
'/path/to/assets')
Mounts a proc at a path that accepts a request and response.
Instead of mounting this servlet with WEBrick::HTTPServer#mount use WEBrick::HTTPServer#mount_proc:
server.mount_proc '/' do |req, res|
res.body = 'it worked!'
res.status = 200
end
Root of the HTTP client error statuses
Root of the HTTP error statuses
Root of the HTTP info statuses
Root of the HTTP redirect statuses
Root of the HTTP server error statuses
Root of the HTTP status class hierarchy
Root of the HTTP success statuses
Stores multipart form data. FormData objects are created when WEBrick::HTTPUtils.parse_form_data is called.
Represents an HTTP protocol version
A logging class that prepends a timestamp to each message.
Server error exception
Base server class
Class used to manage timeout handlers across multiple threads.
Timeout handlers should be managed by using the class methods which are synchronized.
id = TimeoutHandler.register(10, Timeout::Error)
begin
sleep 20
puts 'foo'
ensure
TimeoutHandler.cancel(id)
end
will raise Timeout::Error
id = TimeoutHandler.register(10, Timeout::Error)
begin
sleep 5
puts 'foo'
ensure
TimeoutHandler.cancel(id)
end
will print 'foo'
WIN32OLE
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.
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
WIN32OLE_EVENT objects controls OLE event.
WIN32OLE_METHOD objects represent OLE method information.
WIN32OLE_PARAM objects represent param information of the OLE method.
WIN32OLE_RECORD objects represents VT_RECORD OLE variant. Win32OLE returns WIN32OLE_RECORD object if the result value of invoking OLE methods.
If COM server in VB.NET ComServer project is the following:
Imports System.Runtime.InteropServices
Public Class ComClass
Public Structure Book
<MarshalAs(UnmanagedType.BStr)> _
Public title As String
Public cost As Integer
End Structure
Public Function getBook() As Book
Dim book As New Book
book.title = "The Ruby Book"
book.cost = 20
Return book
End Function
End Class
then, you can retrieve getBook return value from the following Ruby script:
require 'win32ole'
obj = WIN32OLE.new('ComServer.ComClass')
book = obj.getBook
book.class # => WIN32OLE_RECORD
book.title # => "The Ruby Book"
book.cost # => 20
WIN32OLE_TYPE objects represent OLE type libarary information.
WIN32OLE_TYPELIB objects represent OLE tyblib information.
WIN32OLE_VARIABLE objects represent OLE variable information.
WIN32OLE_VARIANT objects represents OLE variant.
Win32OLE converts Ruby object into OLE variant automatically when invoking OLE methods. If OLE method requires the argument which is different from the variant by automatic conversion of Win32OLE, you can convert the specfied variant type by using WIN32OLE_VARIANT class.
param = WIN32OLE_VARIANT.new(10, WIN32OLE::VARIANT::VT_R4)
oleobj.method(param)
WIN32OLE_VARIANT does not support VT_RECORD variant. Use WIN32OLE_RECORD class instead of WIN32OLE_VARIANT if the VT_RECORD variant is needed.
Weak Reference class that allows a referenced object to be garbage-collected.
A WeakRef may be used exactly like the object it references.
Usage:
foo = Object.new # create a new object instance
p foo.to_s # original's class
foo = WeakRef.new(foo) # reassign foo with WeakRef instance
p foo.to_s # should be same class
GC.start # start the garbage collector
p foo.to_s # should raise exception (recycled)
RefError is raised when a referenced object has been recycled by the garbage collector
An example printer for irb.
It's much like the standard library PrettyPrint, that shows the value of each expression as it runs.
In order to use this library, you must first require it:
require 'irb/xmp'
Now, you can take advantage of the Object#xmp convenience method.
xmp <<END
foo = "bar"
baz = 42
END
#=> foo = "bar"
#==>"bar"
#=> baz = 42
#==>42
You can also create an XMP object, with an optional binding to print expressions in the given binding:
ctx = binding
x = XMP.new ctx
x.puts
#=> today = "a good day"
#==>"a good day"
ctx.eval 'today # is what?'
#=> "a good day"
A custom InputMethod class used by XMP for evaluating string io.
YAML + DBM = YDBM
YAML::DBM provides the same interface as ::DBM.
However, while DBM only allows strings for both keys and values, this library allows one to use most Ruby objects for values by first converting them to YAML. Keys must be strings.
Conversion to and from YAML is performed automatically.
See the documentation for ::DBM and ::YAML for more information.
YAML::Store provides the same functionality as PStore, except it uses YAML to dump objects instead of Marshal.
Example¶ ↑
require 'yaml/store'
Person = Struct.new :first_name, :last_name
people = [Person.new("Bob", "Smith"), Person.new("Mary", "Johnson")]
store = YAML::Store.new "test.store"
store.transaction do
store["people"] = people
store["greeting"] = { "hello" => "world" }
end
After running the above code, the contents of “test.store” will be:
---
people:
- !ruby/struct:Person
first_name: Bob
last_name: Smith
- !ruby/struct:Person
first_name: Mary
last_name: Johnson
greeting:
hello: world
Raised when attempting to divide an integer by 0.
42 / 0 #=> ZeroDivisionError: divided by 0
Note that only division by an exact 0 will raise the exception:
42 / 0.0 #=> Float::INFINITY
42 / -0.0 #=> -Float::INFINITY
0 / 0.0 #=> NaN
Subclass of Zlib::Error when zlib returns a Z_BUF_ERROR.
Usually if no progress is possible.
Subclass of Zlib::Error when zlib returns a Z_DATA_ERROR.
Usually if a stream was prematurely freed.
Zlib::Deflate is the class for compressing data. See Zlib::ZStream for more information.
The superclass for all exceptions raised by Ruby/zlib.
The following exceptions are defined as subclasses of Zlib::Error. These exceptions are raised when zlib library functions return with an error status.
Zlib::StreamEnd
Zlib::NeedDict
Zlib::DataError
Zlib::StreamError
Zlib::MemError
Zlib::BufError
Zlib::VersionError
Zlib::GzipFile is an abstract class for handling a gzip formatted compressed file. The operations are defined in the subclasses, Zlib::GzipReader for reading, and Zlib::GzipWriter for writing.
GzipReader should be used by associating an IO, or IO-like, object.
Method Catalogue¶ ↑
::wrap
::open (Zlib::GzipReader::open and Zlib::GzipWriter::open)
close
closed?
comment
comment= (Zlib::GzipWriter#comment=)
crc
eof? (Zlib::GzipReader#eof?)
finish
level
lineno (Zlib::GzipReader#lineno)
lineno= (Zlib::GzipReader#lineno=)
mtime
mtime= (Zlib::GzipWriter#mtime=)
orig_name
orig_name (Zlib::GzipWriter#orig_name=)
os_code
path (when the underlying IO supports path)
sync
sync=
to_io
(due to internal structure, documentation may appear under Zlib::GzipReader or Zlib::GzipWriter)
Raised when the CRC checksum recorded in gzip file footer is not equivalent to the CRC checksum of the actual uncompressed data.
Base class of errors that occur when processing GZIP files.
Raised when the data length recorded in the gzip file footer is not equivalent to the length of the actual uncompressed data.
Raised when gzip file footer is not found.
Zlib::GzipReader is the class for reading a gzipped file. GzipReader should be used as an IO, or -IO-like, object.
Zlib::GzipReader.open('hoge.gz') {|gz|
print gz.read
}
File.open('hoge.gz') do |f|
gz = Zlib::GzipReader.new(f)
print gz.read
gz.close
end
Method Catalogue¶ ↑
The following methods in Zlib::GzipReader are just like their counterparts in IO, but they raise Zlib::Error or Zlib::GzipFile::Error exception if an error was found in the gzip file.
each
each_line
each_byte
gets
getc
lineno
lineno=
read
readchar
readline
readlines
ungetc
Be careful of the footer of the gzip file. A gzip file has the checksum of pre-compressed data in its footer. GzipReader checks all uncompressed data against that checksum at the following cases, and if it fails, raises Zlib::GzipFile::NoFooter, Zlib::GzipFile::CRCError, or Zlib::GzipFile::LengthError exception.
When an reading request is received beyond the end of file (the end of compressed data). That is, when Zlib::GzipReader#read, Zlib::GzipReader#gets, or some other methods for reading returns nil.
When Zlib::GzipFile#close method is called after the object reaches the end of file.
When Zlib::GzipReader#unused method is called after the object reaches the end of file.
The rest of the methods are adequately described in their own documentation.
Zlib::GzipWriter is a class for writing gzipped files. GzipWriter should be used with an instance of IO, or IO-like, object.
Following two example generate the same result.
Zlib::GzipWriter.open('hoge.gz') do |gz|
gz.write 'jugemu jugemu gokou no surikire...'
end
File.open('hoge.gz', 'w') do |f|
gz = Zlib::GzipWriter.new(f)
gz.write 'jugemu jugemu gokou no surikire...'
gz.close
end
To make like gzip(1) does, run following:
orig = 'hoge.txt'
Zlib::GzipWriter.open('hoge.gz') do |gz|
gz.mtime = File.mtime(orig)
gz.orig_name = orig
gz.write IO.binread(orig)
end
NOTE: Due to the limitation of Ruby's finalizer, you must explicitly close GzipWriter objects by Zlib::GzipWriter#close etc. Otherwise, GzipWriter will be not able to write the gzip footer and will generate a broken gzip file.
Zlib:Inflate is the class for decompressing compressed data. Unlike Zlib::Deflate, an instance of this class is not able to duplicate (clone, dup) itself.
Subclass of Zlib::Error
When zlib returns a Z_MEM_ERROR, usually if there was not enough memory.
Subclass of Zlib::Error
When zlib returns a Z_NEED_DICT if a preset dictionary is needed at this point.
Used by Zlib::Inflate.inflate and Zlib.inflate
Subclass of Zlib::Error
When zlib returns a Z_STREAM_END is return if the end of the compressed data has been reached and all uncompressed out put has been produced.
Subclass of Zlib::Error
When zlib returns a Z_STREAM_ERROR, usually if the stream state was inconsistent.
Subclass of Zlib::Error
When zlib returns a Z_VERSION_ERROR, usually if the zlib library version is incompatible with the version assumed by the caller.
Zlib::ZStream is the abstract class for the stream which handles the compressed data. The operations are defined in the subclasses: Zlib::Deflate for compression, and Zlib::Inflate for decompression.
An instance of Zlib::ZStream has one stream (struct zstream in the source) and two variable-length buffers which associated to the input (next_in) of the stream and the output (next_out) of the stream. In this document, “input buffer” means the buffer for input, and “output buffer” means the buffer for output.
Data input into an instance of Zlib::ZStream are temporally stored into the end of input buffer, and then data in input buffer are processed from the beginning of the buffer until no more output from the stream is produced (i.e. until avail_out > 0 after processing). During processing, output buffer is allocated and expanded automatically to hold all output data.
Some particular instance methods consume the data in output buffer and return them as a String.
Here is an ascii art for describing above:
+================ an instance of Zlib::ZStream ================+
|| ||
|| +--------+ +-------+ +--------+ ||
|| +--| output |<---------|zstream|<---------| input |<--+ ||
|| | | buffer | next_out+-------+next_in | buffer | | ||
|| | +--------+ +--------+ | ||
|| | | ||
+===|======================================================|===+
| |
v |
"output data" "input data"
If an error occurs during processing input buffer, an exception which is a subclass of Zlib::Error is raised. At that time, both input and output buffer keep their conditions at the time when the error occurs.
Method Catalogue¶ ↑
Many of the methods in this class are fairly low-level and unlikely to be of interest to users. In fact, users are unlikely to use this class directly; rather they will be interested in Zlib::Inflate and Zlib::Deflate.
The higher level methods are listed below.
total_in
total_out
data_type
adler
reset
finish
finished?
close
closed?
fatal is an Exception that is raised when Ruby has encountered a fatal error and must exit. You are not able to rescue fatal.