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
Symbol
objects represent names 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
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
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"]
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.
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.
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
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.
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
The syslog package provides a Ruby interface to the POSIX system logging facility.
Syslog
messages are typically passed to a central logging daemon. The daemon may filter them; route them into different files (usually found under /var/log); place them in SQL databases; forward them to centralized logging servers via TCP or UDP; or even alert the system administrator via email, pager or text message.
Unlike application-level logging via Logger
or Log4r, syslog is designed to allow secure tamper-proof logging.
The syslog protocol is standardized in RFC 5424.
The Benchmark
module provides methods to measure and report the time used to execute Ruby code.
Measure the time to construct the string given by the expression "a"*1_000_000_000
:
require 'benchmark' puts Benchmark.measure { "a"*1_000_000_000 }
On my machine (OSX 10.8.3 on i5 1.7 GHz) this generates:
0.350000 0.400000 0.750000 ( 0.835234)
This report shows the user CPU time, system CPU time, the sum of the user and system CPU times, and the elapsed real time. The unit of time is seconds.
Do some experiments sequentially using the bm
method:
require 'benchmark' n = 5000000 Benchmark.bm do |x| x.report { for i in 1..n; a = "1"; end } x.report { n.times do ; a = "1"; end } x.report { 1.upto(n) do ; a = "1"; end } end
The result:
user system total real 1.010000 0.000000 1.010000 ( 1.014479) 1.000000 0.000000 1.000000 ( 0.998261) 0.980000 0.000000 0.980000 ( 0.981335)
Continuing the previous example, put a label in each report:
require 'benchmark' n = 5000000 Benchmark.bm(7) do |x| x.report("for:") { for i in 1..n; a = "1"; end } x.report("times:") { n.times do ; a = "1"; end } x.report("upto:") { 1.upto(n) do ; a = "1"; end } end
The result:
user system total real for: 1.010000 0.000000 1.010000 ( 1.015688) times: 1.000000 0.000000 1.000000 ( 1.003611) upto: 1.030000 0.000000 1.030000 ( 1.028098)
The times for some benchmarks depend on the order in which items are run. These differences are due to the cost of memory allocation and garbage collection. To avoid these discrepancies, the bmbm
method is provided. For example, to compare ways to sort an array of floats:
require 'benchmark' array = (1..1000000).map { rand } Benchmark.bmbm do |x| x.report("sort!") { array.dup.sort! } x.report("sort") { array.dup.sort } end
The result:
Rehearsal ----------------------------------------- sort! 1.490000 0.010000 1.500000 ( 1.490520) sort 1.460000 0.000000 1.460000 ( 1.463025) -------------------------------- total: 2.960000sec user system total real sort! 1.460000 0.000000 1.460000 ( 1.460465) sort 1.450000 0.010000 1.460000 ( 1.448327)
Report statistics of sequential experiments with unique labels, using the benchmark
method:
require 'benchmark' include Benchmark # we need the CAPTION and FORMAT constants n = 5000000 Benchmark.benchmark(CAPTION, 7, FORMAT, ">total:", ">avg:") do |x| tf = x.report("for:") { for i in 1..n; a = "1"; end } tt = x.report("times:") { n.times do ; a = "1"; end } tu = x.report("upto:") { 1.upto(n) do ; a = "1"; end } [tf+tt+tu, (tf+tt+tu)/3] end
The result:
user system total real for: 0.950000 0.000000 0.950000 ( 0.952039) times: 0.980000 0.000000 0.980000 ( 0.984938) upto: 0.950000 0.000000 0.950000 ( 0.946787) >total: 2.880000 0.000000 2.880000 ( 2.883764) >avg: 0.960000 0.000000 0.960000 ( 0.961255)
Create a new Alias
that points to an anchor
Create a new Psych::Nodes::Document
object.
version
is a list indicating the YAML version. tags_directives
is a list of tag directive declarations implicit
is a flag indicating whether the document will be implicitly started.
This creates a YAML document object that represents a YAML 1.1 document with one tag directive, and has an implicit start:
Psych::Nodes::Document.new( [1,1], [["!", "tag:tenderlovemaking.com,2009:"]], true )
See also Psych::Handler#start_document
Returns the root node. A Document
may only have one root node: yaml.org/spec/1.1/#id898031
Create a new Psych::Nodes::Mapping
object.
anchor
is the anchor associated with the map or nil
. tag
is the tag associated with the map or nil
. implicit
is a boolean indicating whether or not the map was implicitly started. style
is an integer indicating the mapping style.
See also Psych::Handler#start_mapping
Create a new Psych::Nodes::Node