Tree Filter

Filter arbitrary data trees with a concise query language. Similar to how the Jenkins API works, if you happen to be familiar with that.

name,environments             # Select specific attributes from a hash
environments[id,last_deploy]  # Select attributes from sub-hash
environments[*]               # Select all attributes

Usage

require 'tree_filter'

data = {
  'name' => 'don',
  'contact' => {
    'phone' => '415-123-4567',
    'email' => '[email protected]'
  }
}

TreeFilter.new("name,contact[email]").filter(data)
# => {'name' => 'don', 'contact' => {'email' => '[email protected]'}}

Different data structures can be presented dependent on whether they are explicitly expanded or not. This is typically used when referring to other resources in an API response.

data = {
  'name' => 'don',
  'contact' => TreeFilter::Leaf.new('/contact-data/1', {
    'phone' => '415-123-4567',
    'email' => '[email protected]'
  })
}

TreeFilter.new("*").filter(data)
# => {'name' => 'don', 'contact' => '/contact-data/1'}

TreeFilter.new("contact[*]").filter(data)
# => {'contact' => {'phone' => '415-123-4567', 'email' => '[email protected]'}}

For nested data structures, evaluation can be defered until it is actually required. This can defer resource lookups, and also allows cyclic structures!

data = { 'name' => 'don', }

data['contact'] = TreeFilter::Leaf.new(
  '/contact-data/1',
  TreeFilter::Defer.new(->{{
    'email' => '[email protected]',
    'person' => TreeFilter::Leaf.new('/person/1', data)
  }})
)

TreeFilter.new("contact[person[contact[email]]]").filter(data)
# => {'contact' => {'person' => {'contact' => {'email' => '[email protected]'}}}}

Compatibility

All rubies that ruby core supports! Should work on JRuby and Rubinius too.

Support

Make a new github issue.

Contributing

Fork and patch! Before any changes are merged to master, we need you to sign an Individual Contributor Agreement (Google Form).

Run tests:

gem install bundler
bundle
bundle exec rspec