saringan 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/lib/saringan/operator.rb +12 -14
  3. data/lib/saringan/operators/equal.rb +7 -24
  4. data/lib/saringan/operators/greater.rb +24 -0
  5. data/lib/saringan/operators/greater_equal.rb +24 -0
  6. data/lib/saringan/parser.rb +12 -13
  7. data/lib/saringan/parsers/date.rb +28 -0
  8. data/lib/saringan/parsers/date_time.rb +13 -16
  9. data/lib/saringan/parsers/string.rb +14 -0
  10. data/lib/saringan/qualifier.rb +28 -2
  11. data/lib/saringan/qualifiers/absolute.rb +23 -0
  12. data/lib/saringan/qualifiers/between.rb +19 -9
  13. data/lib/saringan/qualifiers/inclusion.rb +20 -9
  14. data/lib/saringan/qualifiers/range.rb +2 -19
  15. data/lib/saringan/statement.rb +17 -0
  16. data/lib/saringan/statements/abstract_statement.rb +18 -0
  17. data/lib/saringan/statements/equal.rb +11 -0
  18. data/lib/saringan/statements/greater_equal.rb +20 -0
  19. data/lib/saringan/term.rb +0 -5
  20. data/lib/saringan/translator.rb +4 -3
  21. data/lib/saringan/version.rb +1 -1
  22. data/spec/operators/equal_spec.rb +8 -42
  23. data/spec/operators/greater_equal_spec.rb +32 -0
  24. data/spec/operators/greater_spec.rb +32 -0
  25. data/spec/parsers/date_spec.rb +45 -0
  26. data/spec/parsers/date_time_spec.rb +2 -11
  27. data/spec/qualifiers/between_spec.rb +19 -3
  28. data/spec/qualifiers/inclusion_spec.rb +19 -4
  29. data/spec/qualifiers/range_spec.rb +4 -15
  30. data/spec/translations/absolute/date/equal_spec.rb +0 -0
  31. data/spec/translations/absolute/date/greater_equal_spec.rb +19 -0
  32. data/spec/translations/absolute/date/greater_spec.rb +0 -0
  33. data/spec/translations/absolute/string/equal_spec.rb +30 -0
  34. data/spec/translations/range/date_time_spec.rb +25 -0
  35. data/spec/translator_spec.rb +42 -17
  36. metadata +28 -7
  37. data/lib/saringan/operators/range.rb +0 -55
  38. data/lib/saringan/parsers/integer_range.rb +0 -10
  39. data/spec/operators/range_spec.rb +0 -83
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 791993cb596de66e181c0b65604c7a8c8966806174e7ce974f4d30b76a0d9afd
4
- data.tar.gz: cdc0e6d8e7fce69c3f43f8aa3e42ee4193ed1305aadecccf4cad57d74922691b
3
+ metadata.gz: d91fddd56fb7a75587ea167883cc517de89c4865c03effe5da0cc59337499ccb
4
+ data.tar.gz: fcbe331554be9d86cc74efcc743c46ab8172fde974804907851544bed702687e
5
5
  SHA512:
6
- metadata.gz: eb697205169202b661ede5b47cc681cf069f59d34e9069a0618035485f8842723e679e577879948085767145e4b13659469530db410370a4e9f5b7c64d7a6626
7
- data.tar.gz: 6cdf0fdaae73799c625104b27f6062e1c4fb287fcaea484592c7fd559baf0aa113e0f245b8cb9ebfd9e78c39bdbefd6e21bf0c9aa23e3b962cc6751f7523d445
6
+ metadata.gz: f798d7b85db4b9cfaafe4a3967a7d69b1ab1f22722e2bfabe88fbea0e55ab498f9c63fd44d20c8f03e36452a5751f6ba06e2c82918ef8ff0697407fbf00d068c
7
+ data.tar.gz: a49cfa55062c6944cbc02e25edf5c5a230c86f1097e1eacbe1c3f7e94d5c5210e444b8ec429ea6cf5f82fe2972369941c62114609810996e0a98b141754d414b
@@ -1,26 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
  # -*- encoding: utf-8 -*-
3
3
 
4
- require "saringan/operators/equal"
5
- require "saringan/operators/range"
4
+ require 'saringan/operators/equal'
5
+ require 'saringan/operators/greater'
6
+ require 'saringan/operators/greater_equal'
6
7
 
7
8
  module Saringan
8
9
  class Operator
9
- class << self
10
- def parse(term)
11
- return equal.to_h(term) if equal.match?(term)
12
- return range.to_h(term) if range.match?(term)
13
- end
14
-
15
- private
16
10
 
17
- def equal
18
- Saringan::Operators::Equal
19
- end
11
+ OPERATORS = [
12
+ Saringan::Operators::Equal,
13
+ Saringan::Operators::GreaterEqual
14
+ ]
20
15
 
21
- def range
22
- Saringan::Operators::Range
16
+ class << self
17
+ def build(term)
18
+ OPERATORS.each do |operator|
19
+ return operator.new(term) if operator.match?(term)
23
20
  end
21
+ end
24
22
  end
25
23
  end
26
24
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
  # -*- encoding: utf-8 -*-
3
3
 
4
- require 'saringan/parser'
5
4
  require 'saringan/matcher'
5
+ require 'saringan/statements/equal'
6
6
 
7
7
  module Saringan
8
8
  module Operators
@@ -11,34 +11,17 @@ module Saringan
11
11
 
12
12
  OP_EQUAL = /::/
13
13
 
14
- class << self
14
+ attr_reader :subject, :value
15
15
 
16
- # TODO: Create an absolute qualifier
17
- def to_h(term)
18
- splitted = split(term)
19
- { "#{splitted[:key]}": parser.parse(splitted[:value]) }
20
- end
21
-
22
- def to_query(term)
23
- splitted = split(term)
24
- { query: "#{splitted[:key]} = ?", params: splitted[:value] }
25
- end
16
+ def initialize(term)
17
+ @subject, @value = term.split(OP_EQUAL, 2)
18
+ end
26
19
 
27
- def split(term)
28
- splitted = term.split(OP_EQUAL)
29
- { key: splitted[0], value: splitted[1] }
30
- end
20
+ private
31
21
 
32
- def matcher
22
+ def self.matcher
33
23
  OP_EQUAL
34
24
  end
35
-
36
- private
37
-
38
- def parser
39
- Saringan::Parser
40
- end
41
- end
42
25
  end
43
26
  end
44
27
  end
@@ -0,0 +1,24 @@
1
+ require 'saringan/matcher'
2
+ require 'saringan/parser'
3
+
4
+ module Saringan
5
+ module Operators
6
+ class Greater
7
+ extend Saringan::Matcher
8
+
9
+ OP_GREATER = /:>/
10
+
11
+ attr_reader :subject, :value
12
+
13
+ def initialize(term)
14
+ @subject, @value = term.split(OP_GREATER)
15
+ end
16
+
17
+ private
18
+
19
+ def self.matcher
20
+ OP_GREATER
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ require 'saringan/matcher'
2
+ # require 'saringan/parser'
3
+
4
+ module Saringan
5
+ module Operators
6
+ class GreaterEqual
7
+ extend Saringan::Matcher
8
+
9
+ OP_GREATER_EQUAL = />:/
10
+
11
+ attr_reader :subject, :value
12
+
13
+ def initialize(term)
14
+ @subject, @value = term.split(OP_GREATER_EQUAL)
15
+ end
16
+
17
+ private
18
+
19
+ def self.matcher
20
+ OP_GREATER_EQUAL
21
+ end
22
+ end
23
+ end
24
+ end
@@ -2,25 +2,24 @@
2
2
  # -*- encoding: utf-8 -*-
3
3
 
4
4
  require 'saringan/parsers/date_time'
5
+ require 'saringan/parsers/date'
6
+ require 'saringan/parsers/string'
5
7
 
6
8
  module Saringan
7
9
  class Parser
8
- class << self
9
- def parse(value)
10
- return date_time.parse(value) if date_time.match?(value)
11
- value
12
- end
13
-
14
- def build(value)
15
- return {value: date_time.clean(value), parser: date_time} if date_time.match?(value)
16
- { value: value, parser: nil }
17
- end
18
10
 
19
- private
11
+ PARSERS = [
12
+ Saringan::Parsers::DateTime,
13
+ Saringan::Parsers::Date
14
+ ]
20
15
 
21
- def date_time
22
- Saringan::Parsers::DateTime
16
+ class << self
17
+ def build(value)
18
+ PARSERS.each do |parser|
19
+ return parser if parser.match?(value)
23
20
  end
21
+ Saringan::Parsers::String
22
+ end
24
23
  end
25
24
  end
26
25
  end
@@ -0,0 +1,28 @@
1
+ require 'saringan/matcher'
2
+
3
+ module Saringan
4
+ module Parsers
5
+ class Date
6
+ extend Saringan::Matcher
7
+
8
+ MATCHER = /^d\((.+)\)$/
9
+ FORMAT = '%Y-%m-%d'
10
+
11
+ class << self
12
+ def clean(value)
13
+ value.gsub(/^d\(|\)$/, '')
14
+ end
15
+
16
+ def parse(value)
17
+ cleaned = clean(value)
18
+ ::Date.strptime(cleaned, FORMAT)
19
+ end
20
+ alias_method :to_proc, :parse
21
+
22
+ def matcher
23
+ MATCHER
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  # -*- encoding: utf-8 -*-
3
-
4
3
  require 'active_support/core_ext/time'
5
4
  require 'active_support/core_ext/date_time'
6
5
  require 'saringan/matcher'
@@ -10,26 +9,24 @@ module Saringan
10
9
  class DateTime
11
10
  extend Saringan::Matcher
12
11
 
13
- MATCHER = /^dt\[(.+)\]$/
14
- FORMAT = '%Y-%m-%d %H:%M:%S'
12
+ MATCHER = /^dt(\(|\[)(.+)(\)|\])$/
13
+ FORMAT = '%Y-%m-%dT%H:%M:%S'
15
14
 
16
- class << self
17
- def clean(value)
18
- value.gsub(/^dt\[|\]$/, '')
19
- end
15
+ def self.parse(value)
16
+ date = ::DateTime.strptime(value, FORMAT)
17
+ ::DateTime.new date.year, date.month, date.day, date.hour, date.min, \
18
+ date.sec, ::DateTime.current.zone
19
+ end
20
20
 
21
- def parse(value)
22
- cleaned = clean(value)
23
- date = ::DateTime.strptime(cleaned, FORMAT)
24
- ::DateTime.new date.year, date.month, date.day, date.hour, date.min, \
25
- date.sec, ::DateTime.current.zone
26
- end
27
- alias_method :to_proc, :parse
21
+ def self.clean(value)
22
+ value.gsub(/^dt/, '')
23
+ end
24
+
25
+ private
28
26
 
29
- def matcher
27
+ def self.matcher
30
28
  MATCHER
31
29
  end
32
- end
33
30
  end
34
31
  end
35
32
  end
@@ -0,0 +1,14 @@
1
+ module Saringan
2
+ module Parsers
3
+ class String
4
+
5
+ def self.parse(value)
6
+ value.to_s
7
+ end
8
+
9
+ def self.clean(value)
10
+ parse value
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,14 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
  # -*- encoding: utf-8 -*-
3
3
 
4
+ require 'saringan/qualifiers/absolute'
5
+ require 'saringan/qualifiers/between'
6
+ require 'saringan/qualifiers/inclusion'
4
7
  require 'saringan/qualifiers/range'
5
8
 
6
9
  module Saringan
7
10
  class Qualifier
8
11
 
12
+ RANGE_QUALIFIERS = [
13
+ Saringan::Qualifiers::Between
14
+ ]
15
+
9
16
  class << self
10
- def qualify(value)
11
- range.parse_value(value) if range.match?(value)
17
+ def build(value)
18
+ parser = Saringan::Parser.build(value)
19
+ value = parser.clean(value)
20
+ qualifier = nil
21
+
22
+ if range.match?(value)
23
+ value = range.clean(value)
24
+ RANGE_QUALIFIERS.each do |q|
25
+ qualifier = q if q.match?(value)
26
+ end
27
+ qualifier ||= Saringan::Qualifiers::Inclusion
28
+ else
29
+ value = absolute.clean(value)
30
+ qualifier = absolute
31
+ end
32
+
33
+ qualifier.new(value, parser)
12
34
  end
13
35
 
14
36
  private
@@ -17,6 +39,10 @@ module Saringan
17
39
  Saringan::Qualifiers::Range
18
40
  end
19
41
 
42
+ def absolute
43
+ Saringan::Qualifiers::Absolute
44
+ end
45
+
20
46
  end
21
47
  end
22
48
  end
@@ -0,0 +1,23 @@
1
+ module Saringan
2
+ module Qualifiers
3
+ class Absolute
4
+
5
+ QL_REPLACER = /^\(|\)$/
6
+ TYPE = :absolute
7
+
8
+ def initialize(value, parser)
9
+ @value = self.class.clean(value)
10
+ @parser = parser
11
+ end
12
+
13
+ def value
14
+ @parser.parse(@value)
15
+ end
16
+
17
+ def self.clean(value)
18
+ value.gsub(QL_REPLACER, '')
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -8,18 +8,28 @@ module Saringan
8
8
  class Between
9
9
  extend Saringan::Matcher
10
10
 
11
- QL_BETWEEN = /\~+/
11
+ MATCHER = /\~+/
12
+ TYPE = :between
12
13
 
13
- class << self
14
- def matcher
15
- QL_BETWEEN
16
- end
14
+ def initialize(value, parser)
15
+ @value = value
16
+ @parser = parser
17
+ qualify
18
+ end
17
19
 
18
- def qualify(value, parser = nil)
19
- splitted = value.split(QL_BETWEEN)[0,2]
20
- splitted.map{|v| parser.nil? ? v : parser.parse(v)}
21
- end
20
+ def qualify
21
+ @from, @to = @value.split(MATCHER, 2)
22
+ end
23
+
24
+ def value
25
+ @parser.parse(@from)..@parser.parse(@to)
22
26
  end
27
+
28
+ private
29
+
30
+ def self.matcher
31
+ MATCHER
32
+ end
23
33
  end
24
34
  end
25
35
  end
@@ -8,18 +8,29 @@ module Saringan
8
8
  class Inclusion
9
9
  extend Saringan::Matcher
10
10
 
11
- QL_INCLUSION = /\;+/
11
+ MATCHER = /\|+/
12
+ TYPE = :inclusion
12
13
 
13
- class << self
14
- def qualify(value, parser = nil)
15
- splitted = value.split(QL_INCLUSION)
16
- parser.nil? ? splitted : splitted.map(&parser)
17
- end
14
+ def initialize(value, parser)
15
+ @value = value
16
+ @parser = parser
17
+ qualify
18
+ end
18
19
 
19
- def matcher
20
- QL_INCLUSION
21
- end
20
+ def qualify
21
+ @values = @value.split(MATCHER).map(&:strip)
22
+ end
23
+
24
+ def value
25
+ @values.map{|val| @parser.parse(val)}
22
26
  end
27
+
28
+ private
29
+
30
+ def self.matcher
31
+ MATCHER
32
+ end
33
+
23
34
  end
24
35
  end
25
36
  end
@@ -1,6 +1,4 @@
1
1
  require 'saringan/matcher'
2
- require 'saringan/qualifiers/inclusion'
3
- require 'saringan/qualifiers/between'
4
2
 
5
3
  module Saringan
6
4
  module Qualifiers
@@ -15,25 +13,10 @@ module Saringan
15
13
  QL_RANGE
16
14
  end
17
15
 
18
- def qualify(value, parser)
19
- cleaned = value.gsub(QL_REPLACER, '')
20
-
21
- if between.match?(value)
22
- { type: :between, value: between.qualify(cleaned, parser) }
23
- else
24
- { type: :in, value: inclusion.qualify(cleaned, parser) }
25
- end
16
+ def clean(value)
17
+ value.gsub(QL_REPLACER, '')
26
18
  end
27
19
 
28
- private
29
-
30
- def inclusion
31
- Saringan::Qualifiers::Inclusion
32
- end
33
-
34
- def between
35
- Saringan::Qualifiers::Between
36
- end
37
20
  end
38
21
  end
39
22
  end
@@ -0,0 +1,17 @@
1
+ require 'saringan/statements/equal'
2
+ require 'saringan/statements/greater_equal'
3
+
4
+ module Saringan
5
+ class Statement
6
+ def self.build(term)
7
+ operator = Saringan::Operator.build(term)
8
+
9
+ case operator
10
+ when Operators::Equal
11
+ Statements::Equal.new(operator)
12
+ when Operators::GreaterEqual
13
+ Statements::GreaterEqual.new(operator)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ require 'saringan/qualifier'
2
+
3
+ module Saringan
4
+ module Statements
5
+ class AbstractStatement
6
+ attr_reader :operator, :qualifier, :field, :value, :type,
7
+ :subject, :params
8
+
9
+ def initialize(operator)
10
+ @operator = operator
11
+ @qualifier = Saringan::Qualifier.build(@operator.value)
12
+ @field = @operator.subject
13
+ @value = @qualifier.value
14
+ @type = @qualifier.class::TYPE
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,11 @@
1
+ require 'saringan/statements/abstract_statement'
2
+
3
+ module Saringan
4
+ module Statements
5
+ class Equal < AbstractStatement
6
+ def to_query
7
+ {"#{@operator.subject}": @qualifier.value}
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,20 @@
1
+ require 'active_support/concern'
2
+ require 'saringan/statements/abstract_statement'
3
+
4
+ module Saringan
5
+ module Statements
6
+ class GreaterEqual < AbstractStatement
7
+ def to_query
8
+ [subject, params]
9
+ end
10
+
11
+ def subject
12
+ "#{@operator.subject} >= ?"
13
+ end
14
+
15
+ def params
16
+ @qualifier.value
17
+ end
18
+ end
19
+ end
20
+ end
@@ -5,11 +5,6 @@ module Saringan
5
5
  class Term
6
6
  TERM_SEP = ','
7
7
 
8
- OP_N_EQUAL_S = /:!:/
9
- OP_N_EQUAL_I = /:<>:/
10
- OP_LESS = /:<:/
11
- OP_BIGGER = /:>:/
12
-
13
8
  class << self
14
9
  def split(query)
15
10
  query.split(TERM_SEP)
@@ -2,15 +2,16 @@
2
2
  # -*- encoding: utf-8 -*-
3
3
 
4
4
  require 'saringan/operator'
5
+ require 'saringan/statement'
5
6
 
6
7
  module Saringan
7
8
  class Translator
8
9
  class << self
9
10
  def translate(query)
10
11
  terms = term.split(query)
11
- parsed = {}
12
- terms.each{|term| parsed.merge!(operator.parse(term))}
13
- parsed
12
+ terms.map do |t|
13
+ Saringan::Statement.build(t).to_query
14
+ end
14
15
  end
15
16
 
16
17
  private
@@ -1,3 +1,3 @@
1
1
  module Saringan
2
- VERSION = "0.4.1"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -4,6 +4,8 @@
4
4
  require 'support/spec_helper'
5
5
 
6
6
  describe Saringan::Operators::Equal do
7
+ let(:operator) { described_class }
8
+
7
9
  describe '#match?' do
8
10
  it 'should match equals operator' do
9
11
  term = 'name::john'
@@ -16,51 +18,15 @@ describe Saringan::Operators::Equal do
16
18
  end
17
19
  end
18
20
 
19
- describe '#split' do
20
- let(:term) { 'name::john' }
21
-
22
- it 'should split term' do
23
- splitted = Saringan::Operators::Equal.split(term)
24
- expect(splitted.size).to eq(2)
25
- end
26
-
27
- context 'splitted key' do
28
- it 'should match term key' do
29
- splitted = Saringan::Operators::Equal.split(term)
30
- expect(splitted[:key]).to eq('name')
31
- end
32
- end
21
+ context 'initialization' do
22
+ let(:instance) { operator.new('name::john') }
33
23
 
34
- context 'splitted value' do
35
- it 'should match term value' do
36
- splitted = Saringan::Operators::Equal.split(term)
37
- expect(splitted[:value]).to eq('john')
38
- end
24
+ it 'extract term subject' do
25
+ expect(instance.subject).to eq('name')
39
26
  end
40
- end
41
-
42
- describe '#to_h' do
43
- it 'should transform term into hash' do
44
- term = 'name::john'
45
- parsed = Saringan::Operators::Equal.to_h(term)
46
-
47
- expect(parsed).to eq({name: 'john'})
48
- end
49
- end
50
-
51
- describe '#to_query' do
52
- it 'should transform term keys into query' do
53
- term = 'name::john'
54
- parsed = Saringan::Operators::Equal.to_query(term)
55
-
56
- expect(parsed[:query]).to eq("name = ?")
57
- end
58
-
59
- it 'should transform term values into params to query' do
60
- term = 'name::john'
61
- parsed = Saringan::Operators::Equal.to_query(term)
62
27
 
63
- expect(parsed[:params]).to eq('john')
28
+ it 'extract term value' do
29
+ expect(instance.value).to eq('john')
64
30
  end
65
31
  end
66
32
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+ # -*- encoding: utf-8 -*-
3
+
4
+ require 'support/spec_helper'
5
+
6
+ describe Saringan::Operators::GreaterEqual do
7
+ let(:operator) { described_class }
8
+
9
+ describe '#match?' do
10
+ it 'should match greater operator' do
11
+ term = 'name>:john'
12
+ expect(operator.match?(term)).to be_truthy
13
+ end
14
+
15
+ it 'should not match other operators' do
16
+ term = 'name!:john'
17
+ expect(operator.match?(term)).to be_falsy
18
+ end
19
+ end
20
+
21
+ context 'initialization' do
22
+ let(:instance) { operator.new('name>:john') }
23
+
24
+ it 'extract term subject' do
25
+ expect(instance.subject).to eq('name')
26
+ end
27
+
28
+ it 'extract term value' do
29
+ expect(instance.value).to eq('john')
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+ # -*- encoding: utf-8 -*-
3
+
4
+ require 'support/spec_helper'
5
+
6
+ describe Saringan::Operators::Greater do
7
+ let(:operator) { described_class }
8
+
9
+ describe '#match?' do
10
+ it 'should match greater operator' do
11
+ term = 'name:>john'
12
+ expect(operator.match?(term)).to be_truthy
13
+ end
14
+
15
+ it 'should not match other operators' do
16
+ term = 'name:!:john'
17
+ expect(operator.match?(term)).to be_falsy
18
+ end
19
+ end
20
+
21
+ context 'initialization' do
22
+ let(:instance) { operator.new('name:>john') }
23
+
24
+ it 'extract term subject' do
25
+ expect(instance.subject).to eq('name')
26
+ end
27
+
28
+ it 'extract term value' do
29
+ expect(instance.value).to eq('john')
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+ # -*- encoding: utf-8 -*-
3
+
4
+ require 'support/spec_helper'
5
+
6
+ describe Saringan::Parsers::Date, type: :parsers do
7
+ let(:parser) { described_class }
8
+ let(:date) { Date.new(2018, 06, 01) }
9
+
10
+ describe '#match?' do
11
+ it 'match date value' do
12
+ value = 'd(2018-06-01)'
13
+ expect(parser.match?(value)).to be_truthy
14
+ end
15
+
16
+ it 'match date time value' do
17
+ value = 'd(2018-06-01T00:00:00.000)'
18
+ expect(parser.match?(value)).to be_truthy
19
+ end
20
+
21
+ it 'do not match non date value' do
22
+ value = 'i(1)'
23
+ expect(parser.match?(value)).to be_falsy
24
+ end
25
+ end
26
+
27
+ describe '#clean' do
28
+ it 'remove range markup from value' do
29
+ value = 'd(2018-06-01)'
30
+ expect(parser.clean(value)).to eq('2018-06-01')
31
+ end
32
+ end
33
+
34
+ describe '#parse' do
35
+ it 'parse value to Date' do
36
+ value = 'd(2018-06-01)'
37
+ expect(parser.parse(value)).to eq(date)
38
+ end
39
+
40
+ it 'parse value to Date even value is a DateTime' do
41
+ value = 'd(2018-06-01T00:00:00.000)'
42
+ expect(parser.parse(value)).to eq(date)
43
+ end
44
+ end
45
+ end
@@ -23,23 +23,14 @@ describe Saringan::Parsers::DateTime, type: :parsers do
23
23
  describe '#clean' do
24
24
  it 'should remove range markup from value' do
25
25
  value = 'dt[2018-06-01 00:00:00|2018-06-30 23:59:59]'
26
- expect(parser.clean(value)).to eq('2018-06-01 00:00:00|2018-06-30 23:59:59')
26
+ expect(parser.clean(value)).to eq('[2018-06-01 00:00:00|2018-06-30 23:59:59]')
27
27
  end
28
28
  end
29
29
 
30
30
  describe '#parse' do
31
31
  it 'should parse value to DateTime' do
32
- value = '2018-06-01 00:00:00'
32
+ value = '2018-06-01T00:00:00'
33
33
  expect(parser.parse(value)).to eq(from)
34
34
  end
35
35
  end
36
-
37
- # describe '#to_h' do
38
- # context 'using between translator' do
39
- # it 'should translate value into from/to hash' do
40
- # value = 'dt[2018-06-01 00:00:00|2018-06-30 23:59:59]'
41
- # expect(parser.to_h(value)[:value]).to eq([from, to])
42
- # end
43
- # end
44
- # end
45
36
  end
@@ -19,9 +19,25 @@ describe Saringan::Qualifiers::Between, type: :qualifier do
19
19
  end
20
20
 
21
21
  describe '#qualify' do
22
- it 'parse value to array' do
23
- value = 'val~val~val'
24
- expect(qualifier.qualify(value)).to have(2).items
22
+ let(:parser) { double('parser') }
23
+
24
+ before do
25
+ allow(parser).to receive(:parser).and_return(1, 10)
26
+ end
27
+
28
+ it 'split values in two parts' do
29
+ value = '1~1~10'
30
+ instance = qualifier.new(value, parser)
31
+
32
+ expect(instance.qualify).to have(2).items
25
33
  end
34
+
35
+ it 'split values correctly' do
36
+ value = '1~10'
37
+ instance = qualifier.new(value, parser)
38
+
39
+ expect(instance.qualify).to eq(['1', '10'])
40
+ end
41
+
26
42
  end
27
43
  end
@@ -8,7 +8,7 @@ describe Saringan::Qualifiers::Inclusion, type: :qualifier do
8
8
 
9
9
  describe '#match?' do
10
10
  it 'matches inclusion value' do
11
- value = 'val; val; val'
11
+ value = 'val| val| val'
12
12
  expect(qualifier.match?(value)).to be_truthy
13
13
  end
14
14
 
@@ -19,9 +19,24 @@ describe Saringan::Qualifiers::Inclusion, type: :qualifier do
19
19
  end
20
20
 
21
21
  describe '#qualify' do
22
- it 'parse value to array' do
23
- value = 'val;val;val'
24
- expect(qualifier.qualify(value)).to have(3).items
22
+ let(:parser) { double('parser') }
23
+
24
+ before do
25
+ allow(parser).to receive(:parse).and_return('val')
26
+ end
27
+
28
+ it 'parsed value match value size' do
29
+ value = 'val|val|val'
30
+ instance = qualifier.new(value, parser)
31
+
32
+ expect(instance.qualify).to have(3).items
33
+ end
34
+
35
+ it 'parsed value must match value' do
36
+ value = 'val|val|val'
37
+ instance = qualifier.new(value, parser)
38
+
39
+ expect(instance.qualify).to eq(['val', 'val', 'val'])
25
40
  end
26
41
  end
27
42
  end
@@ -28,21 +28,10 @@ describe Saringan::Qualifiers::Range, type: :qualifier do
28
28
  end
29
29
  end
30
30
 
31
- describe '#qualify' do
32
- context 'for inclusion values' do
33
- it 'parse inclusion values as array' do
34
- value = 'val; val; val'
35
- parsed = qualifier.qualify(value, nil)
36
- expect(parsed[:value]).to have(3).items
37
- end
38
- end
39
-
40
- context 'for between values' do
41
- it 'parse between values as from/to hash' do
42
- value = 'val~val~val'
43
- parsed = qualifier.qualify(value, nil)
44
- expect(parsed[:value]).to have(2).items
45
- end
31
+ describe '#clean' do
32
+ it 'clean range value markup' do
33
+ value, expected = '[value]', 'value'
34
+ expect(qualifier.clean(value)).to eq(expected)
46
35
  end
47
36
  end
48
37
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+ # -*- encoding: utf-8 -*-
3
+
4
+ require 'support/spec_helper'
5
+
6
+ describe Saringan::Translator do
7
+ let(:translator) { described_class }
8
+ let(:date) { Date.today }
9
+ let(:query) { "date>:d(#{date.iso8601})" }
10
+
11
+ describe '#translate' do
12
+ context 'greater equal date' do
13
+ it 'translates correctly' do
14
+ translated = translator.translate(query)
15
+ expect(translated[0]).to eq(["date >= ?", date])
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ # -*- encoding: utf-8 -*-
3
+
4
+ require 'support/spec_helper'
5
+
6
+ describe Saringan::Translator do
7
+ let(:translator) { described_class }
8
+
9
+ describe '#translate' do
10
+ context 'equal string' do
11
+ it 'translates correctly' do
12
+ translated = translator.translate('name::john')
13
+ expect(translated).to eq([{name: 'john'}])
14
+ end
15
+ end
16
+
17
+ context 'multiple terms' do
18
+ it 'translate terms correctly' do
19
+ translated = translator
20
+ .translate('name::john,last_name::(doe),email::j.doe@email.com')
21
+
22
+ expect(translated).to eq([
23
+ {name: 'john'},
24
+ {last_name: 'doe'},
25
+ {email: 'j.doe@email.com'}
26
+ ])
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+ # -*- encoding: utf-8 -*-
3
+
4
+ require 'support/spec_helper'
5
+
6
+ describe Saringan::Translator do
7
+ let(:translator) { described_class }
8
+ let(:start) { DateTime.now }
9
+ let(:finish) { start + 30 }
10
+ let(:query) { "date::dt[#{start.iso8601}~#{finish.iso8601}]" }
11
+
12
+ describe '#translate' do
13
+ context 'inclusion range' do
14
+ end
15
+
16
+ context 'between range' do
17
+ it 'to rails query correctly' do
18
+ result = translator.translate(query)
19
+ expected = {"date": start..finish}
20
+
21
+ expect(result.first[:date]).not_to be_nil
22
+ end
23
+ end
24
+ end
25
+ end
@@ -7,33 +7,58 @@ describe Saringan::Translator do
7
7
  let(:translator) { Saringan::Translator }
8
8
 
9
9
  describe '#translate' do
10
- context 'for date time ranges' do
11
- let(:query) { 'created_at:>:dt[2018-06-01 00:00:00~2018-06-30 23:59:59]' }
12
10
 
13
- it 'should translate date time query string to ruby hash' do
14
- from = DateTime.new(2018, 06, 01, 00, 00, 00, DateTime.current.zone)
15
- to = DateTime.new(2018, 06, 30, 23, 59, 59, DateTime.current.zone)
11
+ # context 'for absolute equal values' do
12
+ # context 'and value is string' do
13
+ # let(:query) { 'name::john' }
16
14
 
17
- expect(translator.translate(query)).to eq({ created_at: from..to })
15
+ # it 'translate query string to ruby hash' do
16
+ # expect(translator.translate(query)).to eq({ name: 'john' })
17
+ # end
18
+ # end
19
+ # end
20
+
21
+ context 'multiple filters' do
22
+ context 'with two string values' do
23
+ let(:query) { 'name::john,alias::snow' }
24
+
25
+ it 'translate query string to ruby rash' do
26
+ expect(translator.translate(query)).to eq([{ name: 'john' }, { alias: 'snow' }])
27
+ end
18
28
  end
19
- end
20
29
 
21
- context 'for absolute equal values' do
22
- context 'and value is string' do
23
- let(:query) { 'name::john' }
30
+ context 'with date time range and string range' do
31
+ let(:start) { DateTime.now }
32
+ let(:finish) { start + 30 }
33
+
34
+ let(:query) do
35
+ "date::dt[#{start.iso8601}~#{finish.iso8601}],status::[accepted|refused]"
36
+ end
24
37
 
25
38
  it 'translate query string to ruby hash' do
26
- expect(translator.translate(query)).to eq({ name: 'john' })
39
+ result = translator.translate(query)
40
+ expected = { status: ['accepted', 'refused'] }
41
+
42
+ expect(result).to include(expected)
27
43
  end
28
44
  end
29
45
  end
30
46
 
31
- context 'with multiple filters' do
32
- let(:query) { 'name::john,age::18' }
47
+ # context 'greater equal' do
48
+ # context 'for date values' do
49
+ # let(:query) { 'birthdate>:d(2018-06-30)' }
33
50
 
34
- it 'translate query string to ruby rash' do
35
- expect(translator.translate(query)).to eq({ name: 'john', age: '18' })
36
- end
37
- end
51
+ # it 'translate query to ruby query' do
52
+ # translated = translator.translate(query)[:query]
53
+ # expect(translated).to eq("birthdate >= ?")
54
+ # end
55
+
56
+ # it 'translated value should be a Date object' do
57
+ # date = Date.parse('2018-06-30')
58
+ # translated = translator.translate(query)[:params]
59
+ # expect(translated).to eq(date)
60
+ # end
61
+ # end
62
+ # end
38
63
  end
39
64
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: saringan
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Reinaldo Olivera (k1ng)
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-23 00:00:00.000000000 Z
11
+ date: 2019-02-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -92,19 +92,28 @@ files:
92
92
  - lib/saringan/matcher.rb
93
93
  - lib/saringan/operator.rb
94
94
  - lib/saringan/operators/equal.rb
95
- - lib/saringan/operators/range.rb
95
+ - lib/saringan/operators/greater.rb
96
+ - lib/saringan/operators/greater_equal.rb
96
97
  - lib/saringan/parser.rb
98
+ - lib/saringan/parsers/date.rb
97
99
  - lib/saringan/parsers/date_time.rb
98
- - lib/saringan/parsers/integer_range.rb
100
+ - lib/saringan/parsers/string.rb
99
101
  - lib/saringan/qualifier.rb
102
+ - lib/saringan/qualifiers/absolute.rb
100
103
  - lib/saringan/qualifiers/between.rb
101
104
  - lib/saringan/qualifiers/inclusion.rb
102
105
  - lib/saringan/qualifiers/range.rb
106
+ - lib/saringan/statement.rb
107
+ - lib/saringan/statements/abstract_statement.rb
108
+ - lib/saringan/statements/equal.rb
109
+ - lib/saringan/statements/greater_equal.rb
103
110
  - lib/saringan/term.rb
104
111
  - lib/saringan/translator.rb
105
112
  - lib/saringan/version.rb
106
113
  - spec/operators/equal_spec.rb
107
- - spec/operators/range_spec.rb
114
+ - spec/operators/greater_equal_spec.rb
115
+ - spec/operators/greater_spec.rb
116
+ - spec/parsers/date_spec.rb
108
117
  - spec/parsers/date_time_spec.rb
109
118
  - spec/parsers/integer_range_spec.rb
110
119
  - spec/qualifiers/between_spec.rb
@@ -113,6 +122,11 @@ files:
113
122
  - spec/saringan_spec.rb
114
123
  - spec/support/spec_helper.rb
115
124
  - spec/terms_spec.rb
125
+ - spec/translations/absolute/date/equal_spec.rb
126
+ - spec/translations/absolute/date/greater_equal_spec.rb
127
+ - spec/translations/absolute/date/greater_spec.rb
128
+ - spec/translations/absolute/string/equal_spec.rb
129
+ - spec/translations/range/date_time_spec.rb
116
130
  - spec/translator_spec.rb
117
131
  homepage: https://github.com/reinaldooli/saringan
118
132
  licenses:
@@ -134,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
134
148
  version: '0'
135
149
  requirements: []
136
150
  rubyforge_project:
137
- rubygems_version: 2.7.6
151
+ rubygems_version: 2.7.8
138
152
  signing_key:
139
153
  specification_version: 4
140
154
  summary: Simple way to send filter parameters to rails models.
@@ -142,11 +156,18 @@ test_files:
142
156
  - spec/qualifiers/inclusion_spec.rb
143
157
  - spec/qualifiers/between_spec.rb
144
158
  - spec/qualifiers/range_spec.rb
145
- - spec/operators/range_spec.rb
159
+ - spec/operators/greater_equal_spec.rb
160
+ - spec/operators/greater_spec.rb
146
161
  - spec/operators/equal_spec.rb
147
162
  - spec/terms_spec.rb
148
163
  - spec/support/spec_helper.rb
164
+ - spec/translations/range/date_time_spec.rb
165
+ - spec/translations/absolute/date/greater_equal_spec.rb
166
+ - spec/translations/absolute/date/greater_spec.rb
167
+ - spec/translations/absolute/date/equal_spec.rb
168
+ - spec/translations/absolute/string/equal_spec.rb
149
169
  - spec/translator_spec.rb
150
170
  - spec/parsers/integer_range_spec.rb
151
171
  - spec/parsers/date_time_spec.rb
172
+ - spec/parsers/date_spec.rb
152
173
  - spec/saringan_spec.rb
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
- # -*- encoding: utf-8 -*-
3
-
4
- require 'saringan/matcher'
5
- require 'saringan/parser'
6
- require 'saringan/qualifiers/range'
7
-
8
- module Saringan
9
- module Operators
10
- class Range
11
- extend Saringan::Matcher
12
-
13
- OP_RANGE = /:>:/
14
-
15
- class << self
16
- def matcher
17
- OP_RANGE
18
- end
19
-
20
- def to_h(term)
21
- splitted = split(term)
22
- parsed = parser(splitted[:value])
23
- qualified = qualify(parsed[:value], parsed[:parser])
24
-
25
- case qualified[:type]
26
- when :in
27
- { "#{splitted[:key]}": qualified[:value] }
28
- when :between
29
- { "#{splitted[:key]}": qualified[:value][0]..qualified[:value][1] }
30
- end
31
- end
32
-
33
- def split(term)
34
- splitted = term.split(OP_RANGE)
35
- { key: splitted[0], value: splitted[1] }
36
- end
37
-
38
- def qualify(value, parser)
39
- qualifier.qualify(value, parser)
40
- end
41
-
42
- private
43
-
44
- def qualifier
45
- Saringan::Qualifiers::Range
46
- end
47
-
48
- def parser(value)
49
- Saringan::Parser.build(value)
50
- end
51
- end
52
-
53
- end
54
- end
55
- end
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
- # -*- encoding: utf-8 -*-
3
-
4
- module Saringan
5
- module Parsers
6
- class IntegerRange < Range
7
- MATCHER = /^i\[(.+)\]$/
8
- end
9
- end
10
- end
@@ -1,83 +0,0 @@
1
- # frozen_string_literal: true
2
- # -*- encoding: utf-8 -*-
3
-
4
- require 'support/spec_helper'
5
-
6
- describe Saringan::Operators::Range, type: :operator do
7
- let(:operator) { described_class }
8
-
9
- describe '#qualify' do
10
- context 'for inclusion range' do
11
- it 'return values qualified as array' do
12
- value = 'val;val;val'
13
- qualified = operator.qualify(value, nil)
14
- expect(qualified[:value]).to have(3).items
15
- end
16
-
17
- it 'qualify values as inclusion' do
18
- value = 'val;val;val'
19
- qualified = operator.qualify(value, nil)
20
- expect(qualified[:type]).to eq(:in)
21
- end
22
-
23
- it 'qualified values was not changed' do
24
- value = 'val;val;val'
25
- qualified = operator.qualify(value, nil)
26
- expect(qualified[:value]).to eq(['val', 'val', 'val'])
27
- end
28
- end
29
-
30
- context 'for between range' do
31
- it 'return values qualified as array' do
32
- value = 'val~val'
33
- qualified = operator.qualify(value, nil)
34
- expect(qualified[:value]).to have(2).items
35
- end
36
-
37
- it 'qualify values as between' do
38
- value = 'val~val'
39
- qualified = operator.qualify(value, nil)
40
- expect(qualified[:type]).to eq(:between)
41
- end
42
-
43
- it 'between qualified values has only from/to values' do
44
- value = 'val1~val2~val_'
45
- qualified = operator.qualify(value, nil)
46
- expect(qualified[:value]).to eq(['val1', 'val2'])
47
- end
48
- end
49
- end
50
-
51
- describe '#split' do
52
- it 'split term as key => value hash' do
53
- term = 'status:>:[todo;doing;done]'
54
- expect(operator.split(term)).to eq({ key: 'status', value: '[todo;doing;done]'})
55
- end
56
-
57
- context 'splitted key' do
58
- it 'match term key' do
59
- term = 'status:>:[todo;doing;done]'
60
- splitted = operator.split(term)
61
- expect(splitted[:key]).to eq('status')
62
- end
63
- end
64
-
65
- context 'splitted value' do
66
- it 'match term value' do
67
- term = 'status:>:[todo;doing;done]'
68
- splitted = operator.split(term)
69
- expect(splitted[:value]).to eq('[todo;doing;done]')
70
- end
71
- end
72
- end
73
-
74
- describe '#to_h' do
75
- context 'for inclusion range' do
76
- it 'value must be an array' do
77
- term = 'status:>:[todo;doing;done]'
78
- hash = operator.to_h(term)
79
- expect(hash).to eq({ status: ['todo', 'doing', 'done'] })
80
- end
81
- end
82
- end
83
- end