Class Net::HTTP provides a rich library that implements the client in a client-server model that uses the HTTP request-response protocol. For information about HTTP, see:
If you will make only a few GET requests, consider using OpenURI
.
If you will make only a few requests of all kinds, consider using the various singleton convenience methods in this class. Each of the following methods automatically starts and finishes a session that sends a single request:
# Return string response body. Net::HTTP.get(hostname, path) Net::HTTP.get(uri) # Write string response body to $stdout. Net::HTTP.get_print(hostname, path) Net::HTTP.get_print(uri) # Return response as Net::HTTPResponse object. Net::HTTP.get_response(hostname, path) Net::HTTP.get_response(uri) data = '{"title": "foo", "body": "bar", "userId": 1}' Net::HTTP.post(uri, data) params = {title: 'foo', body: 'bar', userId: 1} Net::HTTP.post_form(uri, params) data = '{"title": "foo", "body": "bar", "userId": 1}' Net::HTTP.put(uri, data)
If performance is important, consider using sessions, which lower request overhead. This session has multiple requests for HTTP methods and WebDAV methods:
Net::HTTP.start(hostname) do |http| # Session started automatically before block execution. http.get(path) http.head(path) body = 'Some text' http.post(path, body) # Can also have a block. http.put(path, body) http.delete(path) http.options(path) http.trace(path) http.patch(path, body) # Can also have a block. http.copy(path) http.lock(path, body) http.mkcol(path, body) http.move(path) http.propfind(path, body) http.proppatch(path, body) http.unlock(path, body) # Session finished automatically at block exit. end
The methods cited above are convenience methods that, via their few arguments, allow minimal control over the requests. For greater control, consider using request objects.
On the internet, a URI
(Universal Resource Identifier) is a string that identifies a particular resource. It consists of some or all of: scheme, hostname, path, query, and fragment; see URI syntax.
A Ruby
URI::Generic
object represents an internet URI
. It provides, among others, methods scheme
, hostname
, path
, query
, and fragment
.
An internet URI has a scheme.
The two schemes supported in Net::HTTP are 'https'
and 'http'
:
uri.scheme # => "https" URI('http://example.com').scheme # => "http"
A hostname identifies a server (host) to which requests may be sent:
hostname = uri.hostname # => "jsonplaceholder.typicode.com" Net::HTTP.start(hostname) do |http| # Some HTTP stuff. end
A host-specific path identifies a resource on the host:
_uri = uri.dup _uri.path = '/todos/1' hostname = _uri.hostname path = _uri.path Net::HTTP.get(hostname, path)
A host-specific query adds name/value pairs to the URI:
_uri = uri.dup params = {userId: 1, completed: false} _uri.query = URI.encode_www_form(params) _uri # => #<URI::HTTPS https://jsonplaceholder.typicode.com?userId=1&completed=false> Net::HTTP.get(_uri)
A URI fragment has no effect in Net::HTTP; the same data is returned, regardless of whether a fragment is included.
Request headers may be used to pass additional information to the host, similar to arguments passed in a method call; each header is a name/value pair.
Each of the Net::HTTP methods that sends a request to the host has optional argument headers
, where the headers are expressed as a hash of field-name/value pairs:
headers = {Accept: 'application/json', Connection: 'Keep-Alive'} Net::HTTP.get(uri, headers)
See lists of both standard request fields and common request fields at Request Fields. A host may also accept other custom fields.
A session is a connection between a server (host) and a client that:
Is begun by instance method Net::HTTP#start
.
May contain any number of requests.
Is ended by instance method Net::HTTP#finish
.
See example sessions at Strategies.
If you have many requests to make to a single host (and port), consider using singleton method Net::HTTP.start
with a block; the method handles the session automatically by:
In the block, you can use these instance methods, each of which that sends a single request:
get
, request_get
: GET.
head
, request_head
: HEAD.
post
, request_post
: POST.
delete
: DELETE.
options
: OPTIONS.
trace
: TRACE.
patch
: PATCH.
You can manage a session manually using methods start
and finish
:
http = Net::HTTP.new(hostname) http.start http.get('/todos/1') http.get('/todos/2') http.delete('/posts/1') http.finish # Needed to free resources.
Certain convenience methods automatically handle a session by:
Creating an HTTP object
Starting a session.
Sending a single request.
Finishing the session.
Destroying the object.
Such methods that send GET requests:
::get
: Returns the string response body.
::get_print
: Writes the string response body to $stdout.
::get_response
: Returns a Net::HTTPResponse
object.
Such methods that send POST requests:
::post
: Posts data to the host.
::post_form
: Posts form data to the host.
Many of the methods above are convenience methods, each of which sends a request and returns a string without directly using Net::HTTPRequest and Net::HTTPResponse objects.
You can, however, directly create a request object, send the request, and retrieve the response object; see:
Each returned response is an instance of a subclass of Net::HTTPResponse
. See the response class hierarchy.
In particular, class Net::HTTPRedirection
is the parent of all redirection classes. This allows you to craft a case statement to handle redirections properly:
def fetch(uri, limit = 10) # You should choose a better exception. raise ArgumentError, 'Too many HTTP redirects' if limit == 0 res = Net::HTTP.get_response(URI(uri)) case res when Net::HTTPSuccess # Any success class. res when Net::HTTPRedirection # Any redirection class. location = res['Location'] warn "Redirected to #{location}" fetch(location, limit - 1) else # Any other class. res.value end end fetch(uri)
Basic authentication is performed according to RFC2617:
req = Net::HTTP::Get.new(uri) req.basic_auth('user', 'pass') res = Net::HTTP.start(hostname) do |http| http.request(req) end
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
.
Net::HTTP.start(hostname) do |http| req = Net::HTTP::Get.new(uri) http.request(req) do |res| open('t.tmp', 'w') do |f| res.read_body do |chunk| f.write chunk end end end end
HTTPS is enabled for an HTTP connection by Net::HTTP#use_ssl=
:
Net::HTTP.start(hostname, :use_ssl => true) do |http| req = Net::HTTP::Get.new(uri) res = http.request(req) end
Or if you simply want to make a GET request, you may pass in a 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 https://jsonplaceholder.typicode.com/> Net::HTTP.get(uri)
An HTTP object can have a proxy server.
You can create an HTTP object with a proxy server using method Net::HTTP.new
or method Net::HTTP.start
.
The proxy may be defined either by argument p_addr
or by environment variable 'http_proxy'
.
p_addr
as a String When argument p_addr
is a string hostname, the returned http
has the given host as its proxy:
http = Net::HTTP.new(hostname, nil, 'proxy.example') http.proxy? # => true http.proxy_from_env? # => false http.proxy_address # => "proxy.example" # These use default values. http.proxy_port # => 80 http.proxy_user # => nil http.proxy_pass # => nil
The port, username, and password for the proxy may also be given:
http = Net::HTTP.new(hostname, nil, 'proxy.example', 8000, 'pname', 'ppass') # => #<Net::HTTP jsonplaceholder.typicode.com:80 open=false> http.proxy? # => true http.proxy_from_env? # => false http.proxy_address # => "proxy.example" http.proxy_port # => 8000 http.proxy_user # => "pname" http.proxy_pass # => "ppass"
ENV['http_proxy']
’ When environment variable 'http_proxy'
is set to a URI string, the returned http
will have the server at that URI
as its proxy; note that the URI string must have a protocol such as 'http'
or 'https'
:
ENV['http_proxy'] = 'http://example.com' http = Net::HTTP.new(hostname) http.proxy? # => true http.proxy_from_env? # => true http.proxy_address # => "example.com" # These use default values. http.proxy_port # => 80 http.proxy_user # => nil http.proxy_pass # => nil
The URI string may include proxy username, password, and port number:
ENV['http_proxy'] = 'http://pname:ppass@example.com:8000' http = Net::HTTP.new(hostname) http.proxy? # => true http.proxy_from_env? # => true http.proxy_address # => "example.com" http.proxy_port # => 8000 http.proxy_user # => "pname" http.proxy_pass # => "ppass"
With method Net::HTTP.new
(but not Net::HTTP.start
), you can use argument p_no_proxy
to filter proxies:
Reject a certain address:
http = Net::HTTP.new('example.com', nil, 'proxy.example', 8000, 'pname', 'ppass', 'proxy.example') http.proxy_address # => nil
Reject certain domains or subdomains:
http = Net::HTTP.new('example.com', nil, 'my.proxy.example', 8000, 'pname', 'ppass', 'proxy.example') http.proxy_address # => nil
Reject certain addresses and port combinations:
http = Net::HTTP.new('example.com', nil, 'proxy.example', 8000, 'pname', 'ppass', 'proxy.example:1234') http.proxy_address # => "proxy.example" http = Net::HTTP.new('example.com', nil, 'proxy.example', 8000, 'pname', 'ppass', 'proxy.example:8000') http.proxy_address # => nil
Reject a list of the types above delimited using a comma:
http = Net::HTTP.new('example.com', nil, 'proxy.example', 8000, 'pname', 'ppass', 'my.proxy,proxy.example:8000') http.proxy_address # => nil http = Net::HTTP.new('example.com', nil, 'my.proxy', 8000, 'pname', 'ppass', 'my.proxy,proxy.example:8000') http.proxy_address # => nil
Net::HTTP does not compress the body of a request before sending.
By default, Net::HTTP adds header 'Accept-Encoding'
to a new request object:
Net::HTTP::Get.new(uri)['Accept-Encoding'] # => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3"
This requests the server to zip-encode the response body if there is one; the server is not required to do so.
Net::HTTP does not automatically decompress a response body if the response has header 'Content-Range'
.
Otherwise decompression (or not) depends on the value of header Content-Encoding:
'deflate'
, 'gzip'
, or 'x-gzip'
: decompresses the body and deletes the header.
'none'
or 'identity'
: does not decompress the body, but deletes the header.
Any other value: leaves the body and header unchanged.
First, what’s elsewhere. Class
Net::HTTP
:
Inherits from class Object.
This is a categorized summary of methods and attributes.
::start: Begins a new session in a new Net::HTTP object.
#started?: Returns whether in a session.
#finish: Ends an active session.
#start: Begins a new session in an existing Net::HTTP object (self
).
:continue_timeout: Returns the continue timeout.
#continue_timeout=: Sets the continue timeout seconds.
:keep_alive_timeout: Returns the keep-alive timeout.
:keep_alive_timeout=: Sets the keep-alive timeout.
:max_retries: Returns the maximum retries.
#max_retries=: Sets the maximum retries.
:open_timeout: Returns the open timeout.
:open_timeout=: Sets the open timeout.
:read_timeout: Returns the open timeout.
:read_timeout=: Sets the read timeout.
:ssl_timeout: Returns the ssl timeout.
:ssl_timeout=: Sets the ssl timeout.
:write_timeout: Returns the write timeout.
write_timeout=: Sets the write timeout.
::get: Sends a GET request and returns the string response body.
::get_print: Sends a GET request and write the string response body to $stdout.
::get_response: Sends a GET request and returns a response object.
::post_form: Sends a POST request with form data and returns a response object.
::post: Sends a POST request with data and returns a response object.
::put: Sends a PUT request with data and returns a response object.
#copy: Sends a COPY request and returns a response object.
#delete: Sends a DELETE request and returns a response object.
#get: Sends a GET request and returns a response object.
#head: Sends a HEAD request and returns a response object.
#lock: Sends a LOCK request and returns a response object.
#mkcol: Sends a MKCOL request and returns a response object.
#move: Sends a MOVE request and returns a response object.
#options: Sends a OPTIONS request and returns a response object.
#patch: Sends a PATCH request and returns a response object.
#post: Sends a POST request and returns a response object.
#propfind: Sends a PROPFIND request and returns a response object.
#proppatch: Sends a PROPPATCH request and returns a response object.
#put: Sends a PUT request and returns a response object.
#request: Sends a request and returns a response object.
#request_get: Sends a GET request and forms a response object; if a block given, calls the block with the object, otherwise returns the object.
#request_head: Sends a HEAD request and forms a response object; if a block given, calls the block with the object, otherwise returns the object.
#request_post: Sends a POST request and forms a response object; if a block given, calls the block with the object, otherwise returns the object.
#send_request: Sends a request and returns a response object.
#trace: Sends a TRACE request and returns a response object.
#unlock: Sends an UNLOCK request and returns a response object.
:close_on_empty_response: Returns whether to close connection on empty response.
:close_on_empty_response=: Sets whether to close connection on empty response.
:ignore_eof: Returns whether to ignore end-of-file when reading a response body with Content-Length
headers.
:ignore_eof=: Sets whether to ignore end-of-file when reading a response body with Content-Length
headers.
:response_body_encoding: Returns the encoding to use for the response body.
#response_body_encoding=: Sets the response body encoding.
:proxy_address: Returns the proxy address.
:proxy_address=: Sets the proxy address.
::proxy_class?: Returns whether self
is a proxy class.
#proxy?: Returns whether self
has a proxy.
#proxy_address: Returns the proxy address.
#proxy_from_env?: Returns whether the proxy is taken from an environment variable.
:proxy_from_env=: Sets whether the proxy is to be taken from an environment variable.
:proxy_pass: Returns the proxy password.
:proxy_pass=: Sets the proxy password.
:proxy_port: Returns the proxy port.
:proxy_port=: Sets the proxy port.
#proxy_user: Returns the proxy user name.
:proxy_user=: Sets the proxy user.
:ca_file: Returns the path to a CA certification file.
:ca_file=: Sets the path to a CA certification file.
:ca_path: Returns the path of to CA directory containing certification files.
:ca_path=: Sets the path of to CA directory containing certification files.
:cert: Returns the OpenSSL::X509::Certificate
object to be used for client certification.
:cert=: Sets the OpenSSL::X509::Certificate
object to be used for client certification.
:cert_store: Returns the X509::Store to be used for verifying peer certificate.
:cert_store=: Sets the X509::Store to be used for verifying peer certificate.
:ciphers: Returns the available SSL ciphers.
:ciphers=: Sets the available SSL ciphers.
:extra_chain_cert: Returns the extra X509 certificates to be added to the certificate chain.
:extra_chain_cert=: Sets the extra X509 certificates to be added to the certificate chain.
:key: Returns the OpenSSL::PKey::RSA
or OpenSSL::PKey::DSA
object.
:key=: Sets the OpenSSL::PKey::RSA
or OpenSSL::PKey::DSA
object.
:max_version: Returns the maximum SSL version.
:max_version=: Sets the maximum SSL version.
:min_version: Returns the minimum SSL version.
:min_version=: Sets the minimum SSL version.
#peer_cert: Returns the X509 certificate chain for the session’s socket peer.
:ssl_version: Returns the SSL version.
:ssl_version=: Sets the SSL version.
#use_ssl=: Sets whether a new session is to use Transport Layer Security.
#use_ssl?: Returns whether self
uses SSL.
:verify_callback: Returns the callback for the server certification verification.
:verify_callback=: Sets the callback for the server certification verification.
:verify_depth: Returns the maximum depth for the certificate chain verification.
:verify_depth=: Sets the maximum depth for the certificate chain verification.
:verify_hostname: Returns the flags for server the certification verification at the beginning of the SSL/TLS session.
:verify_hostname=: Sets he flags for server the certification verification at the beginning of the SSL/TLS session.
:verify_mode: Returns the flags for server the certification verification at the beginning of the SSL/TLS session.
:verify_mode=: Sets the flags for server the certification verification at the beginning of the SSL/TLS session.
:address: Returns the string host name or host IP.
::default_port: Returns integer 80, the default port to use for HTTP
requests.
::http_default_port: Returns integer 80, the default port to use for HTTP
requests.
::https_default_port: Returns integer 443, the default port to use for HTTPS requests.
#ipaddr: Returns the IP address for the connection.
#ipaddr=: Sets the IP address for the connection.
:local_host: Returns the string local host used to establish the connection.
:local_host=: Sets the string local host used to establish the connection.
:local_port: Returns the integer local port used to establish the connection.
:local_port=: Sets the integer local port used to establish the connection.
:port: Returns the integer port number.
::version_1_2? (aliased as ::version_1_2): Returns true; retained for compatibility.
#set_debug_output: Sets the output stream for debugging.
Response class for Continue
responses (status code 100).
A Continue
response indicates that the server has received the request headers.
References:
Response class for Partial Content
responses (status code 206).
The Partial Content
response indicates that the server is delivering only part of the resource (byte serving) due to a Range
header in the request.
References:
Response class for Conflict
responses (status code 409).
The request could not be processed because of conflict in the current state of the resource.
References:
Response class for HTTP Version Not Supported
responses (status code 505).
The server does not support the HTTP
version used in the request.
References:
Response class for Variant Also Negotiates
responses (status code 506).
Transparent content negotiation for the request results in a circular reference.
References:
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.
Raised when there are conflicting gem specs loaded
Raised when a gem dependencies file specifies a ruby version that does not match the current version.
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'
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.
Switch from an array based implementation to a linked-list based implementation.
Provide an automatic (and transparent) backing store for large stacks.
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).
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
.
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.
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!).
Version
Catastrophe: From: www.zenspider.com/ruby/2008/10/rubygems-how-to-preventing-catastrophe.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.
Raised by transcoding methods when a named encoding does not correspond with a known converter.
Mixin module that provides the following:
Access to the CGI
environment variables as methods. See documentation to the CGI
class for a list of these variables. The methods are exposed by removing the leading HTTP_
(if it exists) and downcasing the name. For example, auth_type
will return the environment variable AUTH_TYPE
, and accept
will return the value for HTTP_ACCEPT
.
Access to cookies, including the cookies attribute.
Access to parameters, including the params attribute, and overloading []
to perform parameter value lookup by key.
The initialize_query
method, for initializing the above mechanisms, handling multipart forms, and allowing the class to be used in “offline” mode.
Utility methods for using the RubyGems API.
The WebauthnListener
class retrieves an OTP after a user successfully WebAuthns with the Gem
host. An instance opens a socket using the TCPServer
instance given and listens for a request from the Gem
host. The request should be a GET request to the root path and contains the OTP code in the form of a query parameter ‘code`. The listener will return the code which will be used as the OTP for API requests.
Types of responses sent by the listener after receiving a request:
- 200 OK: OTP code was successfully retrieved - 204 No Content: If the request was an OPTIONS request - 400 Bad Request: If the request did not contain a query parameter `code` - 404 Not Found: The request was not to the root path - 405 Method Not Allowed: OTP code was not retrieved because the request was not a GET/OPTIONS request
Example usage:
thread = Gem::WebauthnListener.listener_thread("https://rubygems.example", server) thread.join otp = thread[:otp] error = thread[:error]
The WebauthnListener
Response class is used by the WebauthnListener
to create responses to be sent to the Gem
host. It creates a Gem::Net::HTTPResponse instance when initialized and can be converted to the appropriate format to be sent by a socket using ‘to_s`. Gem::Net::HTTPResponse instances cannot be directly sent over a socket.
Types of response classes:
- OkResponse - NoContentResponse - BadRequestResponse - NotFoundResponse - MethodNotAllowedResponse
Example usage:
server = TCPServer.new(0) socket = server.accept response = OkResponse.for("https://rubygems.example") socket.print response.to_s socket.close
The WebauthnPoller
class retrieves an OTP after a user successfully WebAuthns. An instance polls the Gem
host for the OTP code. The polling request (api/v1/webauthn_verification/<webauthn_token>/status.json) is sent to the Gem
host every 5 seconds and will timeout after 5 minutes. If the status field in the json response is “success”, the code field will contain the OTP code.
Example usage:
thread = Gem::WebauthnPoller.poll_thread( {}, "RubyGems.org", "https://rubygems.org/api/v1/webauthn_verification/odow34b93t6aPCdY", { email: "email@example.com", password: "password" } ) thread.join otp = thread[:otp] error = thread[:error]
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
).
First, what’s elsewhere. Class
Object:
Inherits from class BasicObject.
Includes module Kernel.
Here, class Object provides methods for:
!~
: Returns true
if self
does not match the given object, otherwise false
.
<=>
: Returns 0 if self
and the given object object
are the same object, or if self == object
; otherwise returns nil
.
===
: Implements case equality, effectively the same as calling ==
.
eql?
: Implements hash equality, effectively the same as calling ==
.
kind_of?
(aliased as is_a?
): Returns whether given argument is an ancestor of the singleton class of self
.
instance_of?
: Returns whether self
is an instance of the given class.
instance_variable_defined?
: Returns whether the given instance variable is defined in self
.
method
: Returns the Method
object for the given method in self
.
methods
: Returns an array of symbol names of public and protected methods in self
.
nil?
: Returns false
. (Only nil
responds true
to method nil?
.)
object_id
: Returns an integer corresponding to self
that is unique for the current process
private_methods
: Returns an array of the symbol names of the private methods in self
.
protected_methods
: Returns an array of the symbol names of the protected methods in self
.
public_method
: Returns the Method
object for the given public method in self
.
public_methods
: Returns an array of the symbol names of the public methods in self
.
respond_to?
: Returns whether self
responds to the given method.
singleton_class
: Returns the singleton class of self
.
singleton_method
: Returns the Method
object for the given singleton method in self
.
singleton_methods
: Returns an array of the symbol names of the singleton methods in self
.
define_singleton_method
: Defines a singleton method in self
for the given symbol method-name and block or proc.
extend
: Includes the given modules in the singleton class of self
.
public_send
: Calls the given public method in self
with the given argument.
send
: Calls the given method in self
with the given argument.
instance_variable_get
: Returns the value of the given instance variable in self
, or nil
if the instance variable is not set.
instance_variable_set
: Sets the value of the given instance variable in self
to the given object.
instance_variables
: Returns an array of the symbol names of the instance variables in self
.
remove_instance_variable
: Removes the named instance variable from self
.
clone
: Returns a shallow copy of self
, including singleton class and frozen state.
define_singleton_method
: Defines a singleton method in self
for the given symbol method-name and block or proc.
dup
: Returns a shallow unfrozen copy of self
.
enum_for
(aliased as to_enum
): Returns an Enumerator
for self
using the using the given method, arguments, and block.
extend
: Includes the given modules in the singleton class of self
.
freeze
: Prevents further modifications to self
.
hash
: Returns the integer hash value for self
.
inspect
: Returns a human-readable string representation of self
.
itself
: Returns self
.
method_missing
: Method
called when an undefined method is called on self
.
public_send
: Calls the given public method in self
with the given argument.
send
: Calls the given method in self
with the given argument.
to_s
: Returns a string representation of self
.
DateTime
A subclass of Date
that easily handles date, hour, minute, second, and offset.
DateTime
class is considered deprecated. Use Time
class.
DateTime
does not consider any leap seconds, does not track any summer time rules.
A DateTime
object is created with DateTime::new
, DateTime::jd
, DateTime::ordinal
, DateTime::commercial
, DateTime::parse
, DateTime::strptime
, DateTime::now
, Time#to_datetime
, etc.
require 'date' DateTime.new(2001,2,3,4,5,6) #=> #<DateTime: 2001-02-03T04:05:06+00:00 ...>
The last element of day, hour, minute, or second can be a fractional number. The fractional number’s precision is assumed at most nanosecond.
DateTime.new(2001,2,3.5) #=> #<DateTime: 2001-02-03T12:00:00+00:00 ...>
An optional argument, the offset, indicates the difference between the local time and UTC. For example, Rational(3,24)
represents ahead of 3 hours of UTC, Rational(-5,24)
represents behind of 5 hours of UTC. The offset should be -1 to +1, and its precision is assumed at most second. The default value is zero (equals to UTC).
DateTime.new(2001,2,3,4,5,6,Rational(3,24)) #=> #<DateTime: 2001-02-03T04:05:06+03:00 ...>
The offset also accepts string form:
DateTime.new(2001,2,3,4,5,6,'+03:00') #=> #<DateTime: 2001-02-03T04:05:06+03:00 ...>
An optional argument, the day of calendar reform (start
), denotes a Julian day number, which should be 2298874 to 2426355 or negative/positive infinity. The default value is Date::ITALY
(2299161=1582-10-15).
A DateTime
object has various methods. See each reference.
d = DateTime.parse('3rd Feb 2001 04:05:06+03:30') #=> #<DateTime: 2001-02-03T04:05:06+03:30 ...> d.hour #=> 4 d.min #=> 5 d.sec #=> 6 d.offset #=> (7/48) d.zone #=> "+03:30" d += Rational('1.5') #=> #<DateTime: 2001-02-04%16:05:06+03:30 ...> d = d.new_offset('+09:00') #=> #<DateTime: 2001-02-04%21:35:06+09:00 ...> d.strftime('%I:%M:%S %p') #=> "09:35:06 PM" d > DateTime.new(1999) #=> true
DateTime
and when should you use Time
? It’s a common misconception that William Shakespeare and Miguel de Cervantes died on the same day in history - so much so that UNESCO named April 23 as World Book Day because of this fact. However, because England hadn’t yet adopted the Gregorian Calendar Reform (and wouldn’t until 1752) their deaths are actually 10 days apart. Since Ruby’s Time
class implements a proleptic Gregorian calendar and has no concept of calendar reform there’s no way to express this with Time
objects. This is where DateTime
steps in:
shakespeare = DateTime.iso8601('1616-04-23', Date::ENGLAND) #=> Tue, 23 Apr 1616 00:00:00 +0000 cervantes = DateTime.iso8601('1616-04-23', Date::ITALY) #=> Sat, 23 Apr 1616 00:00:00 +0000
Already you can see something is weird - the days of the week are different. Taking this further:
cervantes == shakespeare #=> false (shakespeare - cervantes).to_i #=> 10
This shows that in fact they died 10 days apart (in reality 11 days since Cervantes died a day earlier but was buried on the 23rd). We can see the actual date of Shakespeare’s death by using the gregorian
method to convert it:
shakespeare.gregorian #=> Tue, 03 May 1616 00:00:00 +0000
So there’s an argument that all the celebrations that take place on the 23rd April in Stratford-upon-Avon are actually the wrong date since England is now using the Gregorian calendar. You can see why when we transition across the reform date boundary:
# start off with the anniversary of Shakespeare's birth in 1751 shakespeare = DateTime.iso8601('1751-04-23', Date::ENGLAND) #=> Tue, 23 Apr 1751 00:00:00 +0000 # add 366 days since 1752 is a leap year and April 23 is after February 29 shakespeare + 366 #=> Thu, 23 Apr 1752 00:00:00 +0000 # add another 365 days to take us to the anniversary in 1753 shakespeare + 366 + 365 #=> Fri, 04 May 1753 00:00:00 +0000
As you can see, if we’re accurately tracking the number of solar years since Shakespeare’s birthday then the correct anniversary date would be the 4th May and not the 23rd April.
So when should you use DateTime
in Ruby
and when should you use Time
? Almost certainly you’ll want to use Time
since your app is probably dealing with current dates and times. However, if you need to deal with dates and times in a historical context you’ll want to use DateTime
to avoid making the same mistakes as UNESCO. If you also have to deal with timezones then best of luck - just bear in mind that you’ll probably be dealing with local solar times, since it wasn’t until the 19th century that the introduction of the railways necessitated the need for Standard Time and eventually timezones.
A Time
object represents a date and time:
Time.new(2000, 1, 1, 0, 0, 0) # => 2000-01-01 00:00:00 -0600
Although its value can be expressed as a single numeric (see Epoch Seconds below), it can be convenient to deal with the value by parts:
t = Time.new(-2000, 1, 1, 0, 0, 0.0) # => -2000-01-01 00:00:00 -0600 t.year # => -2000 t.month # => 1 t.mday # => 1 t.hour # => 0 t.min # => 0 t.sec # => 0 t.subsec # => 0 t = Time.new(2000, 12, 31, 23, 59, 59.5) # => 2000-12-31 23:59:59.5 -0600 t.year # => 2000 t.month # => 12 t.mday # => 31 t.hour # => 23 t.min # => 59 t.sec # => 59 t.subsec # => (1/2)
Epoch seconds is the exact number of seconds (including fractional subseconds) since the Unix Epoch, January 1, 1970.
You can retrieve that value exactly using method Time.to_r
:
Time.at(0).to_r # => (0/1) Time.at(0.999999).to_r # => (9007190247541737/9007199254740992)
Other retrieval methods such as Time#to_i
and Time#to_f
may return a value that rounds or truncates subseconds.
A Time
object derived from the system clock (for example, by method Time.now
) has the resolution supported by the system.
Time
implementation uses a signed 63 bit integer, Integer
, or Rational
. It is a number of nanoseconds since the Epoch. The signed 63 bit integer can represent 1823-11-12 to 2116-02-20. When Integer
or Rational
is used (before 1823, after 2116, under nanosecond), Time
works slower than when the signed 63 bit integer is used.
Ruby
uses the C function localtime
and gmtime
to map between the number and 6-tuple (year,month,day,hour,minute,second). localtime
is used for local time and “gmtime” is used for UTC.
Integer
and Rational
has no range limit, but the localtime and gmtime has range limits due to the C types time_t
and struct tm
. If that limit is exceeded, Ruby
extrapolates the localtime function.
The Time
class always uses the Gregorian calendar. I.e. the proleptic Gregorian calendar is used. Other calendars, such as Julian calendar, are not supported.
time_t
can represent 1901-12-14 to 2038-01-19 if it is 32 bit signed integer, -292277022657-01-27 to 292277026596-12-05 if it is 64 bit signed integer. However localtime
on some platforms doesn’t supports negative time_t
(before 1970).
struct tm
has tm_year member to represent years. (tm_year = 0
means the year 1900.) It is defined as int
in the C standard. tm_year can represent between -2147481748 to 2147485547 if int
is 32 bit.
Ruby
supports leap seconds as far as if the C function localtime
and gmtime
supports it. They use the tz database in most Unix systems. The tz database has timezones which supports leap seconds. For example, “Asia/Tokyo” doesn’t support leap seconds but “right/Asia/Tokyo” supports leap seconds. So, Ruby
supports leap seconds if the TZ environment variable is set to “right/Asia/Tokyo” in most Unix systems.
All of these examples were done using the EST timezone which is GMT-5.
Time
Instance You can create a new instance of Time
with Time.new
. This will use the current system time. Time.now
is an alias for this. You can also pass parts of the time to Time.new
such as year, month, minute, etc. When you want to construct a time this way you must pass at least a year. If you pass the year with nothing else time will default to January 1 of that year at 00:00:00 with the current system timezone. Here are some examples:
Time.new(2002) #=> 2002-01-01 00:00:00 -0500 Time.new(2002, 10) #=> 2002-10-01 00:00:00 -0500 Time.new(2002, 10, 31) #=> 2002-10-31 00:00:00 -0500
You can pass a UTC offset:
Time.new(2002, 10, 31, 2, 2, 2, "+02:00") #=> 2002-10-31 02:02:02 +0200
zone = timezone("Europe/Athens") # Eastern European Time, UTC+2 Time.new(2002, 10, 31, 2, 2, 2, zone) #=> 2002-10-31 02:02:02 +0200
You can also use Time.local
and Time.utc
to infer 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 (with subsecond) since the Unix Epoch.
Time.at(628232400) #=> 1989-11-28 00:00:00 -0500
Time
Once you have an instance of Time
there is a multitude of things you can do with it. Below are some examples. For all of the following examples, we will work on the assumption that you have done the following:
t = Time.new(1993, 02, 24, 12, 0, 0, "+09:00")
Was that a monday?
t.monday? #=> false
What year was that again?
t.year #=> 1993
Was 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
First, what’s elsewhere. Class
Time
:
Inherits from class Object.
Includes module Comparable.
Here, class Time
provides methods that are useful for:
::new
: Returns a new time from specified arguments (year, month, etc.), including an optional timezone value.
::local
(aliased as ::mktime
): Same as ::new
, except the timezone is the local timezone.
::utc
(aliased as ::gm
): Same as ::new
, except the timezone is UTC.
::at
: Returns a new time based on seconds since epoch.
::now
: Returns a new time based on the current system time.
+
(plus): Returns a new time increased by the given number of seconds.
-
(minus): Returns a new time decreased by the given number of seconds.
year
: Returns the year of the time.
hour
: Returns the hours value for the time.
min
: Returns the minutes value for the time.
sec
: Returns the seconds value for the time.
usec
(aliased as tv_usec
): Returns the number of microseconds in the subseconds value of the time.
nsec
(aliased as tv_nsec
: Returns the number of nanoseconds in the subsecond part of the time.
subsec
: Returns the subseconds value for the time.
wday
: Returns the integer weekday value of the time (0 == Sunday).
yday
: Returns the integer yearday value of the time (1 == January 1).
hash
: Returns the integer hash value for the time.
utc_offset
(aliased as gmt_offset
and gmtoff
): Returns the offset in seconds between time and UTC.
to_f
: Returns the float number of seconds since epoch for the time.
to_i
(aliased as tv_sec
): Returns the integer number of seconds since epoch for the time.
to_r
: Returns the Rational
number of seconds since epoch for the time.
zone
: Returns a string representation of the timezone of the time.
dst?
(aliased as isdst
): Returns whether the time is DST (daylight saving time).
sunday?
: Returns whether the time is a Sunday.
monday?
: Returns whether the time is a Monday.
tuesday?
: Returns whether the time is a Tuesday.
wednesday?
: Returns whether the time is a Wednesday.
thursday?
: Returns whether the time is a Thursday.
friday?
: Returns whether time is a Friday.
saturday?
: Returns whether the time is a Saturday.
inspect
: Returns the time in detail as a string.
strftime
: Returns the time as a string, according to a given format.
to_a
: Returns a 10-element array of values from the time.
to_s
: Returns a string representation of the time.
getutc
(aliased as getgm
): Returns a new time converted to UTC.
getlocal
: Returns a new time converted to local time.
localtime
: Converts time to local time in place.
deconstruct_keys
: Returns a hash of time components used in pattern-matching.
round
:Returns a new time with subseconds rounded.
ceil
: Returns a new time with subseconds raised to a ceiling.
floor
: Returns a new time with subseconds lowered to a floor.
For the forms of argument zone
, see Timezone Specifiers.
Certain Time
methods accept arguments that specify timezones:
Time.at
: keyword argument in:
.
Time.new
: positional argument zone
or keyword argument in:
.
Time.now
: keyword argument in:
.
Time#getlocal
: positional argument zone
.
Time#localtime
: positional argument zone
.
The value given with any of these must be one of the following (each detailed below):
The zone value may be a string offset from UTC in the form '+HH:MM'
or '-HH:MM'
, where:
HH
is the 2-digit hour in the range 0..23
.
MM
is the 2-digit minute in the range 0..59
.
Examples:
t = Time.utc(2000, 1, 1, 20, 15, 1) # => 2000-01-01 20:15:01 UTC Time.at(t, in: '-23:59') # => 1999-12-31 20:16:01 -2359 Time.at(t, in: '+23:59') # => 2000-01-02 20:14:01 +2359
The zone value may be a letter in the range 'A'..'I'
or 'K'..'Z'
; see List of military time zones:
t = Time.utc(2000, 1, 1, 20, 15, 1) # => 2000-01-01 20:15:01 UTC Time.at(t, in: 'A') # => 2000-01-01 21:15:01 +0100 Time.at(t, in: 'I') # => 2000-01-02 05:15:01 +0900 Time.at(t, in: 'K') # => 2000-01-02 06:15:01 +1000 Time.at(t, in: 'Y') # => 2000-01-01 08:15:01 -1200 Time.at(t, in: 'Z') # => 2000-01-01 20:15:01 UTC
The zone value may be an integer number of seconds in the range -86399..86399
:
t = Time.utc(2000, 1, 1, 20, 15, 1) # => 2000-01-01 20:15:01 UTC Time.at(t, in: -86399) # => 1999-12-31 20:15:02 -235959 Time.at(t, in: 86399) # => 2000-01-02 20:15:00 +235959
The zone value may be an object responding to certain timezone methods, an instance of Timezone and TZInfo for example.
The timezone methods are:
local_to_utc
:
Called when Time.new
is invoked with tz
as the value of positional argument zone
or keyword argument in:
.
a Time-like object in the UTC timezone.
utc_to_local
:
Called when Time.at
or Time.now
is invoked with tz
as the value for keyword argument in:
, and when Time#getlocal
or Time#localtime
is called with tz
as the value for positional argument zone
.
The UTC offset will be calculated as the difference between the original time and the returned object as an Integer
. If the object is in fixed offset, its utc_offset
is also counted.
a Time-like object in the local timezone.
A custom timezone class may have these instance methods, which will be called if defined:
abbr
:
Called when Time#strftime
is invoked with a format involving %Z
.
a string abbreviation for the timezone name.
dst?
:
Called when Time.at
or Time.now
is invoked with tz
as the value for keyword argument in:
, and when Time#getlocal
or Time#localtime
is called with tz
as the value for positional argument zone
.
whether the time is daylight saving time.
name
:
Called when Marshal.dump(t)
is invoked
none.
the string name of the timezone.
Time
-Like Objects A Time
-like object is a container object capable of interfacing with timezone libraries for timezone conversion.
The argument to the timezone conversion methods above will have attributes similar to Time
, except that timezone related attributes are meaningless.
The objects returned by local_to_utc
and utc_to_local
methods of the timezone object may be of the same class as their arguments, of arbitrary object classes, or of class Integer
.
For a returned class other than Integer
, the class must have the following methods:
year
mon
mday
hour
min
sec
isdst
to_i
For a returned Integer
, its components, decomposed in UTC, are interpreted as times in the specified timezone.
If the class (the receiver of class methods, or the class of the receiver of instance methods) has find_timezone
singleton method, this method is called to achieve the corresponding timezone object from a timezone name.
For example, using Timezone:
class TimeWithTimezone < Time require 'timezone' def self.find_timezone(z) = Timezone[z] end TimeWithTimezone.now(in: "America/New_York") #=> 2023-12-25 00:00:00 -0500 TimeWithTimezone.new("2023-12-25 America/New_York") #=> 2023-12-25 00:00:00 -0500
Or, using TZInfo:
class TimeWithTZInfo < Time require 'tzinfo' def self.find_timezone(z) = TZInfo::Timezone.get(z) end TimeWithTZInfo.now(in: "America/New_York") #=> 2023-12-25 00:00:00 -0500 TimeWithTZInfo.new("2023-12-25 America/New_York") #=> 2023-12-25 00:00:00 -0500
You can define this method per subclasses, or on the toplevel Time
class.
An instance of class IO (commonly called a stream) represents an input/output stream in the underlying operating system. Class
IO is the basis for input and output in Ruby
.
Class
File
is the only class in the Ruby
core that is a subclass of IO. Some classes in the Ruby
standard library are also subclasses of IO; these include TCPSocket
and UDPSocket
.
The global constant ARGF
(also accessible as $<
) provides an IO-like stream that allows access to all file paths found in ARGV (or found in STDIN if ARGV is empty). ARGF
is not itself a subclass of IO.
Class
StringIO
provides an IO-like stream that handles a String
. StringIO
is not itself a subclass of IO.
Important objects based on IO include:
$stdin.
$stdout.
$stderr.
Instances of class File
.
An instance of IO may be created using:
IO.new
: returns a new IO object for the given integer file descriptor.
IO.open
: passes a new IO object to the given block.
IO.popen
: returns a new IO object that is connected to the $stdin and $stdout of a newly-launched subprocess.
Kernel#open
: Returns a new IO object connected to a given source: stream, file, or subprocess.
Like a File
stream, an IO stream has:
A read/write mode, which may be read-only, write-only, or read/write; see Read/Write Mode.
A data mode, which may be text-only or binary; see Data Mode.
Internal and external encodings; see Encodings.
And like other IO streams, it has:
A position, which determines where in the stream the next read or write is to occur; see Position.
A line number, which is a special, line-oriented, “position” (different from the position mentioned above); see Line Number.
io/console
Extension io/console
provides numerous methods for interacting with the console; requiring it adds numerous methods to class IO.
Many examples here use these variables:
# English text with newlines. text = <<~EOT First line Second line Fourth line Fifth line EOT # Russian text. russian = "\u{442 435 441 442}" # => "тест" # Binary data. data = "\u9990\u9991\u9992\u9993\u9994" # Text file. File.write('t.txt', text) # File with Russian text. File.write('t.rus', russian) # File with binary data. f = File.new('t.dat', 'wb:UTF-16') f.write(data) f.close
A number of IO methods accept optional keyword arguments that determine how a new stream is to be opened:
:mode
: Stream mode.
:flags
: Integer
file open flags; If mode
is also given, the two are bitwise-ORed.
:external_encoding
: External encoding for the stream.
:internal_encoding
: Internal encoding for the stream. '-'
is a synonym for the default internal encoding. If the value is nil
no conversion occurs.
:encoding
: Specifies external and internal encodings as 'extern:intern'
.
:textmode
: If a truthy value, specifies the mode as text-only, binary otherwise.
:binmode
: If a truthy value, specifies the mode as binary, text-only otherwise.
:autoclose
: If a truthy value, specifies that the fd
will close when the stream closes; otherwise it remains open.
:path:
If a string value is provided, it is used in inspect
and is available as path
method.
Also available are the options offered in String#encode
, which may control conversion between external and internal encoding.
You can perform basic stream IO with these methods, which typically operate on multi-byte strings:
IO#read
: Reads and returns some or all of the remaining bytes from the stream.
IO#write
: Writes zero or more strings to the stream; each given object that is not already a string is converted via to_s
.
An IO stream has a nonnegative integer position, which is the byte offset at which the next read or write is to occur. A new stream has position zero (and line number zero); method rewind
resets the position (and line number) to zero.
These methods discard buffers and the Encoding::Converter
instances used for that IO.
The relevant methods:
IO#tell
(aliased as #pos
): Returns the current position (in bytes) in the stream.
IO#pos=
: Sets the position of the stream to a given integer new_position
(in bytes).
IO#seek
: Sets the position of the stream to a given integer offset
(in bytes), relative to a given position whence
(indicating the beginning, end, or current position).
IO#rewind
: Positions the stream at the beginning (also resetting the line number).
A new IO stream may be open for reading, open for writing, or both.
A stream is automatically closed when claimed by the garbage collector.
Attempted reading or writing on a closed stream raises an exception.
The relevant methods:
IO#close
: Closes the stream for both reading and writing.
IO#close_read
: Closes the stream for reading.
IO#close_write
: Closes the stream for writing.
IO#closed?
: Returns whether the stream is closed.
You can query whether a stream is positioned at its end:
IO#eof?
(also aliased as #eof
): Returns whether the stream is at end-of-stream.
You can reposition to end-of-stream by using method IO#seek
:
f = File.new('t.txt') f.eof? # => false f.seek(0, :END) f.eof? # => true f.close
Or by reading all stream content (which is slower than using IO#seek
):
f.rewind f.eof? # => false f.read # => "First line\nSecond line\n\nFourth line\nFifth line\n" f.eof? # => true
Class
IO supports line-oriented input and output
Class
IO supports line-oriented input for files and IO streams
You can read lines from a file using these methods:
IO.foreach
: Reads each line and passes it to the given block.
IO.readlines
: Reads and returns all lines in an array.
For each of these methods:
You can specify open options.
Line parsing depends on the effective line separator; see Line Separator.
The length of each returned line depends on the effective line limit; see Line Limit.
You can read lines from an IO stream using these methods:
IO#each_line
: Reads each remaining line, passing it to the given block.
IO#gets
: Returns the next line.
IO#readline
: Like gets
, but raises an exception at end-of-stream.
IO#readlines
: Returns all remaining lines in an array.
For each of these methods:
Reading may begin mid-line, depending on the stream’s position; see Position.
Line parsing depends on the effective line separator; see Line Separator.
The length of each returned line depends on the effective line limit; see Line Limit.
Each of the line input methods uses a line separator: the string that determines what is considered a line; it is sometimes called the input record separator.
The default line separator is taken from global variable $/
, whose initial value is "\n"
.
Generally, the line to be read next is all data from the current position to the next line separator (but see Special Line Separator Values):
f = File.new('t.txt') # Method gets with no sep argument returns the next line, according to $/. f.gets # => "First line\n" f.gets # => "Second line\n" f.gets # => "\n" f.gets # => "Fourth line\n" f.gets # => "Fifth line\n" f.close
You can use a different line separator by passing argument sep
:
f = File.new('t.txt') f.gets('l') # => "First l" f.gets('li') # => "ine\nSecond li" f.gets('lin') # => "ne\n\nFourth lin" f.gets # => "e\n" f.close
Or by setting global variable $/
:
f = File.new('t.txt') $/ = 'l' f.gets # => "First l" f.gets # => "ine\nSecond l" f.gets # => "ine\n\nFourth l" f.close
Each of the line input methods accepts two special values for parameter sep
:
nil
: The entire stream is to be read (“slurped”) into a single string:
f = File.new('t.txt') f.gets(nil) # => "First line\nSecond line\n\nFourth line\nFifth line\n" f.close
''
(the empty string): The next “paragraph” is to be read (paragraphs being separated by two consecutive line separators):
f = File.new('t.txt') f.gets('') # => "First line\nSecond line\n\n" f.gets('') # => "Fourth line\nFifth line\n" f.close
Each of the line input methods uses an integer line limit, which restricts the number of bytes that may be returned. (A multi-byte character will not be split, and so a returned line may be slightly longer than the limit).
The default limit value is -1
; any negative limit value means that there is no limit.
If there is no limit, the line is determined only by sep
.
# Text with 1-byte characters. File.open('t.txt') {|f| f.gets(1) } # => "F" File.open('t.txt') {|f| f.gets(2) } # => "Fi" File.open('t.txt') {|f| f.gets(3) } # => "Fir" File.open('t.txt') {|f| f.gets(4) } # => "Firs" # No more than one line. File.open('t.txt') {|f| f.gets(10) } # => "First line" File.open('t.txt') {|f| f.gets(11) } # => "First line\n" File.open('t.txt') {|f| f.gets(12) } # => "First line\n" # Text with 2-byte characters, which will not be split. File.open('t.rus') {|f| f.gets(1).size } # => 1 File.open('t.rus') {|f| f.gets(2).size } # => 1 File.open('t.rus') {|f| f.gets(3).size } # => 2 File.open('t.rus') {|f| f.gets(4).size } # => 2
With arguments sep
and limit
given, combines the two behaviors:
Returns the next line as determined by line separator sep
.
But returns no more bytes than are allowed by the limit limit
.
Example:
File.open('t.txt') {|f| f.gets('li', 20) } # => "First li" File.open('t.txt') {|f| f.gets('li', 2) } # => "Fi"
A readable IO stream has a non-negative integer line number:
IO#lineno
: Returns the line number.
IO#lineno=
: Resets and returns the line number.
Unless modified by a call to method IO#lineno=
, the line number is the number of lines read by certain line-oriented methods, according to the effective line separator:
IO.foreach
: Increments the line number on each call to the block.
IO#each_line
: Increments the line number on each call to the block.
IO#gets
: Increments the line number.
IO#readline
: Increments the line number.
IO#readlines
: Increments the line number for each line read.
A new stream is initially has line number zero (and position zero); method rewind
resets the line number (and position) to zero:
f = File.new('t.txt') f.lineno # => 0 f.gets # => "First line\n" f.lineno # => 1 f.rewind f.lineno # => 0 f.close
Reading lines from a stream usually changes its line number:
f = File.new('t.txt', 'r') f.lineno # => 0 f.readline # => "This is line one.\n" f.lineno # => 1 f.readline # => "This is the second line.\n" f.lineno # => 2 f.readline # => "Here's the third line.\n" f.lineno # => 3 f.eof? # => true f.close
Iterating over lines in a stream usually changes its line number:
File.open('t.txt') do |f| f.each_line do |line| p "position=#{f.pos} eof?=#{f.eof?} lineno=#{f.lineno}" end end
Output:
"position=11 eof?=false lineno=1" "position=23 eof?=false lineno=2" "position=24 eof?=false lineno=3" "position=36 eof?=false lineno=4" "position=47 eof?=true lineno=5"
Unlike the stream’s position, the line number does not affect where the next read or write will occur:
f = File.new('t.txt') f.lineno = 1000 f.lineno # => 1000 f.gets # => "First line\n" f.lineno # => 1001 f.close
Associated with the line number is the global variable $.
:
When a stream is opened, $.
is not set; its value is left over from previous activity in the process:
$. = 41 f = File.new('t.txt') $. = 41 # => 41 f.close
When a stream is read, $.
is set to the line number for that stream:
f0 = File.new('t.txt') f1 = File.new('t.dat') f0.readlines # => ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"] $. # => 5 f1.readlines # => ["\xFE\xFF\x99\x90\x99\x91\x99\x92\x99\x93\x99\x94"] $. # => 1 f0.close f1.close
Methods IO#rewind
and IO#seek
do not affect $.
:
f = File.new('t.txt') f.readlines # => ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"] $. # => 5 f.rewind f.seek(0, :SET) $. # => 5 f.close
You can write to an IO stream line-by-line using this method:
IO#puts
: Writes objects to the stream.
You can process an IO stream character-by-character using these methods:
IO#getc
: Reads and returns the next character from the stream.
IO#readchar
: Like getc
, but raises an exception at end-of-stream.
IO#ungetc
: Pushes back (“unshifts”) a character or integer onto the stream.
IO#putc
: Writes a character to the stream.
IO#each_char
: Reads each remaining character in the stream, passing the character to the given block.
You can process an IO stream byte-by-byte using these methods:
IO#getbyte
: Returns the next 8-bit byte as an integer in range 0..255.
IO#readbyte
: Like getbyte
, but raises an exception if at end-of-stream.
IO#ungetbyte
: Pushes back (“unshifts”) a byte back onto the stream.
IO#each_byte
: Reads each remaining byte in the stream, passing the byte to the given block.
You can process an IO stream codepoint-by-codepoint:
IO#each_codepoint
: Reads each remaining codepoint, passing it to the given block.
First, what’s elsewhere. Class
IO:
Inherits from class Object.
Includes module Enumerable, which provides dozens of additional methods.
Here, class IO provides methods that are useful for:
::new
(aliased as ::for_fd
): Creates and returns a new IO object for the given integer file descriptor.
::open
: Creates a new IO object.
::pipe
: Creates a connected pair of reader and writer IO objects.
::popen
: Creates an IO object to interact with a subprocess.
::select
: Selects which given IO instances are ready for reading, writing, or have pending exceptions.
::binread
: Returns a binary string with all or a subset of bytes from the given file.
::read
: Returns a string with all or a subset of bytes from the given file.
::readlines
: Returns an array of strings, which are the lines from the given file.
getbyte
: Returns the next 8-bit byte read from self
as an integer.
getc
: Returns the next character read from self
as a string.
gets
: Returns the line read from self
.
pread
: Returns all or the next n bytes read from self
, not updating the receiver’s offset.
read
: Returns all remaining or the next n bytes read from self
for a given n.
read_nonblock
: the next n bytes read from self
for a given n, in non-block mode.
readbyte
: Returns the next byte read from self
; same as getbyte
, but raises an exception on end-of-stream.
readchar
: Returns the next character read from self
; same as getc
, but raises an exception on end-of-stream.
readline
: Returns the next line read from self
; same as getline, but raises an exception of end-of-stream.
readlines
: Returns an array of all lines read read from self
.
readpartial
: Returns up to the given number of bytes from self
.
::binwrite
: Writes the given string to the file at the given filepath, in binary mode.
::write
: Writes the given string to self
.
<<
: Appends the given string to self
.
print
: Prints last read line or given objects to self
.
printf
: Writes to self
based on the given format string and objects.
putc
: Writes a character to self
.
puts
: Writes lines to self
, making sure line ends with a newline.
pwrite
: Writes the given string at the given offset, not updating the receiver’s offset.
write
: Writes one or more given strings to self
.
write_nonblock
: Writes one or more given strings to self
in non-blocking mode.
lineno
: Returns the current line number in self
.
lineno=
: Sets the line number is self
.
pos
(aliased as tell
): Returns the current byte offset in self
.
pos=
: Sets the byte offset in self
.
reopen
: Reassociates self
with a new or existing IO stream.
rewind
: Positions self
to the beginning of input.
seek
: Sets the offset for self
relative to given position.
::foreach
: Yields each line of given file to the block.
each
(aliased as each_line
): Calls the given block with each successive line in self
.
each_byte
: Calls the given block with each successive byte in self
as an integer.
each_char
: Calls the given block with each successive character in self
as a string.
each_codepoint
: Calls the given block with each successive codepoint in self
as an integer.
autoclose=
: Sets whether self
auto-closes.
binmode
: Sets self
to binary mode.
close
: Closes self
.
close_on_exec=
: Sets the close-on-exec flag.
close_read
: Closes self
for reading.
close_write
: Closes self
for writing.
set_encoding
: Sets the encoding for self
.
set_encoding_by_bom
: Sets the encoding for self
, based on its Unicode byte-order-mark.
sync=
: Sets the sync-mode to the given value.
autoclose?
: Returns whether self
auto-closes.
binmode?
: Returns whether self
is in binary mode.
close_on_exec?
: Returns the close-on-exec flag for self
.
closed?
: Returns whether self
is closed.
eof?
(aliased as eof
): Returns whether self
is at end-of-stream.
external_encoding
: Returns the external encoding object for self
.
fileno
(aliased as to_i
): Returns the integer file descriptor for self
internal_encoding
: Returns the internal encoding object for self
.
pid
: Returns the process ID of a child process associated with self
, if self
was created by ::popen
.
stat
: Returns the File::Stat
object containing status information for self
.
sync
: Returns whether self
is in sync-mode.
tty?
(aliased as isatty
): Returns whether self
is a terminal.
fdatasync
: Immediately writes all buffered data in self
to disk.
flush
: Flushes any buffered data within self
to the underlying operating system.
fsync
: Immediately writes all buffered data and attributes in self
to disk.
ungetbyte
: Prepends buffer for self
with given integer byte or string.
ungetc
: Prepends buffer for self
with given string.
::sysopen
: Opens the file given by its path, returning the integer file descriptor.
advise
: Announces the intention to access data from self
in a specific way.
fcntl
: Passes a low-level command to the file specified by the given file descriptor.
ioctl
: Passes a low-level command to the device specified by the given file descriptor.
sysread
: Returns up to the next n bytes read from self using a low-level read.
sysseek
: Sets the offset for self
.
syswrite
: Writes the given string to self
using a low-level write.
::copy_stream
: Copies data from a source to a destination, each of which is a filepath or an IO-like object.
::try_convert
: Returns a new IO object resulting from converting the given object.
inspect
: Returns the string representation of self
.
Class
Struct provides a convenient way to create a simple class that can store and fetch values.
This example creates a subclass of Struct
, Struct::Customer
; the first argument, a string, is the name of the subclass; the other arguments, symbols, determine the members of the new subclass.
Customer = Struct.new('Customer', :name, :address, :zip) Customer.name # => "Struct::Customer" Customer.class # => Class Customer.superclass # => Struct
Corresponding to each member are two methods, a writer and a reader, that store and fetch values:
methods = Customer.instance_methods false methods # => [:zip, :address=, :zip=, :address, :name, :name=]
An instance of the subclass may be created, and its members assigned values, via method ::new
:
joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) joe # => #<struct Struct::Customer name="Joe Smith", address="123 Maple, Anytown NC", zip=12345>
The member values may be managed thus:
joe.name # => "Joe Smith" joe.name = 'Joseph Smith' joe.name # => "Joseph Smith"
And thus; note that member name may be expressed as either a string or a symbol:
joe[:name] # => "Joseph Smith" joe[:name] = 'Joseph Smith, Jr.' joe['name'] # => "Joseph Smith, Jr."
See Struct::new
.
First, what’s elsewhere. Class
Struct:
Inherits from class Object.
Includes module Enumerable, which provides dozens of additional methods.
See also Data
, which is a somewhat similar, but stricter concept for defining immutable value objects.
Here, class Struct provides methods that are useful for:
Struct
Subclass ::new
: Returns a new subclass of Struct.
==
: Returns whether a given object is equal to self
, using ==
to compare member values.
eql?
: Returns whether a given object is equal to self
, using eql?
to compare member values.
[]
: Returns the value associated with a given member name.
to_a
(aliased as values
, deconstruct
): Returns the member values in self
as an array.
deconstruct_keys
: Returns a hash of the name/value pairs for given member names.
dig
: Returns the object in nested objects that is specified by a given member name and additional arguments.
members
: Returns an array of the member names.
select
(aliased as filter
): Returns an array of member values from self
, as selected by the given block.
values_at
: Returns an array containing values for given member names.
[]=
: Assigns a given value to a given member name.
each
: Calls a given block with each member name.
each_pair
: Calls a given block with each member name/value pair.
UNIXServer
represents a UNIX domain stream server socket.
UNIXSocket
represents a UNIX domain stream client socket.