msfl_visitors 0.3.0.dev4 → 0.3.0.dev5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -2
- data/Gemfile.lock +2 -5
- data/README.md +19 -5
- data/lib/msfl_visitors/nodes/named_value.rb +5 -0
- data/lib/msfl_visitors/parsers/msfl_parser.rb +4 -2
- data/lib/msfl_visitors.rb +6 -2
- data/msfl_visitors.gemspec +2 -2
- data/spec/msfl_visitors_spec.rb +60 -0
- data/spec/parsers/msfl_parser_spec.rb +2 -1
- data/spec/visitors/chewy_term_filter_spec.rb +28 -16
- metadata +5 -6
- data/lib/msfl_visitors/ast.rb +0 -20
- data/spec/ast_spec.rb +0 -78
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 179b3ba53392e68b27a017eb798bf8f0035af481
|
4
|
+
data.tar.gz: 2e2360d9f0103674394969e4a73553d572cc5618
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9dd78a8a9b6cad36b44c93d887f1cb765dc3783756c95231c9b4833c725542e6549ba44a2f4c1d5b6fe2c2e85a18cba2fb9a5baa206cbd64096e09f138a11b95
|
7
|
+
data.tar.gz: 947ba05154658c97cebac6b5c9fd686d8a0ac2437ba17e402d493a5eca714e910efa4a269d9ce9907ed18cac100d441b067cd4309544172151f7db24ec04d65e
|
data/Gemfile
CHANGED
@@ -3,5 +3,4 @@ gem 'simplecov', :require => false, :group => :test # MIT https://gith
|
|
3
3
|
gem 'yard' # MIT https://github.com/lsegal/yard/blob/master/LICENSE + Ruby license for one file from the Ruby source lib/parser/ruby/legacy/ruby_lex.rb
|
4
4
|
gem 'rspec' # MIT https://github.com/rspec/rspec/blob/master/License.txt
|
5
5
|
gem 'byebug'
|
6
|
-
gem 'msfl', "1.2
|
7
|
-
gem 'msfl_visitors', "0.3.0.dev4"
|
6
|
+
gem 'msfl', "~> 1.2"
|
data/Gemfile.lock
CHANGED
@@ -7,10 +7,8 @@ GEM
|
|
7
7
|
diff-lcs (1.2.5)
|
8
8
|
docile (1.1.5)
|
9
9
|
json (1.8.2)
|
10
|
-
msfl (1.2.0
|
10
|
+
msfl (1.2.0)
|
11
11
|
json (~> 1.7)
|
12
|
-
msfl_visitors (0.3.0.dev3)
|
13
|
-
msfl (= 1.2.0.dev4)
|
14
12
|
rspec (3.2.0)
|
15
13
|
rspec-core (~> 3.2.0)
|
16
14
|
rspec-expectations (~> 3.2.0)
|
@@ -36,8 +34,7 @@ PLATFORMS
|
|
36
34
|
|
37
35
|
DEPENDENCIES
|
38
36
|
byebug
|
39
|
-
msfl (
|
40
|
-
msfl_visitors (= 0.3.0.dev3)
|
37
|
+
msfl (~> 1.2)
|
41
38
|
rspec
|
42
39
|
simplecov
|
43
40
|
yard
|
data/README.md
CHANGED
@@ -15,15 +15,29 @@ require 'msfl_visitors'
|
|
15
15
|
|
16
16
|
filter = { make: "Toyota" }
|
17
17
|
|
18
|
-
|
18
|
+
dataset = MSFL::Datasets::Car.new
|
19
19
|
|
20
|
-
|
20
|
+
MSFLVisitors.get_chewy_clauses dataset, filter
|
21
21
|
|
22
|
-
|
22
|
+
=> [{:clause=>"make == \"Toyota\""}]
|
23
|
+
|
24
|
+
```
|
23
25
|
|
24
|
-
|
26
|
+
## Facted example
|
25
27
|
|
26
|
-
|
28
|
+
```ruby
|
29
|
+
require 'msfl'
|
30
|
+
# Load one of the test datasets
|
31
|
+
require 'msfl/datasets/car'
|
32
|
+
require 'msfl_visitors'
|
33
|
+
|
34
|
+
filter = { partial: { given: { make: "Toyota" }, filter: { avg_age: 10 } } }
|
35
|
+
|
36
|
+
dataset = MSFL::Datasets::Car.new
|
37
|
+
|
38
|
+
MSFLVisitors.get_chewy_clauses dataset, filter
|
39
|
+
|
40
|
+
=> [{:clause=>{partial: {terms: {make: 'Toyota'}, aggregations: { filter: { range: { avg_age: { gt: 10 }}} }}}}]
|
27
41
|
|
28
42
|
```
|
29
43
|
|
@@ -34,7 +34,7 @@ module MSFLVisitors
|
|
34
34
|
MSFLVisitors::Nodes::Word.new obj.to_s
|
35
35
|
|
36
36
|
else
|
37
|
-
fail ArgumentError, "Invalid NMSFL, unable to parse."
|
37
|
+
fail ArgumentError, "Invalid NMSFL, unable to parse type: #{obj.class}."
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
@@ -80,7 +80,9 @@ module MSFLVisitors
|
|
80
80
|
args = [hash_dispatch(:dataset, value[:dataset]), hash_dispatch(:filter, value[:filter])]
|
81
81
|
|
82
82
|
when :partial
|
83
|
-
args = [hash_dispatch(:given, value[:given]),
|
83
|
+
args = [hash_dispatch(:given, value[:given]),
|
84
|
+
MSFLVisitors::Nodes::NamedValue.new(MSFLVisitors::Nodes::Word.new("partial"),
|
85
|
+
hash_dispatch(:filter, value[:filter]))]
|
84
86
|
|
85
87
|
when :dataset
|
86
88
|
args = [value]
|
data/lib/msfl_visitors.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require_relative 'msfl_visitors/ast'
|
2
1
|
require_relative 'msfl_visitors/nodes'
|
3
2
|
require_relative 'msfl_visitors/visitor'
|
4
3
|
require_relative 'msfl_visitors/parsers/msfl_parser'
|
@@ -6,8 +5,13 @@ require_relative 'msfl_visitors/parsers/msfl_parser'
|
|
6
5
|
module MSFLVisitors
|
7
6
|
|
8
7
|
class << self
|
9
|
-
def get_chewy_clauses(dataset,
|
8
|
+
def get_chewy_clauses(dataset, msfl)
|
9
|
+
unless dataset.is_a? MSFL::Datasets::Base
|
10
|
+
raise ArgumentError, "The first argument to MSFLVisitors.get_chewy_clauses must be a descendant of MSFL::Datasets::Base."
|
11
|
+
end
|
10
12
|
parser = MSFLVisitors::Parsers::MSFLParser.new dataset
|
13
|
+
converter = MSFL::Converters::Operator.new
|
14
|
+
nmsfl = converter.run_conversions msfl
|
11
15
|
ast = parser.parse nmsfl
|
12
16
|
visitor = MSFLVisitors::Visitor.new
|
13
17
|
visitor.visit_tree ast
|
data/msfl_visitors.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'msfl_visitors'
|
3
|
-
s.version = '0.3.0.
|
3
|
+
s.version = '0.3.0.dev5'
|
4
4
|
s.date = '2015-05-15'
|
5
5
|
s.summary = "Convert MSFL to other forms"
|
6
6
|
s.description = "Visitor pattern approach to converting MSFL to other forms."
|
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
11
11
|
s.homepage =
|
12
12
|
'https://github.com/Referly/msfl_visitors'
|
13
|
-
s.add_runtime_dependency "msfl", "1.2.0
|
13
|
+
s.add_runtime_dependency "msfl", "1.2.0"
|
14
14
|
s.add_development_dependency "rake", "~> 10.3"
|
15
15
|
s.add_development_dependency "simplecov", "~> 0.10"
|
16
16
|
s.add_development_dependency "yard", "~> 0.8"
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MSFLVisitors do
|
4
|
+
|
5
|
+
describe ".get_chewy_clauses" do
|
6
|
+
|
7
|
+
subject { described_class.get_chewy_clauses dataset, msfl }
|
8
|
+
|
9
|
+
let(:dataset) { MSFL::Datasets::Car.new }
|
10
|
+
|
11
|
+
let(:msfl) { { make: "Toyota" } }
|
12
|
+
|
13
|
+
it "converts an msfl filter into normal MSFL form" do
|
14
|
+
imitation_converter = double('Imitation Converter')
|
15
|
+
expect(imitation_converter).to receive(:run_conversions).once
|
16
|
+
expect(MSFL::Converters::Operator).to receive(:new).once { imitation_converter }
|
17
|
+
subject
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when the first argument is not a descendant of MSFL::Datasets::Base" do
|
21
|
+
|
22
|
+
let(:dataset) { double('Invalid Dataset') }
|
23
|
+
|
24
|
+
it "raises an ArgumentError" do
|
25
|
+
expect { subject }.to raise_error ArgumentError
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "examples from README" do
|
30
|
+
|
31
|
+
context "when the filter is { make: \"Toyota\" }" do
|
32
|
+
|
33
|
+
it 'returns: [{:clause=>"make == \"Toyota\""}]' do
|
34
|
+
expect(subject).to eq [{:clause=>"make == \"Toyota\""}]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "when the filter is { partial: { given: { make: \"Toyota\" }, filter: { avg_age: 10 } } }" do
|
39
|
+
|
40
|
+
let(:msfl) { { partial: { given: { make: "Toyota" }, filter: { avg_age: 10 } } } }
|
41
|
+
|
42
|
+
it "returns: [{:clause=>{partial: {terms: {make: \"Toyota\"}, aggs: { filter: { range: { avg_age: { gt: 10 }}} }}}}]" do
|
43
|
+
expect(subject).to eq [
|
44
|
+
{
|
45
|
+
clause: {
|
46
|
+
given: {
|
47
|
+
filter: { term: { make: "Toyota"} },
|
48
|
+
aggs: {
|
49
|
+
partial: {
|
50
|
+
filter: {
|
51
|
+
term: { avg_age: 10 }
|
52
|
+
}}}}},
|
53
|
+
method_to_execute: :aggregations
|
54
|
+
}
|
55
|
+
]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -150,7 +150,7 @@ describe MSFLVisitors::Parsers::MSFLParser do
|
|
150
150
|
|
151
151
|
|
152
152
|
|
153
|
-
let(:partial_node) { MSFLVisitors::Nodes::Partial.new given_node,
|
153
|
+
let(:partial_node) { MSFLVisitors::Nodes::Partial.new given_node, named_value }
|
154
154
|
|
155
155
|
let(:given_node) { MSFLVisitors::Nodes::Given.new [given_equal_node] }
|
156
156
|
|
@@ -161,6 +161,7 @@ describe MSFLVisitors::Parsers::MSFLParser do
|
|
161
161
|
let(:given_value_node) { MSFLVisitors::Nodes::Word.new "Toyota" }
|
162
162
|
|
163
163
|
|
164
|
+
let(:named_value) { MSFLVisitors::Nodes::NamedValue.new MSFLVisitors::Nodes::Word.new("partial"), explicit_filter_node }
|
164
165
|
# explicit_filter_node already defined
|
165
166
|
|
166
167
|
# equal_node already defined
|
@@ -71,24 +71,36 @@ describe MSFLVisitors::Visitor do
|
|
71
71
|
|
72
72
|
subject { visitor.visit_tree node }
|
73
73
|
|
74
|
+
let(:expected) do
|
75
|
+
[{
|
76
|
+
clause: {
|
77
|
+
given: {
|
78
|
+
filter: {
|
79
|
+
term: { make: "Toyota" }
|
80
|
+
},
|
81
|
+
aggs: {
|
82
|
+
partial: {
|
83
|
+
filter: { range: { age: { gt: 10 }}}
|
84
|
+
}
|
85
|
+
}
|
86
|
+
}
|
87
|
+
},
|
88
|
+
method_to_execute: :aggregations
|
89
|
+
}]
|
90
|
+
end
|
91
|
+
|
74
92
|
it "results in the appropriate aggregation clause" do
|
75
|
-
exp = [{
|
76
|
-
clause: {
|
77
|
-
given: {
|
78
|
-
filter: {
|
79
|
-
term: { make: "Toyota" }
|
80
|
-
},
|
81
|
-
aggs: {
|
82
|
-
partial: {
|
83
|
-
filter: { range: { age: { gt: 10 }}}
|
84
|
-
}
|
85
|
-
}
|
86
|
-
}
|
87
|
-
},
|
88
|
-
method_to_execute: :aggregations
|
89
|
-
}]
|
90
93
|
visitor.mode = :aggregations
|
91
|
-
expect(subject).to eq
|
94
|
+
expect(subject).to eq expected
|
95
|
+
end
|
96
|
+
|
97
|
+
context "when the Partial node is wrapped in a Filter node" do
|
98
|
+
|
99
|
+
let(:node) { MSFLVisitors::Nodes::Filter.new([MSFLVisitors::Nodes::Partial.new(given_node, named_value)]) }
|
100
|
+
|
101
|
+
it "results in the appropriate aggregation clause" do
|
102
|
+
expect(subject).to eq expected
|
103
|
+
end
|
92
104
|
end
|
93
105
|
end
|
94
106
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: msfl_visitors
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.0.
|
4
|
+
version: 0.3.0.dev5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Courtland Caldwell
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.2.0
|
19
|
+
version: 1.2.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.2.0
|
26
|
+
version: 1.2.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,7 +108,6 @@ files:
|
|
108
108
|
- Rakefile
|
109
109
|
- circle.yml
|
110
110
|
- lib/msfl_visitors.rb
|
111
|
-
- lib/msfl_visitors/ast.rb
|
112
111
|
- lib/msfl_visitors/nodes.rb
|
113
112
|
- lib/msfl_visitors/nodes/and.rb
|
114
113
|
- lib/msfl_visitors/nodes/base.rb
|
@@ -142,7 +141,7 @@ files:
|
|
142
141
|
- lib/msfl_visitors/visitor.rb
|
143
142
|
- msfl_visitors.gemspec
|
144
143
|
- simplecov_custom_profiles.rb
|
145
|
-
- spec/
|
144
|
+
- spec/msfl_visitors_spec.rb
|
146
145
|
- spec/nodes/iterator_spec.rb
|
147
146
|
- spec/parsers/msfl_parser_spec.rb
|
148
147
|
- spec/spec_helper.rb
|
@@ -172,7 +171,7 @@ signing_key:
|
|
172
171
|
specification_version: 4
|
173
172
|
summary: Convert MSFL to other forms
|
174
173
|
test_files:
|
175
|
-
- spec/
|
174
|
+
- spec/msfl_visitors_spec.rb
|
176
175
|
- spec/nodes/iterator_spec.rb
|
177
176
|
- spec/parsers/msfl_parser_spec.rb
|
178
177
|
- spec/spec_helper.rb
|
data/lib/msfl_visitors/ast.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
module MSFLVisitors
|
2
|
-
class AST
|
3
|
-
|
4
|
-
attr_accessor :root
|
5
|
-
|
6
|
-
def initialize(obj, parser = MSFLVisitors::Parsers::MSFLParser.new)
|
7
|
-
self.root = parser.parse obj
|
8
|
-
end
|
9
|
-
|
10
|
-
# Use this method to walk the AST with a particular visitor
|
11
|
-
def accept(visitor)
|
12
|
-
root.accept visitor
|
13
|
-
end
|
14
|
-
|
15
|
-
def ==(other)
|
16
|
-
self.class == other.class &&
|
17
|
-
root == other.root
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
data/spec/ast_spec.rb
DELETED
@@ -1,78 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe MSFLVisitors::AST do
|
4
|
-
|
5
|
-
let(:msfl) { { make: "Honda" } }
|
6
|
-
|
7
|
-
describe "#initialize" do
|
8
|
-
|
9
|
-
let(:parser) do
|
10
|
-
p = double('Fake Parser')
|
11
|
-
expect(p).to receive(:parse).with(msfl).once
|
12
|
-
p
|
13
|
-
end
|
14
|
-
|
15
|
-
subject { described_class.new msfl, parser }
|
16
|
-
|
17
|
-
it "eagerly parses the first argument" do
|
18
|
-
subject
|
19
|
-
end
|
20
|
-
|
21
|
-
context "when a parser is specified" do
|
22
|
-
|
23
|
-
it "uses the specified parser" do
|
24
|
-
subject
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
describe "#accept" do
|
30
|
-
|
31
|
-
let(:parser) { double('Fake Parser', parse: root) }
|
32
|
-
|
33
|
-
let(:root) do
|
34
|
-
r = double('Fake Root Node')
|
35
|
-
expect(r).to receive(:accept).with(visitor).once
|
36
|
-
r
|
37
|
-
end
|
38
|
-
|
39
|
-
let(:visitor) { double('Fake Visitor') }
|
40
|
-
|
41
|
-
subject { described_class.new(msfl, parser).accept visitor }
|
42
|
-
|
43
|
-
it "delegates to the root node" do
|
44
|
-
subject
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
describe "#==" do
|
49
|
-
|
50
|
-
subject { left == right }
|
51
|
-
|
52
|
-
let(:left) { described_class.new(msfl) }
|
53
|
-
|
54
|
-
let(:right) { described_class.new(msfl) }
|
55
|
-
|
56
|
-
context "when the two ASTs are the same class" do
|
57
|
-
|
58
|
-
context "when the two ASTs have equal root nodes" do
|
59
|
-
|
60
|
-
it { is_expected.to be true }
|
61
|
-
end
|
62
|
-
|
63
|
-
context "when the two ASTs do not have equal root nodes" do
|
64
|
-
|
65
|
-
let(:right) { described_class.new({ value: 1000 }) }
|
66
|
-
|
67
|
-
it { is_expected.to be false }
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
context "when the two ASTs are not the same class" do
|
72
|
-
|
73
|
-
let(:right) { double('Fake AST') }
|
74
|
-
|
75
|
-
it { is_expected.to be false }
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|