CloudSesame 0.1.6 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/cloud_sesame.gemspec +1 -1
  4. data/lib/cloud_sesame/domain/base.rb +9 -0
  5. data/lib/cloud_sesame/query/ast/and.rb +1 -1
  6. data/lib/cloud_sesame/query/ast/block_chaining_relation.rb +30 -0
  7. data/lib/cloud_sesame/query/ast/field_array.rb +31 -0
  8. data/lib/cloud_sesame/query/ast/literal.rb +15 -9
  9. data/lib/cloud_sesame/query/ast/multi_expression_operator.rb +26 -8
  10. data/lib/cloud_sesame/query/ast/near.rb +5 -10
  11. data/lib/cloud_sesame/query/ast/not.rb +11 -1
  12. data/lib/cloud_sesame/query/ast/operator.rb +26 -0
  13. data/lib/cloud_sesame/query/ast/or.rb +1 -1
  14. data/lib/cloud_sesame/query/ast/phrase.rb +2 -6
  15. data/lib/cloud_sesame/query/ast/prefix.rb +2 -6
  16. data/lib/cloud_sesame/query/ast/range_value.rb +1 -1
  17. data/lib/cloud_sesame/query/ast/root.rb +7 -3
  18. data/lib/cloud_sesame/query/ast/single_expression_operator.rb +16 -7
  19. data/lib/cloud_sesame/query/ast/term.rb +2 -6
  20. data/lib/cloud_sesame/query/ast/value.rb +5 -5
  21. data/lib/cloud_sesame/query/builder.rb +18 -8
  22. data/lib/cloud_sesame/query/dsl/base.rb +6 -6
  23. data/lib/cloud_sesame/query/dsl/block_chaining_methods.rb +26 -0
  24. data/lib/cloud_sesame/query/dsl/block_methods.rb +41 -0
  25. data/lib/cloud_sesame/query/dsl/field_array_methods.rb +70 -0
  26. data/lib/cloud_sesame/query/dsl/field_methods.rb +25 -0
  27. data/lib/cloud_sesame/query/dsl/{filter_query.rb → filter_query_methods.rb} +3 -9
  28. data/lib/cloud_sesame/query/dsl/operator_methods.rb +53 -0
  29. data/lib/cloud_sesame/query/dsl/{page.rb → page_methods.rb} +12 -1
  30. data/lib/cloud_sesame/query/dsl/{query.rb → query_methods.rb} +1 -1
  31. data/lib/cloud_sesame/query/dsl/{return.rb → return_methods.rb} +1 -1
  32. data/lib/cloud_sesame/query/dsl/{scope.rb → scope_methods.rb} +3 -3
  33. data/lib/cloud_sesame/query/dsl/{sort.rb → sort_methods.rb} +1 -1
  34. data/lib/cloud_sesame/query/dsl/{value.rb → value_methods.rb} +1 -4
  35. data/lib/cloud_sesame/query/{ast/leaf.rb → error/invalid_syntax.rb} +2 -2
  36. data/lib/cloud_sesame/query/fuzziness.rb +54 -0
  37. data/lib/cloud_sesame/query/node/page.rb +6 -6
  38. data/lib/cloud_sesame/query/node/query.rb +14 -10
  39. data/lib/cloud_sesame/query/node/sort.rb +1 -1
  40. data/lib/cloud_sesame.rb +19 -16
  41. data/spec/cloud_sesame/query/dsl/base_spec.rb +2 -2
  42. data/spec/cloud_sesame/query/dsl/block_chaining_methods_spec.rb +73 -0
  43. data/spec/cloud_sesame/query/dsl/block_methods_spec.rb +117 -0
  44. data/spec/cloud_sesame/query/dsl/field_array_methods_spec.rb +69 -0
  45. data/spec/cloud_sesame/query/dsl/field_methods_spec.rb +54 -0
  46. data/spec/cloud_sesame/query/node/query_spec.rb +16 -9
  47. data/spec/cloud_sesame_spec.rb +79 -68
  48. metadata +26 -34
  49. data/lib/cloud_sesame/query/ast/compound_array.rb +0 -77
  50. data/lib/cloud_sesame/query/ast/multi_branch.rb +0 -27
  51. data/lib/cloud_sesame/query/ast/single_branch.rb +0 -27
  52. data/lib/cloud_sesame/query/dsl/and.rb +0 -19
  53. data/lib/cloud_sesame/query/dsl/boost.rb +0 -20
  54. data/lib/cloud_sesame/query/dsl/literal.rb +0 -72
  55. data/lib/cloud_sesame/query/dsl/or.rb +0 -19
  56. data/spec/cloud_sesame/query/ast/and_spec.rb +0 -13
  57. data/spec/cloud_sesame/query/ast/literal_spec.rb +0 -37
  58. data/spec/cloud_sesame/query/ast/multi_branch_spec.rb +0 -65
  59. data/spec/cloud_sesame/query/ast/multi_expression_operator_spec.rb +0 -26
  60. data/spec/cloud_sesame/query/ast/or_spec.rb +0 -13
  61. data/spec/cloud_sesame/query/ast/root_spec.rb +0 -43
  62. data/spec/cloud_sesame/query/ast/value_spec.rb +0 -40
  63. data/spec/cloud_sesame/query/dsl/filter_query_spec.rb +0 -108
  64. data/spec/cloud_sesame/query/node/request_spec.rb +0 -71
@@ -1,22 +1,17 @@
1
1
  module CloudSesame
2
2
  module Query
3
3
  module DSL
4
- module FilterQuery
5
- include And
6
- include Literal
7
- include Or
8
- include Scope
9
- include Value
4
+ module FilterQueryMethods
10
5
 
11
6
  def included?(field, value = nil)
12
- (field_options = method_scope.context[:fields][field]) && (
7
+ (field_options = dsl_context[:fields][field]) && (
13
8
  (value && field_options_is(:included, field_options, value)) ||
14
9
  (!value && field_options_not_empty_in(:included, field_options))
15
10
  )
16
11
  end
17
12
 
18
13
  def excluded?(field, value = nil)
19
- (field_options = method_scope.context[:fields][field]) && (
14
+ (field_options = dsl_context[:fields][field]) && (
20
15
  (value && field_options_is(:excluded, field_options, value)) ||
21
16
  (!value && field_options_not_empty_in(:excluded, field_options))
22
17
  )
@@ -32,7 +27,6 @@ module CloudSesame
32
27
  field_options[type] && !field_options[type].empty?
33
28
  end
34
29
 
35
-
36
30
  end
37
31
  end
38
32
  end
@@ -0,0 +1,53 @@
1
+ module CloudSesame
2
+ module Query
3
+ module DSL
4
+ module OperatorMethods
5
+
6
+ # NEAR: creates a single NEAR node
7
+ # =======================================
8
+ def near(value, options = {})
9
+ create_literal AST::Near, options, value
10
+ end
11
+
12
+ alias_method :sloppy, :near
13
+
14
+ # PREFIX: creates a single PREFIX node
15
+ # =======================================
16
+ def prefix(value, options = {})
17
+ create_literal AST::Prefix, options, value
18
+ end
19
+
20
+ alias_method :start_with, :prefix
21
+ alias_method :begin_with, :prefix
22
+
23
+ # PHRASE: creates a single PHRASE node
24
+ # =======================================
25
+ def phrase(value, options = {})
26
+ create_literal AST::Phrase, options, value
27
+ end
28
+
29
+ # TERM: creates a single TERM node
30
+ # =======================================
31
+ def term(value, options = {})
32
+ create_literal AST::Term, options, value
33
+ end
34
+
35
+ private
36
+
37
+ def fields
38
+ dsl_context[:fields]
39
+ end
40
+
41
+ def create_literal(klass, options, value)
42
+ (operator = klass.new dsl_context, options) << literal(value)
43
+ return operator
44
+ end
45
+
46
+ def literal(value)
47
+ AST::Literal.new nil, value
48
+ end
49
+
50
+ end
51
+ end
52
+ end
53
+ end
@@ -1,12 +1,13 @@
1
1
  module CloudSesame
2
2
  module Query
3
3
  module DSL
4
- module Page
4
+ module PageMethods
5
5
 
6
6
  # CLAUSE: PAGE and SIZE
7
7
  # =========================================
8
8
  def page(input = nil)
9
9
  if input
10
+ request.page.start = nil
10
11
  request.page.page = input.to_i
11
12
  return self
12
13
  else
@@ -14,6 +15,16 @@ module CloudSesame
14
15
  end
15
16
  end
16
17
 
18
+ def start(input = nil)
19
+ if input
20
+ request.page.page = nil
21
+ request.page.start = input.to_i
22
+ return self
23
+ else
24
+ request.page.start
25
+ end
26
+ end
27
+
17
28
  def size(input)
18
29
  if input
19
30
  request.page.size = input.to_i
@@ -1,7 +1,7 @@
1
1
  module CloudSesame
2
2
  module Query
3
3
  module DSL
4
- module Query
4
+ module QueryMethods
5
5
 
6
6
  def query(input = nil)
7
7
  if input
@@ -1,7 +1,7 @@
1
1
  module CloudSesame
2
2
  module Query
3
3
  module DSL
4
- module Return
4
+ module ReturnMethods
5
5
 
6
6
  def all_fields
7
7
  request.return_field.value = :all_fields
@@ -1,10 +1,10 @@
1
1
  module CloudSesame
2
2
  module Query
3
3
  module DSL
4
- module Scope
4
+ module ScopeMethods
5
5
 
6
6
  def scopes
7
- method_context[:scopes]
7
+ dsl_context[:scopes]
8
8
  end
9
9
 
10
10
  private
@@ -12,7 +12,7 @@ module CloudSesame
12
12
  def method_missing(name, *args, &block)
13
13
  if scopes && (callback = scopes[name])
14
14
  self.instance_exec *args, &callback
15
- method_return
15
+ dsl_return
16
16
  else
17
17
  super
18
18
  end
@@ -1,7 +1,7 @@
1
1
  module CloudSesame
2
2
  module Query
3
3
  module DSL
4
- module Sort
4
+ module SortMethods
5
5
 
6
6
  def sort(input = nil)
7
7
  if input.is_a? Hash
@@ -1,10 +1,7 @@
1
1
  module CloudSesame
2
2
  module Query
3
3
  module DSL
4
- module Value
5
-
6
- # VALUE DSL
7
- # =======================================
4
+ module ValueMethods
8
5
 
9
6
  # DATE
10
7
  # =======================================
@@ -1,7 +1,7 @@
1
1
  module CloudSesame
2
2
  module Query
3
- module AST
4
- class Leaf
3
+ module Error
4
+ class InvalidSyntax < Exception
5
5
  end
6
6
  end
7
7
  end
@@ -0,0 +1,54 @@
1
+ module CloudSesame
2
+ module Query
3
+ class Fuzziness
4
+
5
+ def initialize(&block)
6
+
7
+ # default fuzziness
8
+ @max_fuzziness = 3
9
+ @min_char_size = 6
10
+ @fuzzy_percent = 0.17
11
+
12
+ instance_eval &block if block_given?
13
+ end
14
+
15
+ def max_fuzziness(int)
16
+ @max_fuzziness = int.to_i
17
+ end
18
+
19
+ def min_char_size(int)
20
+ @min_char_size = int.to_i
21
+ end
22
+
23
+ def fuzzy_percent(float)
24
+ @fuzzy_percent = float.to_f
25
+ end
26
+
27
+ def parse(string)
28
+ result = each_with(string) { |word| fuzziness word }
29
+ join_by_and result
30
+ end
31
+
32
+ private
33
+
34
+ def each_with(string, &block)
35
+ string.split(' ').map &block
36
+ end
37
+
38
+ def fuzziness(word)
39
+ if word.length >= @min_char_size
40
+ fuzziness = (word.length * @fuzzy_percent).round
41
+ fuzziness = [fuzziness, @max_fuzziness].min
42
+ "#{word}~#{fuzziness}"
43
+ else
44
+ word
45
+ end
46
+ end
47
+
48
+ def join_by_and(*args)
49
+ (args = args.flatten.compact).size > 1 ? "(#{ args.join('+') })" : args[0]
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -3,18 +3,18 @@ module CloudSesame
3
3
  module Node
4
4
  class Page < Abstract
5
5
 
6
- attr_writer :page, :size
6
+ attr_writer :page, :size, :start
7
7
 
8
- def page
9
- @page ||= (context[:page] || 1)
10
- end
8
+ def page
9
+ @page ||= context[:page] || 1
10
+ end
11
11
 
12
12
  def size
13
- @size ||= (context[:size] || 10)
13
+ @size ||= context[:size] || 10
14
14
  end
15
15
 
16
16
  def start
17
- (page - 1) * size
17
+ @start ||= (page - 1) * size
18
18
  end
19
19
 
20
20
  def compile
@@ -3,24 +3,28 @@ module CloudSesame
3
3
  module Node
4
4
  class Query < Abstract
5
5
 
6
- def terms=(array)
7
- @terms = array
6
+ attr_writer :query
7
+
8
+ def query
9
+ @query ||= context[:query]
8
10
  end
9
11
 
10
- def terms
11
- @terms ||= (q = context[:query]) ? q.split(' ') : []
12
+ def compile
13
+ { query: join_by_or(query, fuzziness, sloppiness) }
12
14
  end
13
15
 
14
- def query
15
- terms.map!(&:strip).join(' ')
16
+ private
17
+
18
+ def fuzziness
19
+ context[:fuzziness] ? context[:fuzziness].parse(query) : nil
16
20
  end
17
21
 
18
- def query=(string = '')
19
- @terms = string.split(' ')
22
+ def sloppiness
23
+ context[:sloppiness] && query.include?(' ') ? "\"#{ query }\"~#{ context[:sloppiness] }" : nil
20
24
  end
21
25
 
22
- def compile
23
- { query: query }
26
+ def join_by_or(*args)
27
+ (args = args.flatten.compact).size > 1 ? "(#{ args.join('|') })" : args[0]
24
28
  end
25
29
 
26
30
  end
@@ -13,7 +13,7 @@ module CloudSesame
13
13
  sorting_attributes[attribute.to_sym]
14
14
  end
15
15
 
16
- def []=(attribute, order = nil)
16
+ def []=(attribute, order = :desc)
17
17
  sorting_attributes[attribute.to_sym] = order.to_sym if order
18
18
  end
19
19
 
data/lib/cloud_sesame.rb CHANGED
@@ -10,30 +10,34 @@ require 'cloud_sesame/config/credential'
10
10
 
11
11
  # Custom Errors
12
12
  # ===============================================
13
+ require 'cloud_sesame/query/error/invalid_syntax'
13
14
  require 'cloud_sesame/query/error/missing_operator_symbol'
14
15
  require 'cloud_sesame/query/error/missing_query'
15
16
 
16
17
  # Query DSL Methods
17
18
  # ===============================================
18
19
  require 'cloud_sesame/query/dsl/base'
19
- require 'cloud_sesame/query/dsl/query'
20
- require 'cloud_sesame/query/dsl/page'
21
- require 'cloud_sesame/query/dsl/sort'
22
- require 'cloud_sesame/query/dsl/and'
23
- require 'cloud_sesame/query/dsl/or'
24
- require 'cloud_sesame/query/dsl/literal'
25
- require 'cloud_sesame/query/dsl/value'
26
- require 'cloud_sesame/query/dsl/scope'
27
- require 'cloud_sesame/query/dsl/filter_query'
28
- require 'cloud_sesame/query/dsl/boost'
29
- require 'cloud_sesame/query/dsl/return'
20
+ require 'cloud_sesame/query/dsl/query_methods'
21
+ require 'cloud_sesame/query/dsl/page_methods'
22
+ require 'cloud_sesame/query/dsl/sort_methods'
23
+ require 'cloud_sesame/query/dsl/return_methods'
24
+
25
+ require 'cloud_sesame/query/dsl/block_methods'
26
+ require 'cloud_sesame/query/dsl/block_chaining_methods'
27
+ require 'cloud_sesame/query/dsl/field_methods'
28
+ require 'cloud_sesame/query/dsl/field_array_methods'
29
+ require 'cloud_sesame/query/dsl/filter_query_methods'
30
+ require 'cloud_sesame/query/dsl/operator_methods'
31
+ require 'cloud_sesame/query/dsl/scope_methods'
32
+ require 'cloud_sesame/query/dsl/value_methods'
30
33
 
31
34
  # Query Query Filter Query AST Tree
32
35
  # ===============================================
33
- require 'cloud_sesame/query/ast/multi_branch'
34
- require 'cloud_sesame/query/ast/single_branch'
36
+ require 'cloud_sesame/query/ast/operator'
35
37
  require 'cloud_sesame/query/ast/multi_expression_operator'
36
38
  require 'cloud_sesame/query/ast/single_expression_operator'
39
+ require 'cloud_sesame/query/ast/block_chaining_relation'
40
+ require 'cloud_sesame/query/ast/field_array'
37
41
  require 'cloud_sesame/query/ast/and'
38
42
  require 'cloud_sesame/query/ast/or'
39
43
  require 'cloud_sesame/query/ast/not'
@@ -41,13 +45,11 @@ require 'cloud_sesame/query/ast/near'
41
45
  require 'cloud_sesame/query/ast/phrase'
42
46
  require 'cloud_sesame/query/ast/prefix'
43
47
  require 'cloud_sesame/query/ast/term'
44
- require 'cloud_sesame/query/ast/compound_array'
45
- require 'cloud_sesame/query/ast/root'
46
- require 'cloud_sesame/query/ast/leaf'
47
48
  require 'cloud_sesame/query/ast/literal'
48
49
  require 'cloud_sesame/query/ast/value'
49
50
  require 'cloud_sesame/query/ast/date_value'
50
51
  require 'cloud_sesame/query/ast/range_value'
52
+ require 'cloud_sesame/query/ast/root'
51
53
 
52
54
  # Query Request Nodes
53
55
  # ===============================================
@@ -66,6 +68,7 @@ require 'cloud_sesame/query/node/return'
66
68
  # Query Builder Interface
67
69
  # ===============================================
68
70
  require 'cloud_sesame/query/builder'
71
+ require 'cloud_sesame/query/fuzziness'
69
72
 
70
73
  # Domain Objects
71
74
  # ===============================================
@@ -16,12 +16,12 @@ module CloudSesame
16
16
  end
17
17
 
18
18
  describe '#method_return' do
19
- let(:result) { subject.send(:method_return) }
19
+ let(:result) { subject.send(:dsl_return) }
20
20
  include_examples 'return self instance'
21
21
  end
22
22
 
23
23
  describe '#method_scope' do
24
- let(:result) { subject.send(:method_scope) }
24
+ let(:result) { subject.send(:dsl_scope) }
25
25
  include_examples 'return self instance'
26
26
  end
27
27
 
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ module CloudSesame
4
+ module Query
5
+ module DSL
6
+ describe BlockChainingMethods do
7
+
8
+ # Setup Test Class
9
+ class Product
10
+ include CloudSesame
11
+ define_cloudsearch {}
12
+ end
13
+
14
+ subject(:cloudsearch) { Product.cloudsearch }
15
+
16
+ after { subject.clear_request }
17
+
18
+ # NOT
19
+ # =======================================
20
+ describe '#not' do
21
+ let(:node_class) { AST::Not }
22
+
23
+ context 'when not called after an operator' do
24
+ it 'should raise an error' do
25
+ expect{ subject.not }.to raise_error NoMethodError
26
+ end
27
+ end
28
+ context 'when called after an multi expression operator method call' do
29
+ context 'and not block is given' do
30
+ it 'should raise an error' do
31
+ expect{ subject.or.not }.to raise_error Error::InvalidSyntax
32
+ end
33
+ end
34
+ context 'and block is given' do
35
+ it 'should create a NOT node' do
36
+ expect(node_class).to receive(:new).and_call_original
37
+ subject.and.not {}
38
+ end
39
+ it 'should create a operator node with the block passed to not' do
40
+ proc = -> { }
41
+ expect_any_instance_of(AST::And).to receive(:evaluate) { |context, options, &block|
42
+ expect(block).to eq(proc)
43
+ }
44
+ subject.and.not &proc
45
+ end
46
+ it 'should have the operator node as child' do
47
+ subject.and.not {}
48
+ expect(subject.request.filter_query.root.children[0].child ).to be_kind_of(AST::And)
49
+ end
50
+ it 'should belong to the dsl scope' do
51
+ expect{ subject.and.not {} }.to change{ subject.request.filter_query.root.children[0] }.from(nil).to be_kind_of(node_class)
52
+ end
53
+ context 'from root' do
54
+ it 'should return the cloudsearch domain' do
55
+ expect(subject.and.not {}).to eq subject
56
+ end
57
+ end
58
+ context 'from inside of nested block' do
59
+ it 'should return the Not node itself' do
60
+ node = nil
61
+ subject.and { node = or!.not {} }
62
+ expect(node).to be_kind_of(node_class)
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,117 @@
1
+ require 'spec_helper'
2
+
3
+ module CloudSesame
4
+ module Query
5
+ module DSL
6
+ describe BlockMethods do
7
+
8
+ # Setup Test Class
9
+ class Product
10
+ include CloudSesame
11
+ define_cloudsearch {}
12
+ end
13
+
14
+ subject(:cloudsearch) { Product.cloudsearch }
15
+
16
+ after { subject.clear_request }
17
+
18
+ # AND
19
+ # =======================================================
20
+ describe '#and' do
21
+
22
+ it 'should create an AND node' do
23
+ expect(AST::And).to receive(:new).once
24
+ subject.and
25
+ end
26
+
27
+ context 'when given a block' do
28
+
29
+ context 'when called from cloudsearch' do
30
+ it 'should become a child of root node' do
31
+ node = nil
32
+ subject.and { node = self; }
33
+ expect(subject.request.filter_query.root.children).to include(node)
34
+ end
35
+ it 'should return cloudsearch' do
36
+ expect(subject.and {}).to eq subject
37
+ end
38
+ it 'should use self as the dsl scope in the block' do
39
+ block = ->(scope, node) { expect(scope).to eq node }
40
+ subject.and { block.call(dsl_scope, self) }
41
+ end
42
+ end
43
+
44
+ context 'when called from inside a block' do
45
+ it 'should become a child of the dsl_scope' do
46
+ parent = nil
47
+ child = nil
48
+ subject.or { parent = self; child = and! {} }
49
+ expect(parent.children).to include(child)
50
+ end
51
+ it 'should return the node it self' do
52
+ node = AST::And.new({})
53
+ return_node = nil
54
+ allow(AST::And).to receive(:new).and_return(node)
55
+ subject.or { return_node = and! {} }
56
+ expect(return_node).to eq node
57
+ end
58
+ end
59
+
60
+ end
61
+
62
+ context 'when not given a block' do
63
+ it 'should reutnr a block chaining relation object' do
64
+ expect(subject.and).to be_kind_of(AST::BlockChainingRelation)
65
+ end
66
+ it 'should not add a child to it\'s dsl scope' do
67
+ expect{ subject.and }.to_not change { subject.request.filter_query.root.children.size }
68
+ end
69
+ end
70
+
71
+ end
72
+
73
+ # OR
74
+ # =======================================================
75
+ describe '#or' do
76
+
77
+ it 'should create an Or node' do
78
+ expect(AST::Or).to receive(:new).once
79
+ subject.or
80
+ end
81
+
82
+ context 'when called from cloudsearch' do
83
+ it 'should become a child of root node' do
84
+ node = nil
85
+ subject.or { node = self; }
86
+ expect(subject.request.filter_query.root.children).to include(node)
87
+ end
88
+ it 'should return cloudsearch' do
89
+ expect(subject.or {}).to eq subject
90
+ end
91
+ it 'should use self as the dsl scope in the block' do
92
+ block = ->(scope, node) { expect(scope).to eq node }
93
+ subject.and { block.call(dsl_scope, self) }
94
+ end
95
+ end
96
+
97
+ context 'when called from inside a block' do
98
+ it 'should become a child of the dsl_scope' do
99
+ parent = nil
100
+ child = nil
101
+ subject.and { parent = self; child = or! {} }
102
+ expect(parent.children).to include(child)
103
+ end
104
+ it 'should return the node it self' do
105
+ node = AST::Or.new({})
106
+ return_node = nil
107
+ allow(AST::Or).to receive(:new).and_return(node)
108
+ subject.and { return_node = or! {} }
109
+ expect(return_node).to eq node
110
+ end
111
+ end
112
+ end
113
+
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ module CloudSesame
4
+ module Query
5
+ module DSL
6
+ describe FieldArrayMethods do
7
+
8
+ # Setup Test Class
9
+ class Product
10
+ include CloudSesame
11
+ define_cloudsearch {
12
+ field :name
13
+ field :tags
14
+ }
15
+ end
16
+
17
+ subject(:cloudsearch) { Product.cloudsearch }
18
+
19
+ after { subject.clear_request }
20
+
21
+ shared_examples_for 'single_expression_operator' do |operation, klass, operator_weight|
22
+
23
+ it "should save the class #{ klass } into parents at index #{ operator_weight }" do
24
+ array = nil
25
+ subject.and { array = tags.send(operation) }
26
+ expect(array.parents[operator_weight]).to include klass: klass
27
+ end
28
+
29
+ context 'when given values' do
30
+ let(:array) {
31
+ array = nil
32
+ subject.and { array = tags.send(operation, "men") }
33
+ array
34
+ }
35
+
36
+ it 'should create a literal node with the value' do
37
+ expect(AST::Literal).to receive(:new).with(:tags, "men", Hash).and_call_original
38
+ array
39
+ end
40
+ it 'should create a near node' do
41
+ expect(klass).to receive(:new).and_call_original
42
+ array
43
+ end
44
+ it 'should set the literal node to near node child' do
45
+ expect(array.first.child).to be_kind_of(AST::Literal)
46
+ expect(array.first.child.value).to eq "men"
47
+ end
48
+ it 'should insert the near node to itself' do
49
+ expect(array).to include(klass)
50
+ end
51
+ end
52
+ end
53
+
54
+ describe '#near' do
55
+ it_should_behave_like "single_expression_operator", :near, AST::Near, 0
56
+ end
57
+
58
+ describe '#prefix' do
59
+ it_should_behave_like "single_expression_operator", :prefix, AST::Prefix, 0
60
+ end
61
+
62
+ describe '#not' do
63
+ it_should_behave_like "single_expression_operator", :not, AST::Not, 1
64
+ end
65
+
66
+ end
67
+ end
68
+ end
69
+ end