In general, while a TracePoint
callback is running, other registered callbacks are not called to avoid confusion by reentrance. This method allows the reentrance in a given block. This method should be used carefully, otherwise the callback can be easily called infinitely.
If this method is called when the reentrance is already allowed, it raises a RuntimeError
.
Example:
# Without reentry # --------------- line_handler = TracePoint.new(:line) do |tp| next if tp.path != __FILE__ # only work in this file puts "Line handler" binding.eval("class C; end") end.enable class_handler = TracePoint.new(:class) do |tp| puts "Class handler" end.enable class B end # This script will print "Class handler" only once: when inside :line # handler, all other handlers are ignored # With reentry # ------------ line_handler = TracePoint.new(:line) do |tp| next if tp.path != __FILE__ # only work in this file next if (__LINE__..__LINE__+3).cover?(tp.lineno) # don't be invoked from itself puts "Line handler" TracePoint.allow_reentry { binding.eval("class C; end") } end.enable class_handler = TracePoint.new(:class) do |tp| puts "Class handler" end.enable class B end # This wil print "Class handler" twice: inside allow_reentry block in :line # handler, other handlers are enabled.
Note that the example shows the principal effect of the method, but its practical usage is for debugging libraries that sometimes require other libraries hooks to not be affected by debugger being inside trace point handling. Precautions should be taken against infinite recursion in this case (note that we needed to filter out calls by itself from :line handler, otherwise it will call itself infinitely).
Returns an array of the names of global variables. This includes special regexp global variables such as $~
and $+
, but does not include the numbered regexp global variables ($1
, $2
, etc.).
global_variables.grep /std/ #=> [:$stdin, :$stdout, :$stderr]
Returns the names of the current local variables.
fred = 1 for i in 1..10 # ... end local_variables #=> [:fred, :i]
Returns true
if yield
would execute a block in the current context. The iterator?
form is mildly deprecated.
def try if block_given? yield else "no block" end end try #=> "no block" try { "hello" } #=> "hello" try do "hello" end #=> "hello"
Returns an array containing truthy elements returned by the block.
With a block given, calls the block with successive elements; returns an array containing each truthy value returned by the block:
(0..9).filter_map {|i| i * 2 if i.even? } # => [0, 4, 8, 12, 16] {foo: 0, bar: 1, baz: 2}.filter_map {|key, value| key if value.even? } # => [:foo, :baz]
When no block given, returns an Enumerator
.
With a block given, calls the block with each element, but in reverse order; returns self
:
a = [] (1..4).reverse_each {|element| a.push(-element) } # => 1..4 a # => [-4, -3, -2, -1] a = [] %w[a b c d].reverse_each {|element| a.push(element) } # => ["a", "b", "c", "d"] a # => ["d", "c", "b", "a"] a = [] h.reverse_each {|element| a.push(element) } # => {:foo=>0, :bar=>1, :baz=>2} a # => [[:baz, 2], [:bar, 1], [:foo, 0]]
With no block given, returns an Enumerator
.
Creates an enumerator for each chunked elements. The ends of chunks are defined by pattern and the block.
If pattern === elt
returns true
or the block returns true
for the element, the element is end of a chunk.
The ===
and block is called from the first element to the last element of enum.
The result enumerator yields the chunked elements as an array. So each
method can be called as follows:
enum.slice_after(pattern).each { |ary| ... } enum.slice_after { |elt| bool }.each { |ary| ... }
Other methods of the Enumerator
class and Enumerable
module, such as map
, etc., are also usable.
For example, continuation lines (lines end with backslash) can be concatenated as follows:
lines = ["foo\n", "bar\\\n", "baz\n", "\n", "qux\n"] e = lines.slice_after(/(?<!\\)\n\z/) p e.to_a #=> [["foo\n"], ["bar\\\n", "baz\n"], ["\n"], ["qux\n"]] p e.map {|ll| ll[0...-1].map {|l| l.sub(/\\\n\z/, "") }.join + ll.last } #=>["foo\n", "barbaz\n", "\n", "qux\n"]
Returns the last Error
of the current executing Thread
or nil if none
Sets the last Error
of the current executing Thread
to error
Enters exclusive section.
Returns true if this monitor is locked by any thread
Returns the source file origin from the given object
.
See ::trace_object_allocations
for more information and examples.
Returns the original line from source for from the given object
.
See ::trace_object_allocations
for more information and examples.
Adds aProc as a finalizer, to be called after obj was destroyed. The object ID of the obj will be passed as an argument to aProc. If aProc is a lambda or method, make sure it can be called with a single argument.
The return value is an array [0, aProc]
.
The two recommended patterns are to either create the finaliser proc in a non-instance method where it can safely capture the needed state, or to use a custom callable object that stores the needed state explicitly as instance variables.
class Foo def initialize(data_needed_for_finalization) ObjectSpace.define_finalizer(self, self.class.create_finalizer(data_needed_for_finalization)) end def self.create_finalizer(data_needed_for_finalization) proc { puts "finalizing #{data_needed_for_finalization}" } end end class Bar class Remover def initialize(data_needed_for_finalization) @data_needed_for_finalization = data_needed_for_finalization end def call(id) puts "finalizing #{@data_needed_for_finalization}" end end def initialize(data_needed_for_finalization) ObjectSpace.define_finalizer(self, Remover.new(data_needed_for_finalization)) end end
Note that if your finalizer references the object to be finalized it will never be run on GC
, although it will still be run at exit. You will get a warning if you capture the object to be finalized as the receiver of the finalizer.
class CapturesSelf def initialize(name) ObjectSpace.define_finalizer(self, proc { # this finalizer will only be run on exit puts "finalizing #{name}" }) end end
Also note that finalization can be unpredictable and is never guaranteed to be run except on exit.
Removes all finalizers for obj.
Alias of GC.start
Alias of GC.start
Load yaml
in to a Ruby data structure. If multiple documents are provided, the object contained in the first document will be returned. filename
will be used in the exception message if any exception is raised while parsing. If yaml
is empty, it returns the specified fallback
return value, which defaults to false
.
Raises a Psych::SyntaxError
when a YAML
syntax error is detected.
Example:
Psych.unsafe_load("--- a") # => 'a' Psych.unsafe_load("---\n - a\n - b") # => ['a', 'b'] begin Psych.unsafe_load("--- `", filename: "file.txt") rescue Psych::SyntaxError => ex ex.file # => 'file.txt' ex.message # => "(file.txt): found character that cannot start any token" end
When the optional symbolize_names
keyword argument is set to a true value, returns symbols for keys in Hash
objects (default: strings).
Psych.unsafe_load("---\n foo: bar") # => {"foo"=>"bar"} Psych.unsafe_load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
Raises a TypeError
when ‘yaml` parameter is NilClass
NOTE: This method *should not* be used to parse untrusted documents, such as YAML
documents that are supplied via user input. Instead, please use the load method or the safe_load
method.
Safely load the yaml string in yaml
. By default, only the following classes are allowed to be deserialized:
Recursive data structures are not allowed by default. Arbitrary classes can be allowed by adding those classes to the permitted_classes
keyword argument. They are additive. For example, to allow Date
deserialization:
Psych.safe_load(yaml, permitted_classes: [Date])
Now the Date
class can be loaded in addition to the classes listed above.
Aliases can be explicitly allowed by changing the aliases
keyword argument. For example:
x = [] x << x yaml = Psych.dump x Psych.safe_load yaml # => raises an exception Psych.safe_load yaml, aliases: true # => loads the aliases
A Psych::DisallowedClass
exception will be raised if the yaml contains a class that isn’t in the permitted_classes
list.
A Psych::AliasesNotEnabled
exception will be raised if the yaml contains aliases but the aliases
keyword argument is set to false.
filename
will be used in the exception message if any exception is raised while parsing.
When the optional symbolize_names
keyword argument is set to a true value, returns symbols for keys in Hash
objects (default: strings).
Psych.safe_load("---\n foo: bar") # => {"foo"=>"bar"} Psych.safe_load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
Load multiple documents given in yaml
. Returns the parsed documents as a list. If a block is given, each document will be converted to Ruby and passed to the block during parsing
Example:
Psych.load_stream("--- foo\n...\n--- bar\n...") # => ['foo', 'bar'] list = [] Psych.load_stream("--- foo\n...\n--- bar\n...") do |ruby| list << ruby end list # => ['foo', 'bar']
Loads the document contained in filename
. Returns the yaml contained in filename
as a Ruby object, or if the file is empty, it returns the specified fallback
return value, which defaults to false
. See load for options.
Returns the version of libyaml being used
Returns the string which represents the version of zlib library.