Skip to content

jaynetics/leto

Repository files navigation

Leto

Gem Version Build Status Coverage

A generic object traverser for Ruby (named after the Greek childbearing goddess Leto).

Takes an object and recursively yields:

  • the given object
  • instance variables, class variables, constants
  • Hash keys and values
  • Enumerable members
  • Struct members
  • Data members
  • Range begins and ends

This makes stuff like deep-freezing fairly easy to implement:

my_object = [ { a: ['b', 'c'..'d'] } ]

Leto.call(my_object, &:freeze)

my_object.frozen? # => true
my_object[0].frozen? # => true
my_object[0][:a][1].begin.frozen? # => true

Note: the slightly smarter Leto.deep_freeze is one of the included utility methods.

Usage

Basic example:

object = [{ a: ['b', 'c'..'d'] }]

Leto.call(object) { |el| p el }
# prints:
#
# [{:a=>["b", ["c".."d"]]}]
# {:a=>["b", ["c".."d"]]}
# :a
# ["b", ["c".."d"]]
# "b"
# "c".."d"
# "c"
# "d"

Leto.call(object).to_a
# => [[{:a=>["b", ["c".."d"]]}], {:a=>["b", ["c".."d"]]}, :a, ...]

# Leto::trace behaves like ::call, but also yields each (sub-)object's path:
Leto.trace(object) { |el, path| puts "#{el.inspect.ljust(23)} @#{path}" }
# prints:
#
# [{:a=>["b", "c".."d"]}] @#<Leto::Path [{:a=>["b", "c".."d"]}]>
# {:a=>["b", "c".."d"]}   @#<Leto::Path [{:a=>["b", "c".."d"]}][0]>
# :a                      @#<Leto::Path [{:a=>["b", "c".."d"]}][0].keys[0]>
# ["b", "c".."d"]         @#<Leto::Path [{:a=>["b", "c".."d"]}][0][:a]>
# "b"                     @#<Leto::Path [{:a=>["b", "c".."d"]}][0][:a][0]>
# "c".."d"                @#<Leto::Path [{:a=>["b", "c".."d"]}][0][:a][1]>
# "c"                     @#<Leto::Path [{:a=>["b", "c".."d"]}][0][:a][1].begin>
# "d"                     @#<Leto::Path [{:a=>["b", "c".."d"]}][0][:a][1].end>

# paths can be looked up with Leto::Path#resolve or Leto::dig
path = Leto.trace(object).map { |_el, path| path }.last # => #<Leto::Path...>
path.resolve # => "d"
Leto.dig(object, path) # => "d"
Leto.dig(object, [[:[], 0], [:[], :a], [:[], 1], [:end]]) # => "d"

Included utility methods

Benchmarks

    Leto.deep_freeze:     8762.1 i/s
 IceNine.deep_freeze:     7390.3 i/s - 1.19x  (± 0.00) slower

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/jaynetics/leto.

License

The gem is available as open source under the terms of the MIT License.

About

Generic object traverser for Ruby

Resources

License

Stars

Watchers

Forks

Packages

No packages published