msfl_visitors 1.2.3 → 1.3.0.dev.f

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e4f7b46f12ec1e288ad1b62e983c0585a6194b5c
4
- data.tar.gz: 01bf0621c30d745039618cd6f8ce71927fe13e1d
3
+ metadata.gz: ec528af7457f8551d7febd5d497337a2b805ac8b
4
+ data.tar.gz: 5e3de6c175ad703eb72b351c30cb3e7a025d9c82
5
5
  SHA512:
6
- metadata.gz: 1be1ea7b20669e7205edf8dd164ba9799cc67995c5dff2b41706b2259a2f62ec8af4b75ad3e612fdeaf8782797ca2c43df1ceb7e207c80787b41cfd4452ccf6e
7
- data.tar.gz: 5a5c14a0c70f0bb6e6273e3450f46216bd183766ba1539d0690fb3a52b2a3ccb1a825c8d3b83984f64f4faac7b769545579533d5b55c30422abe35dde1e522e7
6
+ metadata.gz: a78faedefd14402aba98cbdcd9e4c8ff976c43fc80aa5a9370cf17d6cc1d3ddc0350e47e4d4c3ced60669253fc7840ff0fe54ece4d6a46641f8a55b1449667c8
7
+ data.tar.gz: c05b7c376734ef110bb67a02f16c2e4bc167da846e07a30b00c6197900655b85da0c3adf6b671384f3b55da9e8ca19ff8bda38ff6c53599c021752344be4d89c
@@ -19,11 +19,15 @@ module MSFLVisitors
19
19
  def composable_expr_for(regex_as_literal_string)
20
20
  regex_as_literal_string[3..-4]
21
21
  end
22
+
23
+ def coerce_value_to_unquoted(value)
24
+ return value[1..-2] if value[0] == "\""
25
+ end
22
26
  end
23
27
 
24
28
  class Visitor
25
29
 
26
- attr_accessor :clauses, :current_clause
30
+ attr_accessor :clauses, :current_clause, :arel_table
27
31
  attr_writer :mode
28
32
 
29
33
  def initialize
@@ -35,6 +39,8 @@ module MSFLVisitors
35
39
  def visit(node)
36
40
  if mode == :es_term
37
41
  get_visitor.visit(node)
42
+ elsif mode == :arel
43
+ get_visitor.visit(node)
38
44
  else
39
45
  case node
40
46
  when Nodes::Partial
@@ -54,6 +60,8 @@ module MSFLVisitors
54
60
  TermFilterVisitor.new(self)
55
61
  when :es_term
56
62
  ESTermFilterVisitor.new(self)
63
+ when :arel
64
+ ArelFilterVisitor.new(self, arel_table)
57
65
  else
58
66
  AggregationsVisitor.new(self)
59
67
  end
@@ -66,8 +74,11 @@ module MSFLVisitors
66
74
  result
67
75
  end
68
76
 
69
- def visit_tree(root)
70
- [{clause: root.accept(self)}].concat(clauses).reject { |c| c[:clause] == "" }
77
+ def visit_tree(root, arel_table: nil)
78
+ return [{clause: root.accept(self)}].concat(clauses).reject { |c| c[:clause] == "" } unless mode == :arel
79
+ raise ArgumentError unless arel_table
80
+ @arel_table = arel_table.name
81
+ "#{root.accept(self)}"
71
82
  end
72
83
 
73
84
  private
@@ -245,6 +256,87 @@ module MSFLVisitors
245
256
  attr_reader :visitor
246
257
  end
247
258
 
259
+ class ArelFilterVisitor
260
+ include VisitorHelpers
261
+
262
+ attr_accessor :arel_table
263
+
264
+ def initialize(visitor, arel_table)
265
+ @visitor = visitor
266
+ @arel_table = arel_table
267
+ end
268
+
269
+ BINARY_OPERATORS = {
270
+ Nodes::Containment => 'in',
271
+ Nodes::GreaterThan => 'gt',
272
+ Nodes::GreaterThanEqual => 'gte',
273
+ Nodes::Equal => 'eq',
274
+ Nodes::LessThan => 'lt',
275
+ Nodes::LessThanEqual => 'lte',
276
+ Nodes::Match => '=~',
277
+ }
278
+
279
+
280
+
281
+ def visit(node)
282
+ case node
283
+ when Nodes::Field
284
+ "#{node.value.to_sym}"
285
+ when Nodes::Regex
286
+ regex_escape node.value.to_s
287
+ when Nodes::Word
288
+ "\"#{node.value}\""
289
+ when Nodes::Date, Nodes::Time
290
+ "\"#{node.value.iso8601}\""
291
+ when Nodes::Number, Nodes::Boolean
292
+ node.value
293
+
294
+ when Nodes::QueryString
295
+ %(#{node.left.accept(visitor)} LIKE '%#{coerce_value_to_unquoted node.right.accept(visitor)}%')
296
+
297
+ when Nodes::Match
298
+ if node.right.is_a? Nodes::Set
299
+ escaped_str_frags = node.right.contents.map { |right_child| composable_expr_for(MSFLVisitors::Nodes::Regex.new(right_child.value.to_s).accept(visitor).inspect) }
300
+ escaped_str = "(" + escaped_str_frags.join('|') + ")"
301
+ "#{node.left.accept(visitor)} #{BINARY_OPERATORS[node.class]} " + %r[.*#{escaped_str}.*].inspect
302
+ else
303
+ "#{node.left.accept(visitor)} #{BINARY_OPERATORS[node.class]} " + MSFLVisitors::Nodes::Regex.new(node.right.value.to_s).accept(visitor).inspect
304
+ end
305
+ when Nodes::Containment,
306
+ Nodes::GreaterThan,
307
+ Nodes::GreaterThanEqual,
308
+ Nodes::Equal,
309
+ Nodes::LessThan,
310
+ Nodes::LessThanEqual
311
+ %(#{arel_table}[:#{node.left.accept(visitor)}].#{BINARY_OPERATORS[node.class]}(#{node.right.accept(visitor)}))
312
+ when Nodes::Set
313
+ "[" + node.contents.map { |n| n.accept(visitor) }.join(", ") + "]"
314
+ when Nodes::Filter
315
+ node.contents.reduce("") { |res, n|
316
+ next(n.accept(visitor)) unless res.length > 0
317
+ res + ".and(#{n.accept(visitor)})"
318
+ }
319
+ when Nodes::And
320
+ node.set.contents.reduce("") { |res, n|
321
+ next(n.accept(visitor)) unless res.length > 0
322
+ res + ".and(#{n.accept(visitor)})"
323
+ }
324
+ when Nodes::Foreign
325
+ "#{node.left.accept visitor}.filter { #{node.right.accept visitor} }"
326
+
327
+ when Nodes::Dataset
328
+ "has_child( :#{node.value} )"
329
+
330
+ else
331
+ fail ArgumentError, "ArelFilter cannot visit: #{node.class.name}"
332
+ end
333
+ end
334
+
335
+ private
336
+
337
+ attr_reader :visitor
338
+ end
339
+
248
340
  # ESTermFilterVisitor is not currently used and so not all node types are implemented
249
341
  class ESTermFilterVisitor
250
342
  def initialize(visitor)
data/lib/msfl_visitors.rb CHANGED
@@ -15,5 +15,17 @@ module MSFLVisitors
15
15
  ast = parser.parse nmsfl
16
16
  visitor.visit_tree ast
17
17
  end
18
+
19
+ def get_arel(dataset, msfl, visitor = MSFLVisitors::Visitor.new)
20
+ visitor.mode = :arel
21
+ unless dataset.is_a? MSFL::Datasets::Base
22
+ raise ArgumentError, "The first argument to MSFLVisitors.get_arel must be a descendant of MSFL::Datasets::Base."
23
+ end
24
+ parser = MSFLVisitors::Parsers::MSFLParser.new dataset
25
+ converter = MSFL::Converters::Operator.new
26
+ nmsfl = converter.run_conversions msfl
27
+ ast = parser.parse nmsfl
28
+ visitor.visit_tree ast, arel_table: dataset.arel_table
29
+ end
18
30
  end
19
31
  end
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'msfl_visitors'
3
- s.version = '1.2.3'
4
- s.date = '2015-07-09'
3
+ s.version = '1.3.0.dev.f'
4
+ s.date = '2016-09-30'
5
5
  s.summary = "Convert MSFL to other forms"
6
6
  s.description = "Visitor pattern approach to converting MSFL to other forms."
7
7
  s.authors = ["Courtland Caldwell"]
@@ -0,0 +1,451 @@
1
+ require 'spec_helper'
2
+
3
+ describe MSFLVisitors::Visitor do
4
+
5
+ let(:node) { fail ArgumentError, "You must define the node variable in each scope." }
6
+
7
+ let(:visitor) { described_class.new }
8
+
9
+ let(:left) { MSFLVisitors::Nodes::Field.new "lhs" }
10
+
11
+ let(:right) { MSFLVisitors::Nodes::Word.new "rhs" }
12
+
13
+ subject(:result) { node.accept visitor }
14
+
15
+ context "when using the ArelFilter visitor" do
16
+
17
+ before {
18
+ visitor.mode = :arel
19
+ visitor.arel_table = :cars
20
+ }
21
+
22
+ context "when visiting" do
23
+
24
+ describe "an unsupported node" do
25
+
26
+ class UnsupportedNode
27
+
28
+ def accept(visitor)
29
+ visitor.visit self
30
+ end
31
+ end
32
+
33
+ let(:node) { UnsupportedNode.new }
34
+
35
+ it "raises an ArgumentError" do
36
+ expect { subject }.to raise_error ArgumentError
37
+ end
38
+ end
39
+
40
+ # describe "a Partial node" do
41
+ #
42
+ # let(:node) { MSFLVisitors::Nodes::Partial.new given_node, named_value }
43
+ #
44
+ # let(:given_node) { MSFLVisitors::Nodes::Given.new [given_equal_node] }
45
+ #
46
+ # let(:given_equal_node) { MSFLVisitors::Nodes::Equal.new given_field_node, given_value_node }
47
+ #
48
+ # let(:given_field_node) { MSFLVisitors::Nodes::Field.new :make }
49
+ #
50
+ # let(:given_value_node) { MSFLVisitors::Nodes::Word.new "Toyota" }
51
+ #
52
+ #
53
+ # let(:named_value) { MSFLVisitors::Nodes::NamedValue.new MSFLVisitors::Nodes::Word.new("partial"), explicit_filter_node }
54
+ #
55
+ # let(:explicit_filter_node) { MSFLVisitors::Nodes::ExplicitFilter.new [greater_than_node] }
56
+ #
57
+ # let(:greater_than_node) { MSFLVisitors::Nodes::GreaterThan.new field_node, value_node }
58
+ #
59
+ # let(:field_node) { MSFLVisitors::Nodes::Field.new :age }
60
+ #
61
+ # let(:value_node) { MSFLVisitors::Nodes::Number.new 10 }
62
+ #
63
+ #
64
+ # subject { visitor.visit_tree node }
65
+ #
66
+ # it "results in the appropriate clause" do
67
+ # exp = [{
68
+ # clause: {
69
+ # given: {
70
+ # filter: {
71
+ # term: { make: "Toyota" }
72
+ # },
73
+ # aggs: {
74
+ # partial: {
75
+ # filter: { range: { age: { gt: 10 }}}
76
+ # }
77
+ # }
78
+ # }
79
+ # }
80
+ # }]
81
+ # expect(subject).to eq exp
82
+ # end
83
+ # end
84
+ #
85
+ # describe "a Given node" do
86
+ #
87
+ # let(:node) { MSFLVisitors::Nodes::Given.new [given_equal_node] }
88
+ #
89
+ # let(:given_equal_node) { MSFLVisitors::Nodes::Equal.new given_field_node, given_value_node }
90
+ #
91
+ # let(:given_field_node) { MSFLVisitors::Nodes::Field.new :make }
92
+ #
93
+ # let(:given_value_node) { MSFLVisitors::Nodes::Word.new "Toyota" }
94
+ #
95
+ #
96
+ # it "results in: [:filter, { term: { make: \"Toyota\" } }]" do
97
+ # expect(subject).to eq([:filter, { term: { make: "Toyota" } }])
98
+ # end
99
+ # end
100
+ #
101
+ # describe "a Foreign node" do
102
+ #
103
+ # let(:node) { MSFLVisitors::Nodes::Foreign.new dataset_node, filter_node }
104
+ #
105
+ # let(:dataset_node) { MSFLVisitors::Nodes::Dataset.new "person" }
106
+ #
107
+ # let(:filter_node) { MSFLVisitors::Nodes::ExplicitFilter.new [equal_node] }
108
+ #
109
+ # let(:equal_node) { MSFLVisitors::Nodes::Equal.new left, right }
110
+ #
111
+ # let(:left) { MSFLVisitors::Nodes::Field.new :age }
112
+ #
113
+ # let(:right) { MSFLVisitors::Nodes::Number.new 25 }
114
+ #
115
+ # it "results in: { has_child: { type: \"person\", filter: { term: { age: 25 } } } }" do
116
+ # expect(subject).to eq({ has_child: { type: "person", filter: { term: { age: 25 } } } })
117
+ # end
118
+ # end
119
+
120
+ describe "a Containment node" do
121
+
122
+ let(:node) { MSFLVisitors::Nodes::Containment.new field, values }
123
+
124
+ let(:values) { MSFLVisitors::Nodes::Set.new(MSFL::Types::Set.new([item_one, item_two, item_three])) }
125
+
126
+ let(:item_one) { MSFLVisitors::Nodes::Word.new "item_one" }
127
+
128
+ let(:item_two) { MSFLVisitors::Nodes::Word.new "item_two" }
129
+
130
+ let(:item_three) { MSFLVisitors::Nodes::Word.new "item_three" }
131
+
132
+ let(:field) { left }
133
+
134
+ it %(results in: 'cars[:lhs].in(["item_one", "item_two", "item_three"])') do
135
+ expect(subject).to eq(%(cars[:lhs].in(["item_one", "item_two", "item_three"])))
136
+ end
137
+ end
138
+
139
+ describe "a Set node" do
140
+
141
+ let(:node) { MSFLVisitors::Nodes::Set.new values }
142
+
143
+ let(:values) { MSFL::Types::Set.new([item_one, item_two]) }
144
+
145
+ let(:item_one) { MSFLVisitors::Nodes::Word.new "item_one" }
146
+
147
+ let(:item_two) { MSFLVisitors::Nodes::Word.new "item_two" }
148
+
149
+ it %(results in: '["item_one", "item_two"]') do
150
+ expect(result).to eq %(["item_one", "item_two"])
151
+ end
152
+ end
153
+
154
+ describe "an Equal node" do
155
+
156
+ let(:node) { MSFLVisitors::Nodes::Equal.new left, right }
157
+
158
+ it %(results in: 'cars[:lhs].eq("rhs")') do
159
+ expect(result).to eq(%(cars[:lhs].eq("rhs")))
160
+ end
161
+ end
162
+
163
+ #
164
+ # Models::Investor.arel_table.project(Arel.sql('*')).where(send MSFLVisitors.get_arel(MSFL::Datasets::Investor.new, { linkedin_id: { gt: 200 } })).to_a
165
+ #
166
+ describe "a GreaterThan node" do
167
+
168
+ let(:node) { MSFLVisitors::Nodes::GreaterThan.new left, right }
169
+
170
+ let(:right) { MSFLVisitors::Nodes::Number.new 1000 }
171
+
172
+ it %(results in: 'cars[:lhs].gt(1000)') do
173
+ expect(result).to eq(%(cars[:lhs].gt(1000)))
174
+ end
175
+ end
176
+
177
+ describe "a GreaterThanEqual node" do
178
+
179
+ let(:node) { MSFLVisitors::Nodes::GreaterThanEqual.new left, right }
180
+
181
+ let(:right) { MSFLVisitors::Nodes::Number.new 10.52 }
182
+
183
+ it %(results in: 'cars[:lhs].gte(10.52)') do
184
+ expect(result).to eq(%(cars[:lhs].gte(10.52)))
185
+ end
186
+ end
187
+
188
+ describe "a LessThan node" do
189
+
190
+ let(:node) { MSFLVisitors::Nodes::LessThan.new left, right }
191
+
192
+ let(:right) { MSFLVisitors::Nodes::Number.new 133.7 }
193
+
194
+ it %(returns: 'cars[:lhs].lt(133.7)') do
195
+ expect(result).to eq(%(cars[:lhs].lt(133.7)))
196
+ end
197
+ end
198
+
199
+ describe "a LessThanEqual node" do
200
+
201
+ let(:node) { MSFLVisitors::Nodes::LessThanEqual.new left, right }
202
+
203
+ let(:right) { MSFLVisitors::Nodes::Date.new Date.today }
204
+
205
+ it %(returns: 'cars[:lhs].lte(#{Date.today})') do
206
+ expect(result).to eq(%(cars[:lhs].lte("#{Date.today}")))
207
+ end
208
+ end
209
+
210
+ describe "a QueryString node" do
211
+
212
+ let(:node) { MSFLVisitors::Nodes::QueryString.new left, right }
213
+
214
+ let(:right) { MSFLVisitors::Nodes::Word.new "happy" }
215
+
216
+ it %(returns: "lhs LIKE '%happy%'") do
217
+ expect(result).to eq(%(lhs LIKE '%happy%'))
218
+ end
219
+ end
220
+
221
+ describe "a Filter node" do
222
+
223
+ let(:node) { MSFLVisitors::Nodes::Filter.new filtered_nodes }
224
+
225
+ let(:filtered_nodes) do
226
+ [
227
+ MSFLVisitors::Nodes::GreaterThanEqual.new(
228
+ MSFLVisitors::Nodes::Field.new(:value),
229
+ MSFLVisitors::Nodes::Number.new(1000))
230
+ ]
231
+ end
232
+
233
+ it %(returns: 'cars[:value].gte(1000)') do
234
+ expect(result).to eq(%(cars[:value].gte(1000)))
235
+ end
236
+
237
+ context "when the filter has multiple children" do
238
+
239
+ let(:filtered_nodes) do
240
+ [
241
+ MSFLVisitors::Nodes::Equal.new(
242
+ MSFLVisitors::Nodes::Field.new(:make),
243
+ MSFLVisitors::Nodes::Word.new("Chevy")
244
+ ),
245
+ MSFLVisitors::Nodes::GreaterThanEqual.new(
246
+ MSFLVisitors::Nodes::Field.new(:value),
247
+ MSFLVisitors::Nodes::Number.new(1000))
248
+ ]
249
+ end
250
+
251
+ it %(returns: 'cars[:make].eq("Chevy").and(cars[:value].gte(1000))') do
252
+ expect(result).to eq(%(cars[:make].eq("Chevy").and(cars[:value].gte(1000))))
253
+ end
254
+ end
255
+ end
256
+
257
+ describe "an And node" do
258
+
259
+ let(:first_field) { MSFLVisitors::Nodes::Field.new "first_field" }
260
+
261
+ let(:first_value) { MSFLVisitors::Nodes::Word.new "first_word" }
262
+
263
+ let(:first) { MSFLVisitors::Nodes::Equal.new(first_field, first_value) }
264
+
265
+ let(:second_field) { MSFLVisitors::Nodes::Field.new "second_field" }
266
+
267
+ let(:second_value) { MSFLVisitors::Nodes::Word.new "second_word" }
268
+
269
+ let(:second) { MSFLVisitors::Nodes::Equal.new(second_field, second_value) }
270
+
271
+ let(:third_field) { MSFLVisitors::Nodes::Field.new "third_field" }
272
+
273
+ let(:third_value) { MSFLVisitors::Nodes::Word.new "third_word" }
274
+
275
+ let(:third) { MSFLVisitors::Nodes::Equal.new(third_field, third_value) }
276
+
277
+ let(:node) { MSFLVisitors::Nodes::And.new(set_node) }
278
+
279
+ context "when the And node has zero items" do
280
+
281
+ let(:set_node) { MSFLVisitors::Nodes::Set.new [] }
282
+
283
+ it %(returns: '') do
284
+ expect(result).to eq('')
285
+ end
286
+ end
287
+
288
+ context "when the node has one item" do
289
+
290
+ let(:set_node) { MSFLVisitors::Nodes::Set.new [first] }
291
+
292
+ it %(returns: 'cars[:first_field].eq("first_word")') do
293
+ expect(result).to eq(%(cars[:first_field].eq("first_word")))
294
+ end
295
+ end
296
+
297
+ context "when the node has two items" do
298
+
299
+ let(:set_node) { MSFLVisitors::Nodes::Set.new [first, second] }
300
+
301
+ it %(returns: 'cars[:first_field].eq("first_word").and(cars[:second_field].eq("second_word"))') do
302
+ expect(result).to eq(%(cars[:first_field].eq("first_word").and(cars[:second_field].eq("second_word"))))
303
+ end
304
+ end
305
+
306
+ context "when the node has three items" do
307
+
308
+ let(:set_node) { MSFLVisitors::Nodes::Set.new [first, second, third] }
309
+
310
+ it %(returns: 'cars[:first_field].eq("first_word").and(cars[:second_field].eq("second_word")).and(cars[:third_field].eq("third_word"))') do
311
+ expect(result).to eq(%(cars[:first_field].eq("first_word").and(cars[:second_field].eq("second_word")).and(cars[:third_field].eq("third_word"))))
312
+ end
313
+ end
314
+
315
+ context "when one of the node's items is a containment node" do
316
+
317
+ let(:node) do
318
+ MSFLVisitors::Nodes::And.new(
319
+ MSFLVisitors::Nodes::Set.new(
320
+ [
321
+ MSFLVisitors::Nodes::Filter.new(
322
+ [
323
+ MSFLVisitors::Nodes::Containment.new(
324
+ MSFLVisitors::Nodes::Field.new(:make),
325
+ MSFLVisitors::Nodes::Set.new(
326
+ [
327
+ MSFLVisitors::Nodes::Word.new("Honda"),
328
+ MSFLVisitors::Nodes::Word.new("Chevy"),
329
+ MSFLVisitors::Nodes::Word.new("Volvo")
330
+ ]
331
+ )
332
+ )
333
+ ]
334
+ ),
335
+ MSFLVisitors::Nodes::Filter.new(
336
+ [
337
+ MSFLVisitors::Nodes::GreaterThanEqual.new(
338
+ MSFLVisitors::Nodes::Field.new(:value),
339
+ MSFLVisitors::Nodes::Number.new(1000)
340
+ )
341
+ ]
342
+ )
343
+ ]
344
+ )
345
+ )
346
+ end
347
+ it %(returns: 'cars[:make].in(["Honda", "Chevy", "Volvo"]).and(cars[:value].gte(1000))') do
348
+ expected = %(cars[:make].in(["Honda", "Chevy", "Volvo"]).and(cars[:value].gte(1000)))
349
+ expect(result).to eq expected
350
+ end
351
+ end
352
+ end
353
+
354
+ describe "value nodes" do
355
+ describe "a Boolean node" do
356
+
357
+ let(:node) { MSFLVisitors::Nodes::Boolean.new value }
358
+
359
+ subject(:result) { node.accept visitor }
360
+
361
+ context "with a value of true" do
362
+
363
+ let(:value) { true }
364
+
365
+ it "returns: true" do
366
+ expect(result).to eq true
367
+ end
368
+ end
369
+
370
+ context "with a value of false" do
371
+
372
+ let(:value) { false }
373
+
374
+ it "returns: false" do
375
+ expect(result).to eq false
376
+ end
377
+ end
378
+ end
379
+
380
+ describe "a Word node" do
381
+
382
+ let(:word) { "node_content" }
383
+
384
+ let(:node) { MSFLVisitors::Nodes::Word.new word }
385
+
386
+ it "returns: the literal string" do
387
+ expect(result).to eq "\"#{word}\""
388
+ end
389
+ end
390
+ end
391
+
392
+ describe "range value nodes" do
393
+
394
+ subject(:result) { node.accept visitor }
395
+
396
+ describe "a Date node" do
397
+
398
+ let(:today) { Date.today }
399
+
400
+ let(:node) { MSFLVisitors::Nodes::Date.new today }
401
+
402
+ it "returns: the date using iso8601 formatting" do
403
+ expect(result).to eq "\"#{today.iso8601}\""
404
+ end
405
+ end
406
+
407
+ describe "a Time node" do
408
+
409
+ let(:now) { Time.now }
410
+
411
+ let(:node) { MSFLVisitors::Nodes::Time.new now }
412
+
413
+ it "returns: the date using iso8601 formatting" do
414
+ expect(result).to eq "\"#{now.iso8601}\""
415
+ end
416
+ end
417
+
418
+ describe "a DateTime node" do
419
+
420
+ let(:now) { DateTime.now }
421
+
422
+ let(:node) { MSFLVisitors::Nodes::DateTime.new now }
423
+
424
+ it "returns: the date and time using iso8601 formatting" do
425
+ expect(result).to eq "\"#{now.iso8601}\""
426
+ end
427
+ end
428
+
429
+ describe "a Number node" do
430
+
431
+ let(:number) { 123 }
432
+
433
+ let(:node) { MSFLVisitors::Nodes::Number.new number }
434
+
435
+ it "returns: 123" do
436
+ expect(result).to eq number
437
+ end
438
+
439
+ context "when the number is a float" do
440
+
441
+ let(:number) { 123.456 }
442
+
443
+ it "returns: the number with the same precision" do
444
+ expect(result).to eq number
445
+ end
446
+ end
447
+ end
448
+ end
449
+ end
450
+ end
451
+ end
metadata CHANGED
@@ -1,103 +1,103 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: msfl_visitors
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.3
4
+ version: 1.3.0.dev.f
5
5
  platform: ruby
6
6
  authors:
7
7
  - Courtland Caldwell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-09 00:00:00.000000000 Z
11
+ date: 2016-09-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msfl
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.2'
20
- - - '>='
20
+ - - ">="
21
21
  - !ruby/object:Gem::Version
22
22
  version: 1.2.1
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
- - - ~>
27
+ - - "~>"
28
28
  - !ruby/object:Gem::Version
29
29
  version: '1.2'
30
- - - '>='
30
+ - - ">="
31
31
  - !ruby/object:Gem::Version
32
32
  version: 1.2.1
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: rake
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
- - - ~>
37
+ - - "~>"
38
38
  - !ruby/object:Gem::Version
39
39
  version: '10.3'
40
40
  type: :development
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
- - - ~>
44
+ - - "~>"
45
45
  - !ruby/object:Gem::Version
46
46
  version: '10.3'
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: simplecov
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  requirements:
51
- - - ~>
51
+ - - "~>"
52
52
  - !ruby/object:Gem::Version
53
53
  version: '0.10'
54
54
  type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
- - - ~>
58
+ - - "~>"
59
59
  - !ruby/object:Gem::Version
60
60
  version: '0.10'
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: yard
63
63
  requirement: !ruby/object:Gem::Requirement
64
64
  requirements:
65
- - - ~>
65
+ - - "~>"
66
66
  - !ruby/object:Gem::Version
67
67
  version: '0.8'
68
68
  type: :development
69
69
  prerelease: false
70
70
  version_requirements: !ruby/object:Gem::Requirement
71
71
  requirements:
72
- - - ~>
72
+ - - "~>"
73
73
  - !ruby/object:Gem::Version
74
74
  version: '0.8'
75
75
  - !ruby/object:Gem::Dependency
76
76
  name: rspec
77
77
  requirement: !ruby/object:Gem::Requirement
78
78
  requirements:
79
- - - ~>
79
+ - - "~>"
80
80
  - !ruby/object:Gem::Version
81
81
  version: '3.2'
82
82
  type: :development
83
83
  prerelease: false
84
84
  version_requirements: !ruby/object:Gem::Requirement
85
85
  requirements:
86
- - - ~>
86
+ - - "~>"
87
87
  - !ruby/object:Gem::Version
88
88
  version: '3.2'
89
89
  - !ruby/object:Gem::Dependency
90
90
  name: byebug
91
91
  requirement: !ruby/object:Gem::Requirement
92
92
  requirements:
93
- - - ~>
93
+ - - "~>"
94
94
  - !ruby/object:Gem::Version
95
95
  version: '4.0'
96
96
  type: :development
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
- - - ~>
100
+ - - "~>"
101
101
  - !ruby/object:Gem::Version
102
102
  version: '4.0'
103
103
  description: Visitor pattern approach to converting MSFL to other forms.
@@ -106,7 +106,7 @@ executables: []
106
106
  extensions: []
107
107
  extra_rdoc_files: []
108
108
  files:
109
- - .gitignore
109
+ - ".gitignore"
110
110
  - Gemfile
111
111
  - Gemfile.lock
112
112
  - LICENSE
@@ -154,6 +154,7 @@ files:
154
154
  - spec/msfl_visitors/nodes/iterator_spec.rb
155
155
  - spec/msfl_visitors/parsers/msfl_parser_spec.rb
156
156
  - spec/msfl_visitors/visitor_spec.rb
157
+ - spec/msfl_visitors/visitors/arel_filter_spec.rb
157
158
  - spec/msfl_visitors/visitors/chewy_term_filter_spec.rb
158
159
  - spec/msfl_visitors/visitors/es_term_filter_spec.rb
159
160
  - spec/msfl_visitors_spec.rb
@@ -168,17 +169,17 @@ require_paths:
168
169
  - lib
169
170
  required_ruby_version: !ruby/object:Gem::Requirement
170
171
  requirements:
171
- - - '>='
172
+ - - ">="
172
173
  - !ruby/object:Gem::Version
173
174
  version: '0'
174
175
  required_rubygems_version: !ruby/object:Gem::Requirement
175
176
  requirements:
176
- - - '>='
177
+ - - ">"
177
178
  - !ruby/object:Gem::Version
178
- version: '0'
179
+ version: 1.3.1
179
180
  requirements: []
180
181
  rubyforge_project:
181
- rubygems_version: 2.4.2
182
+ rubygems_version: 2.4.3
182
183
  signing_key:
183
184
  specification_version: 4
184
185
  summary: Convert MSFL to other forms
@@ -187,6 +188,7 @@ test_files:
187
188
  - spec/msfl_visitors/nodes/iterator_spec.rb
188
189
  - spec/msfl_visitors/parsers/msfl_parser_spec.rb
189
190
  - spec/msfl_visitors/visitor_spec.rb
191
+ - spec/msfl_visitors/visitors/arel_filter_spec.rb
190
192
  - spec/msfl_visitors/visitors/chewy_term_filter_spec.rb
191
193
  - spec/msfl_visitors/visitors/es_term_filter_spec.rb
192
194
  - spec/msfl_visitors_spec.rb