CloudSesame 0.7.5 → 0.7.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +14 -12
  3. data/Guardfile +2 -2
  4. data/cloud_sesame.gemspec +2 -2
  5. data/coverage/.last_run.json +1 -1
  6. data/coverage/.resultset.json +1363 -248
  7. data/lib/cloud_sesame/domain/base.rb +1 -1
  8. data/lib/cloud_sesame/query/ast/abstract/multi_expression_operator.rb +3 -4
  9. data/lib/cloud_sesame/query/ast/abstract/value.rb +10 -2
  10. data/lib/cloud_sesame/query/ast/date_value.rb +1 -4
  11. data/lib/cloud_sesame/query/ast/literal.rb +20 -12
  12. data/lib/cloud_sesame/query/ast/{field_array.rb → multi_expression_operator_children.rb} +8 -2
  13. data/lib/cloud_sesame/query/ast/not.rb +1 -7
  14. data/lib/cloud_sesame/query/ast/range_value.rb +43 -28
  15. data/lib/cloud_sesame/query/ast/root.rb +2 -4
  16. data/lib/cloud_sesame/query/ast/value.rb +1 -9
  17. data/lib/cloud_sesame/query/builder.rb +9 -11
  18. data/lib/cloud_sesame/query/domain/block.rb +1 -3
  19. data/lib/cloud_sesame/query/domain/chaining_block.rb +3 -4
  20. data/lib/cloud_sesame/query/domain/literal.rb +1 -3
  21. data/lib/cloud_sesame/query/dsl/bind_caller.rb +13 -6
  22. data/lib/cloud_sesame/query/dsl/{field_array_methods.rb → literal_chaining_methods.rb} +1 -6
  23. data/lib/cloud_sesame/query/dsl/{field_accessors.rb → literal_methods.rb} +1 -1
  24. data/lib/cloud_sesame/query/node/fuzziness.rb +1 -1
  25. data/lib/cloud_sesame.rb +4 -3
  26. data/spec/cloud_sesame/query/ast/abstract/multi_expression_operator_spec.rb +5 -1
  27. data/spec/cloud_sesame/query/ast/field_array_spec.rb +57 -0
  28. data/spec/cloud_sesame/query/ast/literal_spec.rb +136 -0
  29. data/spec/cloud_sesame/query/ast/not_spec.rb +30 -0
  30. data/spec/cloud_sesame/query/ast/phrase_spec.rb +20 -0
  31. data/spec/cloud_sesame/query/ast/range_value_spec.rb +245 -30
  32. data/spec/cloud_sesame/query/ast/string_value_spec.rb +39 -0
  33. data/spec/cloud_sesame/query/ast/term_spec.rb +20 -0
  34. data/spec/cloud_sesame/query/ast/value_spec.rb +109 -0
  35. data/spec/cloud_sesame/query/builder_spec.rb +4 -4
  36. data/spec/cloud_sesame/query/domain/block_spec.rb +3 -3
  37. data/spec/cloud_sesame/query/dsl/{field_array_methods_spec.rb → literal_chaining_methods_spec.rb} +1 -1
  38. data/spec/cloud_sesame/query/dsl/{field_accessors_spec.rb → literal_methods_spec.rb} +3 -3
  39. data/spec/cloud_sesame/query/node/query_spec.rb +22 -0
  40. data/spec/profiling_spec.rb +155 -155
  41. metadata +23 -9
@@ -88,7 +88,7 @@ module CloudSesame
88
88
  end
89
89
 
90
90
  def create_accessor(name)
91
- @builder.field_accessor.__define_accessor__(name)
91
+ @builder.literal_methods.__define_accessor__(name)
92
92
  end
93
93
 
94
94
  def create_default_literal(name, options)
@@ -9,14 +9,14 @@ module CloudSesame
9
9
  end
10
10
 
11
11
  def applied(included = true)
12
- children.map { |child| child.applied(included) }
12
+ children.map { |child| child.applied included }
13
13
  end
14
14
 
15
15
  def children
16
16
  @children ||= build_children
17
17
  end
18
18
 
19
- def compile
19
+ def compile(_ = nil)
20
20
  if !children.empty? && (compiled = children.compile) && !compiled.empty?
21
21
  "(#{ symbol }#{ boost } #{ compiled })"
22
22
  end
@@ -25,8 +25,7 @@ module CloudSesame
25
25
  private
26
26
 
27
27
  def build_children
28
- (children = FieldArray.new)._scope = self
29
- children
28
+ MultiExpressionOperatorChildren.build(self)
30
29
  end
31
30
 
32
31
  end
@@ -6,6 +6,8 @@ module CloudSesame
6
6
  module Abstract
7
7
  class Value
8
8
 
9
+ # CONSTANTS
10
+ # =====================================
9
11
  RANGE_FORMAT = Regexp.new(/\A(\[|{)(.*),(.*)(\}|\])\z/).freeze
10
12
  DIGIT_FORMAT = Regexp.new(/\A\d+(.\d+)?\z/).freeze
11
13
  DATETIME_FORMAT = Regexp.new(/\d+{4}-\d+{2}-\d+{2}T\d+{2}:\d+{2}:\d+{2}/).freeze
@@ -13,12 +15,15 @@ module CloudSesame
13
15
 
14
16
  attr_reader :value, :changed, :compiled
15
17
 
18
+ # CLASS METHODS
19
+ # =====================================
20
+
16
21
  def self.range?(value)
17
22
  value.kind_of?(Range)
18
23
  end
19
24
 
20
25
  def self.string_range?(value)
21
- RANGE_FORMAT =~ strip(value)
26
+ value.is_a?(String) && !!(RANGE_FORMAT =~ strip(value))
22
27
  end
23
28
 
24
29
  def self.numeric?(value)
@@ -26,7 +31,7 @@ module CloudSesame
26
31
  end
27
32
 
28
33
  def self.string_numeric?(value)
29
- DIGIT_FORMAT =~ value.to_s
34
+ value.is_a?(String) && !!(DIGIT_FORMAT =~ value)
30
35
  end
31
36
 
32
37
  def self.datetime?(value)
@@ -41,6 +46,9 @@ module CloudSesame
41
46
  value.is_a?(String) && DATE_FORMAT =~ value
42
47
  end
43
48
 
49
+ # INSTANCE METHODS
50
+ # =====================================
51
+
44
52
  def initialize(value, type = nil)
45
53
  self.value = value
46
54
  @type = type
@@ -8,10 +8,7 @@ module CloudSesame
8
8
  DATE_FORMAT = '%F'.freeze
9
9
 
10
10
  def self.parse(value)
11
- if value.kind_of?(RangeValue)
12
- value.type = self
13
- return value
14
- end
11
+ return value.parse self if value.kind_of?(RangeValue)
15
12
 
16
13
  range?(value) || string_range?(value) ? RangeValue.new(value, self) :
17
14
  string_datetime?(value) ? new(parse_datetime(value)) :
@@ -6,45 +6,53 @@ module CloudSesame
6
6
  SINGLE_QUATE = Regexp.new(/\'/).freeze
7
7
  ESCAPE_QUATE = "\\'".freeze
8
8
 
9
- attr_reader :value
9
+ attr_reader :field, :value, :options
10
10
 
11
11
  def initialize(field, value, options = {})
12
12
  @field = field
13
- @options = options
14
- @value = LazyObject.new { (options[:type] || Value).parse(value) } if value
13
+ @options = options || default_options
14
+ @value = parse_value(value) if value
15
15
  end
16
16
 
17
- def is_for(field, options = {})
18
- @field = field
19
- @options.merge! options
17
+ def actual_field_name
18
+ @options[:as] || @field
20
19
  end
21
20
 
22
21
  def applied(included)
23
22
  { field: @field, value: @value, included: included } if @value
24
23
  end
25
24
 
26
- def as_field
27
- @options[:as] || @field
28
- end
29
-
30
25
  def compile(detailed = false)
31
26
  (detailed ? detailed_format : standard_format) if @value
32
27
  end
33
28
 
29
+ def is_for(field, options)
30
+ @field = field
31
+ @options.merge! options if options
32
+ end
33
+
34
34
  private
35
35
 
36
36
  def standard_format
37
- "#{ as_field }:#{ @value.compile }"
37
+ "#{ actual_field_name }:#{ @value.compile }"
38
38
  end
39
39
 
40
40
  def detailed_format
41
- "field=#{ escape as_field.to_s } #{ @value.compile }"
41
+ "field=#{ escape actual_field_name.to_s } #{ @value.compile }"
42
42
  end
43
43
 
44
44
  def escape(data)
45
45
  "'#{ data.gsub(SINGLE_QUATE) { ESCAPE_QUATE } }'"
46
46
  end
47
47
 
48
+ def parse_value(value)
49
+ LazyObject.new { (@options[:type] || Value).parse(value) }
50
+ end
51
+
52
+ def default_options
53
+ { type: Value }
54
+ end
55
+
48
56
  end
49
57
  end
50
58
  end
@@ -1,12 +1,18 @@
1
1
  module CloudSesame
2
2
  module Query
3
3
  module AST
4
- class FieldArray < Array
5
- include DSL::FieldArrayMethods
4
+ class MultiExpressionOperatorChildren < Array
5
+ include DSL::LiteralChainingMethods
6
6
 
7
7
  attr_accessor :_scope, :_return
8
8
  attr_reader :field
9
9
 
10
+ def self.build(scope, children = nil)
11
+ array = new(children || [])
12
+ array._scope = scope
13
+ array
14
+ end
15
+
10
16
  def field=(field)
11
17
  parents.clear
12
18
  @field = field
@@ -4,14 +4,8 @@ module CloudSesame
4
4
  class Not < Abstract::SingleExpressionOperator
5
5
  SYMBOL = :not
6
6
 
7
- def compile
8
- if child && (compiled = child.compile) && !compiled.empty?
9
- "(#{ symbol }#{ boost } #{ compiled })"
10
- end
11
- end
12
-
13
7
  def applied(included = true)
14
- child.applied(!included)
8
+ child.applied !included
15
9
  end
16
10
 
17
11
  end
@@ -4,35 +4,54 @@ module CloudSesame
4
4
  class RangeValue < Abstract::Value
5
5
 
6
6
  def initialize(value = nil, type = nil)
7
- self.value = RangeValue.range?(value) ? range_handler(value) :
8
- RangeValue.string_range?(value) ? string_handler(value) :
9
- empty_value
7
+ self.value = RangeValue.range?(value) ? build_from_range(value) :
8
+ RangeValue.string_range?(value) ? build_from_string(value) :
9
+ initialize_value
10
+ self.parse type
11
+ end
12
+
13
+ def parse(type)
14
+ if type && type.respond_to?(:parse)
15
+ @changed = true
16
+ value[1] = type.parse(self.begin) unless self.begin.to_s.empty?
17
+ value[2] = type.parse(self.end) unless self.end.to_s.empty?
18
+ end
19
+ return self
20
+ end
21
+
22
+ def begin
23
+ value[1]
24
+ end
25
+
26
+ def end
27
+ value[2]
28
+ end
10
29
 
11
- self.type = type if type
30
+ def lower_bound
31
+ value[0]
12
32
  end
13
33
 
14
- def type=(type)
15
- value_type_handler(type) if (@type = type)
16
- type
34
+ def upper_bound
35
+ value[3]
17
36
  end
18
37
 
19
38
  def gt(value)
20
- update_lower_value(value) if value
39
+ set_begin(value) if value
21
40
  return self
22
41
  end
23
42
 
24
43
  def gte(value)
25
- update_lower_value(value, '[') if value
44
+ set_begin(value, '[') if value
26
45
  return self
27
46
  end
28
47
 
29
48
  def lt(value)
30
- update_uppoer_value(value) if value
49
+ set_end(value) if value
31
50
  return self
32
51
  end
33
52
 
34
53
  def lte(value)
35
- update_uppoer_value(value, ']') if value
54
+ set_end(value, ']') if value
36
55
  return self
37
56
  end
38
57
 
@@ -41,7 +60,7 @@ module CloudSesame
41
60
  end
42
61
 
43
62
  def ==(object)
44
- value == RangeValue.new(object, Value).value
63
+ value == (object.is_a?(RangeValue) ? object : RangeValue.new(object, Value)).value
45
64
  end
46
65
 
47
66
  private
@@ -50,30 +69,26 @@ module CloudSesame
50
69
  super "#{ value[0] }#{ value[1] },#{ value[2] }#{ value[3] }"
51
70
  end
52
71
 
53
- def update_lower_value(value, included = '{')
54
- self.value[0] = included
55
- self.value[1] = value
56
- end
57
-
58
- def update_uppoer_value(value, included = '}')
59
- self.value[2] = value
60
- self.value[3] = included
72
+ def set_begin(value, included = '{')
73
+ @changed = true
74
+ self.value[0, 2] = [included, value]
61
75
  end
62
76
 
63
- def range_handler(value)
64
- ['[', value.begin, value.end, value.exclude_end? ? '}' : ']']
77
+ def set_end(value, included = '}')
78
+ @changed = true
79
+ self.value[2, 2] = [value, included]
65
80
  end
66
81
 
67
- def string_handler(value)
68
- RANGE_FORMAT.match(strip(value)).captures
82
+ def build_from_range(range)
83
+ initialize_value('[', range.begin, range.end, range.exclude_end? ? '}' : ']')
69
84
  end
70
85
 
71
- def value_type_handler(type)
72
- self.value[1, 2] = value[1, 2].map { |v| type.parse(v) unless v.to_s.empty? }
86
+ def build_from_string(string)
87
+ initialize_value(*RANGE_FORMAT.match(strip(string)).captures)
73
88
  end
74
89
 
75
- def empty_value
76
- ['{', nil, nil, '}']
90
+ def initialize_value(lb = '[', bv = nil, ev = nil, up = ']')
91
+ [lb, bv, ev, up]
77
92
  end
78
93
 
79
94
  end
@@ -10,10 +10,8 @@ module CloudSesame
10
10
 
11
11
  private
12
12
 
13
- def create_children
14
- array = FieldArray.new(context[:defaults] || [])
15
- array._scope = self
16
- array
13
+ def build_children
14
+ MultiExpressionOperatorChildren.build(self, context[:defaults])
17
15
  end
18
16
 
19
17
  end
@@ -13,21 +13,13 @@ module CloudSesame
13
13
  (klass =TYPES[symbol]) ? klass : self
14
14
  end
15
15
 
16
- # if the value is already a range value object
17
- # set the type to Value and return the value
18
- # else determine the type of value and create it
19
16
  def self.parse(value)
20
- if value.kind_of?(RangeValue)
21
- value.type = self
22
- return value
23
- end
24
-
17
+ return value.parse self if value.kind_of?(RangeValue)
25
18
  (
26
19
  range_value?(value) ? RangeValue :
27
20
  numeric_value?(value) ? NumericValue :
28
21
  datetime?(value) ? DateValue : StringValue
29
22
  ).new(value, self)
30
-
31
23
  end
32
24
 
33
25
  def self.range_value?(value)
@@ -15,16 +15,16 @@ module CloudSesame
15
15
  # ClassSpecific construct class callback
16
16
  #
17
17
  # after construct searchable specific builder,
18
- # construct searchable specific DSL::FieldAccessors,
18
+ # construct searchable specific DSL::LiteralMethods,
19
19
  # and Domain::Block and include the new field accessors
20
20
  # in both builder and domain block
21
21
  # ===================================================
22
22
  after_construct do |searchable|
23
- @field_accessor = DSL::FieldAccessors.construct_module(searchable)
24
- @block_domain = Domain::Block.construct_class(searchable, callback_args: [field_accessor])
23
+ @literal_methods = DSL::LiteralMethods.construct_module(searchable)
24
+ @block_domain = Domain::Block.construct_class(searchable, callback_args: [literal_methods])
25
25
  @request = Node::Request.construct_class(searchable)
26
26
 
27
- include field_accessor
27
+ include literal_methods
28
28
  end
29
29
 
30
30
  # Domain::Block getter
@@ -37,9 +37,9 @@ module CloudSesame
37
37
  @request ||= Node::Request
38
38
  end
39
39
 
40
- # DSL::FieldAccessors getter
41
- def self.field_accessor
42
- @field_accessor ||= DSL::FieldAccessors
40
+ # DSL::LiteralMethods getter
41
+ def self.literal_methods
42
+ @literal_methods ||= DSL::LiteralMethods
43
43
  end
44
44
 
45
45
  # ===================================================
@@ -62,10 +62,8 @@ module CloudSesame
62
62
  private
63
63
 
64
64
  def _block_domain(block)
65
- if block
66
- caller = block.binding.eval("self")
67
- self.class.block_domain.new caller, _context
68
- end
65
+ caller = block ? block.binding.eval("self") : nil
66
+ self.class.block_domain.new caller, _context
69
67
  end
70
68
 
71
69
  def _scope
@@ -15,11 +15,9 @@ module CloudSesame
15
15
  attr_reader :_caller, :_context, :_scopes
16
16
 
17
17
  def initialize(_caller, _context)
18
- @_caller = _caller
18
+ self._caller = _caller
19
19
  @_context = _context
20
20
  @_scopes = []
21
-
22
- _bind_caller_instance_variables
23
21
  end
24
22
 
25
23
  def _eval(node, _scope, _return = _scope, &block)
@@ -28,10 +28,9 @@ module CloudSesame
28
28
  private
29
29
 
30
30
  def _block_domain(block)
31
- @_block_domain ||= (
32
- caller = block.binding.eval("self")
33
- Domain::Block.new caller, _scope.context
34
- )
31
+ caller = block.binding.eval("self")
32
+ @_block_domain._caller = caller
33
+ @_block_domain
35
34
  end
36
35
 
37
36
  def missing_block
@@ -10,9 +10,7 @@ module CloudSesame
10
10
  def initialize(_name, _options, _caller)
11
11
  @_name = _name
12
12
  @_options = _options
13
- @_caller = _caller
14
-
15
- _bind_caller_instance_variables
13
+ self._caller = _caller
16
14
  end
17
15
 
18
16
  def _eval(&block)
@@ -3,11 +3,16 @@ module CloudSesame
3
3
  module DSL
4
4
  module BindCaller
5
5
 
6
+ def _caller=(caller)
7
+ __bind_caller_instance_variables__(caller) if caller
8
+ @_caller = caller
9
+ end
10
+
6
11
  private
7
12
 
8
- def _bind_caller_instance_variables
9
- _caller.instance_variables.each do |name|
10
- value = _caller.instance_variable_get name
13
+ def __bind_caller_instance_variables__(caller)
14
+ caller.instance_variables.each do |name|
15
+ value = caller.instance_variable_get name
11
16
  instance_variable_set name, value
12
17
  end
13
18
  end
@@ -15,9 +20,11 @@ module CloudSesame
15
20
  # ACCESS CALLER'S METHODS
16
21
  # =========================================
17
22
  def method_missing(name, *args, &block)
18
- _caller.send(name, *args, &block)
19
- rescue NoMethodError
20
- super
23
+ if _caller && _caller.respond_to?(name, *args, &block)
24
+ _caller.send(name, *args, &block)
25
+ else
26
+ super
27
+ end
21
28
  end
22
29
 
23
30
  end
@@ -1,12 +1,7 @@
1
- # =========================================================
2
- # field array methods enables field array to chain
3
- # operators after calling the field expression
4
- # accessor
5
- # =========================================================
6
1
  module CloudSesame
7
2
  module Query
8
3
  module DSL
9
- module FieldArrayMethods
4
+ module LiteralChainingMethods
10
5
 
11
6
  # NOT
12
7
  # =======================================
@@ -1,7 +1,7 @@
1
1
  module CloudSesame
2
2
  module Query
3
3
  module DSL
4
- module FieldAccessors
4
+ module LiteralMethods
5
5
  extend ClassSpecific
6
6
 
7
7
  def self.__define_accessor__(name)
@@ -3,7 +3,7 @@ module CloudSesame
3
3
  module Node
4
4
  class Fuzziness
5
5
 
6
- EXCLUDING_TERMS = /^\-/.freeze
6
+ EXCLUDING_TERMS = /(^\-|\*$)/.freeze
7
7
 
8
8
  def initialize(&block)
9
9
 
data/lib/cloud_sesame.rb CHANGED
@@ -25,10 +25,11 @@ require 'cloud_sesame/config/credential'
25
25
  require 'cloud_sesame/query/dsl/applied_filter_query'
26
26
  require 'cloud_sesame/query/dsl/bind_caller'
27
27
  require 'cloud_sesame/query/dsl/block_styled_operators'
28
- require 'cloud_sesame/query/dsl/field_accessors'
28
+ require 'cloud_sesame/query/dsl/literal_methods'
29
+ require 'cloud_sesame/query/dsl/literal_chaining_methods'
29
30
  require 'cloud_sesame/query/dsl/scope_accessors'
30
31
  require 'cloud_sesame/query/dsl/operators'
31
- require 'cloud_sesame/query/dsl/field_array_methods'
32
+
32
33
  require 'cloud_sesame/query/dsl/inspect_method'
33
34
  require 'cloud_sesame/query/dsl/page_methods'
34
35
  require 'cloud_sesame/query/dsl/query_methods'
@@ -49,7 +50,7 @@ require 'cloud_sesame/query/ast/abstract/operator'
49
50
  require 'cloud_sesame/query/ast/abstract/multi_expression_operator'
50
51
  require 'cloud_sesame/query/ast/abstract/single_expression_operator'
51
52
  require 'cloud_sesame/query/ast/abstract/value'
52
- require 'cloud_sesame/query/ast/field_array'
53
+ require 'cloud_sesame/query/ast/multi_expression_operator_children'
53
54
  require 'cloud_sesame/query/ast/and'
54
55
  require 'cloud_sesame/query/ast/or'
55
56
  require 'cloud_sesame/query/ast/not'
@@ -19,11 +19,15 @@ module CloudSesame
19
19
  expect(subject.children).to be_empty
20
20
  end
21
21
  it 'should be an Field Array' do
22
- expect(subject.children).to be_a AST::FieldArray
22
+ expect(subject.children).to be_a AST::MultiExpressionOperatorChildren
23
23
  end
24
24
  end
25
25
 
26
26
  describe '#compile' do
27
+ it 'should accept one optional param' do
28
+ expect{ subject.compile(true) }.to_not raise_error
29
+ end
30
+
27
31
  context 'when theres children' do
28
32
  let(:child) { OpenStruct.new(compile: "compiled") }
29
33
  before { subject.children << child }
@@ -0,0 +1,57 @@
1
+ module CloudSesame
2
+ module Query
3
+ module AST
4
+ describe MultiExpressionOperatorChildren do
5
+
6
+ describe '.build' do
7
+
8
+
9
+
10
+ context 'when children is given' do
11
+
12
+ end
13
+ end
14
+
15
+ describe '#field=' do
16
+
17
+ end
18
+
19
+ describe '#parents' do
20
+
21
+ end
22
+
23
+ describe '#_context' do
24
+
25
+ end
26
+
27
+ describe '#compile' do
28
+
29
+ end
30
+ end
31
+ # class FieldArray < Array
32
+ # include DSL::FieldArrayMethods
33
+
34
+ # attr_accessor :_scope, :_return
35
+ # attr_reader :field
36
+
37
+ # def field=(field)
38
+ # parents.clear
39
+ # @field = field
40
+ # end
41
+
42
+ # def parents
43
+ # @parents ||= []
44
+ # end
45
+
46
+ # def _context
47
+ # _scope && _scope.context
48
+ # end
49
+
50
+ # def compile
51
+ # map(&:compile).join(' ')
52
+ # end
53
+
54
+ # end
55
+ end
56
+ end
57
+ end