hpath 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +3 -0
- data/Gemfile +6 -1
- data/README.md +120 -2
- data/Rakefile +5 -0
- data/hpath.gemspec +5 -3
- data/lib/hpath.rb +91 -3
- data/lib/hpath/filter.rb +33 -0
- data/lib/hpath/parser.rb +105 -0
- data/lib/hpath/version.rb +1 -1
- data/spec/hpath/filter_spec.rb +15 -0
- data/spec/hpath/parser_spec.rb +26 -0
- data/spec/hpath_spec.rb +70 -0
- data/spec/spec_helper.rb +12 -0
- metadata +48 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d97f5894eb225d22238c604ab0fc4e06a31e5fa1
|
4
|
+
data.tar.gz: a52d7400d901e41584dafb8613048358cfb78a2f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ed6a57ed11bd16a296a6572ea282190960f0f60ca925d7226c469c461948c9bdc89e10972fed14221316c0fa138382cabf6c10b9a05485bbcf524b1b49f3bc1
|
7
|
+
data.tar.gz: 3e0bb084b7274f51c8c53bd175ee3992f7049d3689d257f9851a31376ce88bd01cc8e6800d3a105c761869fd3e8f7fb3497b064c66b004f3f3c2abbf16368af4
|
data/.rspec
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Hpath
|
2
2
|
|
3
|
-
|
3
|
+
This code is heavy work in progress and does not work today. The examples and usage hints given below only show the goals.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -18,7 +18,125 @@ Or install it yourself as:
|
|
18
18
|
|
19
19
|
## Usage
|
20
20
|
|
21
|
-
|
21
|
+
Here are some examples of hpath in action.
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
record = {
|
25
|
+
title: "About a hash",
|
26
|
+
creator: [
|
27
|
+
"Hashman",
|
28
|
+
"Hashboy"
|
29
|
+
],
|
30
|
+
price: [
|
31
|
+
{ currency: :USD, value: 12.99 },
|
32
|
+
{ currency: :EUR, value: 8.99 }
|
33
|
+
],
|
34
|
+
subject: [
|
35
|
+
{ type: "automatic", value: "hash" },
|
36
|
+
{ type: "automatic", value: "hashes" },
|
37
|
+
{ type: "automatic", value: "ruby" },
|
38
|
+
{ type: "manual", value: "hash" },
|
39
|
+
{ type: "manual", value: "array" },
|
40
|
+
{ type: "manual", value: "Hashman" },
|
41
|
+
{ type: "manual", value: "Hashboy" },
|
42
|
+
],
|
43
|
+
_source: {
|
44
|
+
"id" => "123",
|
45
|
+
"title" => "<h1>About a hash</h1>",
|
46
|
+
...
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
Hpath.get record, "/title"
|
51
|
+
# => "About a hash"
|
52
|
+
|
53
|
+
Hpath.get record, "/_source/id"
|
54
|
+
# => "123"
|
55
|
+
|
56
|
+
Hpath.get record, "/_source/[id, title]"
|
57
|
+
# => { "id" => "123", "title" => "<h1>About a hash</h1>" }
|
58
|
+
|
59
|
+
Hpath.get record, "/price/*[currency=USD]"
|
60
|
+
# => [{ currency: :USD, value: 12.99 }]
|
61
|
+
|
62
|
+
Hpath.get record, "/price/*[currency=USD,value<10]"
|
63
|
+
# => nil
|
64
|
+
|
65
|
+
Hpath.get record, "/price/*[(currency=USD|currency=EUR),value<10]"
|
66
|
+
# => [{ currency: :EUR, value: 8.99 }]
|
67
|
+
|
68
|
+
Hpath.get record, "/subject/*[type=automatic]"
|
69
|
+
# => [
|
70
|
+
# { type: "automatic", value: "hash" },
|
71
|
+
# { type: "automatic", value: "hashes" },
|
72
|
+
# { type: "automatic", value: "ruby" }
|
73
|
+
# ]
|
74
|
+
|
75
|
+
Hpath.get record, "/subject/*[type=automatic]/type"
|
76
|
+
# => ["automatic", "automatic", "automatic"]
|
77
|
+
```
|
78
|
+
|
79
|
+
## Syntax
|
80
|
+
|
81
|
+
### `/`
|
82
|
+
Get the root element.
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
Hpath.get [:a,:b,:c], "/"
|
86
|
+
# => [:a,:b,:c]
|
87
|
+
```
|
88
|
+
|
89
|
+
### `/[n]`
|
90
|
+
Get the n-th element of an array.
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
Hpath.get [:a,:b,:c], "/[1]"
|
94
|
+
# => :a
|
95
|
+
```
|
96
|
+
|
97
|
+
### `/[n,m,...]`
|
98
|
+
Get the n-th, m-th and ... element of an array.
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
Hpath.get [:a,:b,:c], "/[1,2]"
|
102
|
+
# => [:a,:b]
|
103
|
+
```
|
104
|
+
|
105
|
+
### `/[key1, key2, ...]`
|
106
|
+
If current element is a hash, get a hash only with the given keys. Since it cannot be determined, if the key is a symbol or a string, both interpretations are checked. If the current object is not a hash, but has methods named `key1, key2`, this methods are called and the results are returned.
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
Hpath.get {a: "b", c: "d", e: "f"}, "/[a,c]"
|
110
|
+
# => {a: "b", c: "d"}
|
111
|
+
```
|
112
|
+
|
113
|
+
### `/*`
|
114
|
+
Get all elements of the current root element. If it's a array, this simply returns the array. If it's a hash, an array of all key/value pairs is returned.
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
Hpath.get [:a,:b,:c], "/*"
|
118
|
+
# => [:a,:b,:c]
|
119
|
+
```
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
Hpath.get {a: "b", c: "d", e: "f"}, "/*"
|
123
|
+
# => [{a: "b"}, {c: "d"}, {e: "f"}]
|
124
|
+
```
|
125
|
+
|
126
|
+
### `/key`
|
127
|
+
If the current element is a hash, return the value of the given key. If the current element is not a hash, but has a method named `key`, this method is called and the result is returned.
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
Hpath.get {a: { b: "c" } }, "/a"
|
131
|
+
# => { b: "c" }
|
132
|
+
```
|
133
|
+
|
134
|
+
If the current element is an array, the non-array behaviour is applied to all members of the array.
|
135
|
+
|
136
|
+
```ruby
|
137
|
+
Hpath.get([{a:"1", b:"2", c:"3"}, {a:"2", b:"5", c:"6"}], "/a")
|
138
|
+
# => ["1", "2"]
|
139
|
+
```
|
22
140
|
|
23
141
|
## Contributing
|
24
142
|
|
data/Rakefile
CHANGED
data/hpath.gemspec
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
lib = File.expand_path(
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
4
|
+
require "hpath/version"
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "hpath"
|
8
8
|
spec.version = Hpath::VERSION
|
9
9
|
spec.authors = ["Michael Sievers"]
|
10
|
-
#spec.email = ["michael_sievers@web.de"]
|
11
10
|
spec.summary = %q{HPath for ruby}
|
12
11
|
spec.homepage = "https://github.com/hpath/hpath-ruby"
|
13
12
|
spec.license = "MIT"
|
@@ -17,6 +16,9 @@ Gem::Specification.new do |spec|
|
|
17
16
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
17
|
spec.require_paths = ["lib"]
|
19
18
|
|
19
|
+
spec.add_dependency "parslet", ">= 1.6.1"
|
20
|
+
|
20
21
|
spec.add_development_dependency "bundler", "~> 1.5"
|
21
22
|
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec", ">= 3.0.0", "< 4.0.0"
|
22
24
|
end
|
data/lib/hpath.rb
CHANGED
@@ -1,5 +1,93 @@
|
|
1
|
-
require "hpath/version"
|
2
|
-
|
3
1
|
module Hpath
|
4
|
-
|
2
|
+
require "hpath/filter"
|
3
|
+
require "hpath/parser"
|
4
|
+
require "hpath/version"
|
5
|
+
|
6
|
+
def self.get(object, hpath_string)
|
7
|
+
hpath = Hpath::Parser.parse(hpath_string)
|
8
|
+
_get(object, hpath[:path])
|
9
|
+
end
|
10
|
+
|
11
|
+
#
|
12
|
+
private
|
13
|
+
#
|
14
|
+
def self._get(object, paths, parent = object)
|
15
|
+
_object = object
|
16
|
+
|
17
|
+
if paths.empty?
|
18
|
+
return object
|
19
|
+
else
|
20
|
+
path = paths.shift
|
21
|
+
end
|
22
|
+
|
23
|
+
if path[:identifier]
|
24
|
+
object = _resolve_identifier(object, path[:identifier])
|
25
|
+
elsif path[:axis] == "parent"
|
26
|
+
object = parent
|
27
|
+
end
|
28
|
+
|
29
|
+
if path[:indices]
|
30
|
+
object = _resolve_indices(object, path[:indices])
|
31
|
+
elsif path[:keys]
|
32
|
+
object = _resolve_keys(object, path[:keys])
|
33
|
+
end
|
34
|
+
|
35
|
+
unless path[:filter].nil?
|
36
|
+
object = _apply_filters(object, Hpath::Filter.new(path[:filter]))
|
37
|
+
end
|
38
|
+
|
39
|
+
self._get(object, paths, _object)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self._apply_filters(object, filter)
|
43
|
+
if object.is_a?(Array)
|
44
|
+
object.select do |element|
|
45
|
+
filter.applies?(element)
|
46
|
+
end
|
47
|
+
else
|
48
|
+
#binding.pry
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def self._resolve_identifier(object, identifier)
|
53
|
+
if object.is_a?(Array)
|
54
|
+
if identifier.to_s == "*"
|
55
|
+
object
|
56
|
+
else
|
57
|
+
object.map do |element|
|
58
|
+
if element.is_a?(Hash)
|
59
|
+
element[identifier.to_s] || element[identifier.to_sym]
|
60
|
+
elsif element.respond_to?(identifier)
|
61
|
+
element.send(identifier)
|
62
|
+
else
|
63
|
+
raise "Cannot apply identifier to collection object!"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
elsif object.is_a?(Hash)
|
68
|
+
if identifier.to_s == "*"
|
69
|
+
object.map { |key, value| {key => value} }
|
70
|
+
else
|
71
|
+
object[identifier.to_s] || object[identifier.to_sym]
|
72
|
+
end
|
73
|
+
else
|
74
|
+
#binding.pry
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def self._resolve_indices(object, indices)
|
79
|
+
if indices.length == 1
|
80
|
+
object[indices.first]
|
81
|
+
else
|
82
|
+
indices.map { |index| object[index] }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def self._resolve_keys(object, keys)
|
87
|
+
if object.is_a?(Hash)
|
88
|
+
object.select { |key, value| keys.include?(key.to_s) || keys.include?(key.to_sym) }
|
89
|
+
else
|
90
|
+
raise "Cannot resolve keys for non-hash objects!"
|
91
|
+
end
|
92
|
+
end
|
5
93
|
end
|
data/lib/hpath/filter.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
class Hpath::Filter
|
2
|
+
|
3
|
+
def initialize(filter_hash)
|
4
|
+
@type = filter_hash.keys.first
|
5
|
+
|
6
|
+
if @type == :and_filter || @type == :or_filter
|
7
|
+
@children = filter_hash.values.first.map do |element|
|
8
|
+
Hpath::Filter.new(element)
|
9
|
+
end
|
10
|
+
elsif @type == :key_value_filter
|
11
|
+
@key = filter_hash[:key_value_filter][:key]
|
12
|
+
@value = filter_hash[:key_value_filter][:value]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def applies?(object)
|
17
|
+
if @type == :and_filter
|
18
|
+
@children.all? { |child_filter| child_filter.applies?(object) }
|
19
|
+
elsif @type == :or_filter
|
20
|
+
@children.any? { |child_filter| child_filter.applies?(object) }
|
21
|
+
elsif @type == :key_value_filter
|
22
|
+
if object.is_a?(Hash) && (@value.is_a?(String) || @value.is_a?(Symbol))
|
23
|
+
object[@key.to_s] == @value.to_s || object[@key.to_sym] == @value.to_s ||
|
24
|
+
object[@key.to_s] == @value.to_sym || object[@key.to_sym] == @value.to_sym
|
25
|
+
else
|
26
|
+
if object.respond_to(@key)
|
27
|
+
object.send(@key) == @value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
data/lib/hpath/parser.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
require "parslet"
|
2
|
+
|
3
|
+
class Hpath::Parser
|
4
|
+
def self.parse(string)
|
5
|
+
self.new.parse(string)
|
6
|
+
end
|
7
|
+
|
8
|
+
def parse(string)
|
9
|
+
transform(normalize(parser.parse(string)))
|
10
|
+
end
|
11
|
+
|
12
|
+
#
|
13
|
+
private
|
14
|
+
#
|
15
|
+
def normalize(result_tree) # to ease transformation
|
16
|
+
result_tree[:path].map! do |element|
|
17
|
+
element[:axis] ||= nil
|
18
|
+
element[:identifier] ||= nil
|
19
|
+
element[:filter] ||= nil
|
20
|
+
element[:indices] ||= nil
|
21
|
+
element[:indices] = [element[:indices]] if !element[:indices].nil? && !element[:indices].is_a?(Array)
|
22
|
+
element[:keys] ||= nil
|
23
|
+
element[:keys] = [element[:keys]] if !element[:keys].nil? && !element[:keys].is_a?(Array)
|
24
|
+
element
|
25
|
+
end
|
26
|
+
|
27
|
+
result_tree
|
28
|
+
end
|
29
|
+
|
30
|
+
def parser
|
31
|
+
@parser ||=
|
32
|
+
Class.new(Parslet::Parser) do
|
33
|
+
rule(:space) { match('\s').repeat(1) }
|
34
|
+
rule(:space?) { space.maybe }
|
35
|
+
|
36
|
+
rule(:key_value_filter) {
|
37
|
+
space? >> match['a-zA-Z'].repeat(1).maybe.as(:key) >> (str("<") | str(">") | str("=").repeat(1,3)).as(:operator) >> match['a-zA-Z0-9'].repeat(1).as(:value) >> space?
|
38
|
+
}
|
39
|
+
|
40
|
+
rule(:or_filter) {
|
41
|
+
((and_filter.as(:and_filter) | key_value_filter.as(:key_value_filter)) >> str("|")).repeat(1) >> (and_filter.as(:and_filter) | key_value_filter.as(:key_value_filter))
|
42
|
+
}
|
43
|
+
|
44
|
+
rule(:primary) {
|
45
|
+
str("(") >> or_filter.as(:or_filter) >> str(")")
|
46
|
+
}
|
47
|
+
|
48
|
+
rule(:and_filter) {
|
49
|
+
((primary | key_value_filter.as(:key_value_filter)) >>
|
50
|
+
str(",")).repeat(1) >>
|
51
|
+
(primary | key_value_filter.as(:key_value_filter))
|
52
|
+
}
|
53
|
+
|
54
|
+
rule(:filter) {
|
55
|
+
space? >> (or_filter.as(:or_filter) | and_filter.as(:and_filter) | key_value_filter.as(:key_value_filter)).as(:filter) >> space?
|
56
|
+
}
|
57
|
+
|
58
|
+
rule(:keys) {
|
59
|
+
match('[a-zA-Z0-9]').repeat(1).as(:key) >> (space? >> str(",") >> space? >> match('[a-zA-Z0-9]').repeat(1).as(:key)).repeat
|
60
|
+
}
|
61
|
+
|
62
|
+
rule(:indices) {
|
63
|
+
match('[0-9]').repeat(1).as(:index) >> (space? >> str(",") >> match('[0-9]').repeat(1).as(:index)).repeat
|
64
|
+
}
|
65
|
+
|
66
|
+
rule(:identifier) {
|
67
|
+
match('[a-zA-Z0-9*_]').repeat(1)
|
68
|
+
}
|
69
|
+
|
70
|
+
rule(:node) {
|
71
|
+
str("/") >> (identifier.as(:identifier) | (str("::") >> identifier.as(:axis))).maybe >> (str("[") >> space? >> (indices.as(:indices) | filter | keys.as(:keys)) >> space? >> str("]")).maybe
|
72
|
+
}
|
73
|
+
|
74
|
+
rule(:path) {
|
75
|
+
node.repeat(1).as(:path)
|
76
|
+
}
|
77
|
+
|
78
|
+
# root
|
79
|
+
root(:path)
|
80
|
+
end.new
|
81
|
+
end
|
82
|
+
|
83
|
+
def transform(result_tree)
|
84
|
+
transformation.apply(result_tree)
|
85
|
+
end
|
86
|
+
|
87
|
+
def transformation
|
88
|
+
@transformation ||=
|
89
|
+
Class.new(Parslet::Transform) do
|
90
|
+
rule(axis: simple(:axis), identifier: simple(:identifier), filter: subtree(:filter), indices: subtree(:indices), keys: subtree(:keys)) {
|
91
|
+
{
|
92
|
+
axis: axis.nil? ? nil : axis.to_s,
|
93
|
+
identifier: identifier.nil? ? nil : identifier.to_s,
|
94
|
+
filter: filter,
|
95
|
+
indices: indices.nil? ? nil : indices.map { |element| Integer(element[:index]) },
|
96
|
+
keys: keys.nil? ? nil : keys.map { |element| element[:key].to_s.to_sym }
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
rule(key: simple(:key), operator: simple(:operator), value: simple(:value)) {
|
101
|
+
{ key: key.nil? ? nil : key.to_sym, operator: operator.to_s, value: value.to_s }
|
102
|
+
}
|
103
|
+
end.new
|
104
|
+
end
|
105
|
+
end
|
data/lib/hpath/version.rb
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
describe Hpath::Filter do
|
2
|
+
context "initialized with a (nested) filter hash" do
|
3
|
+
let(:filter_hash) { Hpath::Parser.new.parse("/array/*[a=b,c=d,(e=d|e=f)]")[:path].first[:filter] }
|
4
|
+
|
5
|
+
describe ".filter" do
|
6
|
+
context "when given object is an array containing hashes" do
|
7
|
+
let(:filter) { Hpath::Filter.new(Hpath::Parser.new.parse("/array/*[a=b,c=d,(e=d|e=f)]")[:path][1][:filter]) }
|
8
|
+
|
9
|
+
it "returns only hashes which match the filter" do
|
10
|
+
#w = [{a: "b", c: "d", e: "f"}, {a: "b", c: "d", e: "z"}].select { |e| filter.applies?(e) }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
describe Hpath::Parser do
|
2
|
+
let(:parser) { Hpath::Parser.new }
|
3
|
+
|
4
|
+
it "parses a hpath string into a tree structure" do
|
5
|
+
=begin
|
6
|
+
expect(parser.parse("/foo/bar/*[a=b,c=d,(e<d|e>f)]/foo[1]/bar[<10]")).to eq(
|
7
|
+
{:path=>
|
8
|
+
[{:identifier=>:foo, :filter=>nil, :index=>nil},
|
9
|
+
{:identifier=>:bar, :filter=>nil, :index=>nil},
|
10
|
+
{:identifier=>:*,
|
11
|
+
:filter=>
|
12
|
+
{:and_filter=>
|
13
|
+
[{:key_value_filter=>{:key=>:a, :operator=>"=", :value=>"b"}},
|
14
|
+
{:key_value_filter=>{:key=>:c, :operator=>"=", :value=>"d"}},
|
15
|
+
{:or_filter=>
|
16
|
+
[{:key_value_filter=>{:key=>:e, :operator=>"<", :value=>"d"}},
|
17
|
+
{:key_value_filter=>{:key=>:e, :operator=>">", :value=>"f"}}]}]},
|
18
|
+
:index=>nil},
|
19
|
+
{:identifier=>:foo, :filter=>nil, :index=>1},
|
20
|
+
{:identifier=>:bar,
|
21
|
+
:filter=>{:key_value_filter=>{:key=>nil, :operator=>"<", :value=>"10"}},
|
22
|
+
:index=>nil}]}
|
23
|
+
)
|
24
|
+
=end
|
25
|
+
end
|
26
|
+
end
|
data/spec/hpath_spec.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
describe Hpath do
|
2
|
+
describe "#get" do
|
3
|
+
describe "returns the corresponding value from the given object" do
|
4
|
+
it "processes \"/key\" for a nested hash" do
|
5
|
+
hpath_result = Hpath.get({ foo: { bar: 1 } }, "/foo")
|
6
|
+
expect(hpath_result).to eq({ bar: 1 })
|
7
|
+
end
|
8
|
+
|
9
|
+
it "processes \"/[n]\" for an array" do
|
10
|
+
hpath_result = Hpath.get([1,2,3], "/[0]")
|
11
|
+
expect(hpath_result).to eq(1)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "processes \"/[m,n]\" for an array" do
|
15
|
+
hpath_result = Hpath.get([1,2,3], "/[0,1]")
|
16
|
+
expect(hpath_result).to eq([1,2])
|
17
|
+
end
|
18
|
+
|
19
|
+
it "processes \"/key1/key2\" for a nested hash" do
|
20
|
+
hpath_result = Hpath.get({ foo: { bar: 1 } }, "/foo/bar")
|
21
|
+
expect(hpath_result).to eq(1)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "processes \"/*\" for an array" do
|
25
|
+
hpath_result = Hpath.get([1,2,3], "/*")
|
26
|
+
expect(hpath_result).to eq([1,2,3])
|
27
|
+
end
|
28
|
+
|
29
|
+
it "processes \"/*\" for a hash" do
|
30
|
+
hpath_result = Hpath.get({a: "b", c: "d"}, "/*")
|
31
|
+
expect(hpath_result).to eq([{a: "b"}, {c: "d"}])
|
32
|
+
end
|
33
|
+
|
34
|
+
it "processes \"/[key1, key2]\" for a hash" do
|
35
|
+
hpath_result = Hpath.get({a: 1, b: 2, "c" => 3}, "/[a,c]")
|
36
|
+
expect(hpath_result).to eq({a: 1, "c" => 3})
|
37
|
+
end
|
38
|
+
|
39
|
+
it "processes \"/[key=value]\" for a array of hashes" do
|
40
|
+
hpath_result = Hpath.get([{a: "foo"}, {a: "bar"}, { "a" => :bar }, {a: "muff"}], "/[a=bar]")
|
41
|
+
expect(hpath_result).to eq([{:a=>"bar"}, {"a"=>:bar}])
|
42
|
+
end
|
43
|
+
|
44
|
+
it "processes \"/[key1=value1,key2=value2]\" for a array of hashes" do
|
45
|
+
hpath_result = Hpath.get([{a:"1", b:"2", c:"3"}, {"a" => "1", "b" => "2", c:"3"}, {a:"2", b:"1", c:"3"}], "/[a=1,b=2]")
|
46
|
+
expect(hpath_result).to eq([{:a=>"1", :b=>"2", :c=>"3"}, {"a"=>"1", "b"=>"2", :c=>"3"}])
|
47
|
+
end
|
48
|
+
|
49
|
+
it "processes \"/[key1=value1,(key2=value2|key3=value3)]\" for a array of hashes" do
|
50
|
+
hpath_result = Hpath.get([{a:"1", b:"2", c:"3"}, {a:"1", b:"5", c:"6"}, {a:"2", b:"1", c:"3"}], "/[a=1,(b=5|c=3)]")
|
51
|
+
expect(hpath_result).to eq([{:a=>"1", :b=>"2", :c=>"3"}, {:a=>"1", :b=>"5", :c=>"6"}])
|
52
|
+
end
|
53
|
+
|
54
|
+
it "processes \"/array/key\" for an array of hashes" do
|
55
|
+
hpath_result = Hpath.get([{a:"1", b:"2", c:"3"}, {a:"1", b:"5", c:"6"}, {a:"2", b:"1", c:"3"}], "/a")
|
56
|
+
expect(hpath_result).to eq(["1", "1", "2"])
|
57
|
+
end
|
58
|
+
|
59
|
+
it "processes \"/key1/::parent\" for a hash" do
|
60
|
+
hpath_result = Hpath.get({ foo: { bar: "foobar" } }, "/foo/::parent")
|
61
|
+
expect(hpath_result).to eq({ foo: { bar: "foobar" } })
|
62
|
+
end
|
63
|
+
|
64
|
+
it "processes \"/[n]/::parent\" for an array of hashes" do
|
65
|
+
hpath_result = Hpath.get([{ foo: { bar: "foobar" } }], "/[0]/::parent")
|
66
|
+
expect(hpath_result).to eq([{ foo: { bar: "foobar" } }])
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hpath
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Sievers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-06-
|
11
|
+
date: 2014-06-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: parslet
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.6.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.6.1
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,6 +52,26 @@ dependencies:
|
|
38
52
|
- - ">="
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 3.0.0
|
62
|
+
- - "<"
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 4.0.0
|
65
|
+
type: :development
|
66
|
+
prerelease: false
|
67
|
+
version_requirements: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: 3.0.0
|
72
|
+
- - "<"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 4.0.0
|
41
75
|
description:
|
42
76
|
email:
|
43
77
|
executables: []
|
@@ -45,13 +79,20 @@ extensions: []
|
|
45
79
|
extra_rdoc_files: []
|
46
80
|
files:
|
47
81
|
- ".gitignore"
|
82
|
+
- ".rspec"
|
48
83
|
- Gemfile
|
49
84
|
- LICENSE.txt
|
50
85
|
- README.md
|
51
86
|
- Rakefile
|
52
87
|
- hpath.gemspec
|
53
88
|
- lib/hpath.rb
|
89
|
+
- lib/hpath/filter.rb
|
90
|
+
- lib/hpath/parser.rb
|
54
91
|
- lib/hpath/version.rb
|
92
|
+
- spec/hpath/filter_spec.rb
|
93
|
+
- spec/hpath/parser_spec.rb
|
94
|
+
- spec/hpath_spec.rb
|
95
|
+
- spec/spec_helper.rb
|
55
96
|
homepage: https://github.com/hpath/hpath-ruby
|
56
97
|
licenses:
|
57
98
|
- MIT
|
@@ -76,4 +117,8 @@ rubygems_version: 2.2.0
|
|
76
117
|
signing_key:
|
77
118
|
specification_version: 4
|
78
119
|
summary: HPath for ruby
|
79
|
-
test_files:
|
120
|
+
test_files:
|
121
|
+
- spec/hpath/filter_spec.rb
|
122
|
+
- spec/hpath/parser_spec.rb
|
123
|
+
- spec/hpath_spec.rb
|
124
|
+
- spec/spec_helper.rb
|