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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/cloud_sesame.gemspec +1 -1
- data/lib/cloud_sesame/domain/base.rb +9 -0
- data/lib/cloud_sesame/query/ast/and.rb +1 -1
- data/lib/cloud_sesame/query/ast/block_chaining_relation.rb +30 -0
- data/lib/cloud_sesame/query/ast/field_array.rb +31 -0
- data/lib/cloud_sesame/query/ast/literal.rb +15 -9
- data/lib/cloud_sesame/query/ast/multi_expression_operator.rb +26 -8
- data/lib/cloud_sesame/query/ast/near.rb +5 -10
- data/lib/cloud_sesame/query/ast/not.rb +11 -1
- data/lib/cloud_sesame/query/ast/operator.rb +26 -0
- data/lib/cloud_sesame/query/ast/or.rb +1 -1
- data/lib/cloud_sesame/query/ast/phrase.rb +2 -6
- data/lib/cloud_sesame/query/ast/prefix.rb +2 -6
- data/lib/cloud_sesame/query/ast/range_value.rb +1 -1
- data/lib/cloud_sesame/query/ast/root.rb +7 -3
- data/lib/cloud_sesame/query/ast/single_expression_operator.rb +16 -7
- data/lib/cloud_sesame/query/ast/term.rb +2 -6
- data/lib/cloud_sesame/query/ast/value.rb +5 -5
- data/lib/cloud_sesame/query/builder.rb +18 -8
- data/lib/cloud_sesame/query/dsl/base.rb +6 -6
- data/lib/cloud_sesame/query/dsl/block_chaining_methods.rb +26 -0
- data/lib/cloud_sesame/query/dsl/block_methods.rb +41 -0
- data/lib/cloud_sesame/query/dsl/field_array_methods.rb +70 -0
- data/lib/cloud_sesame/query/dsl/field_methods.rb +25 -0
- data/lib/cloud_sesame/query/dsl/{filter_query.rb → filter_query_methods.rb} +3 -9
- data/lib/cloud_sesame/query/dsl/operator_methods.rb +53 -0
- data/lib/cloud_sesame/query/dsl/{page.rb → page_methods.rb} +12 -1
- data/lib/cloud_sesame/query/dsl/{query.rb → query_methods.rb} +1 -1
- data/lib/cloud_sesame/query/dsl/{return.rb → return_methods.rb} +1 -1
- data/lib/cloud_sesame/query/dsl/{scope.rb → scope_methods.rb} +3 -3
- data/lib/cloud_sesame/query/dsl/{sort.rb → sort_methods.rb} +1 -1
- data/lib/cloud_sesame/query/dsl/{value.rb → value_methods.rb} +1 -4
- data/lib/cloud_sesame/query/{ast/leaf.rb → error/invalid_syntax.rb} +2 -2
- data/lib/cloud_sesame/query/fuzziness.rb +54 -0
- data/lib/cloud_sesame/query/node/page.rb +6 -6
- data/lib/cloud_sesame/query/node/query.rb +14 -10
- data/lib/cloud_sesame/query/node/sort.rb +1 -1
- data/lib/cloud_sesame.rb +19 -16
- data/spec/cloud_sesame/query/dsl/base_spec.rb +2 -2
- data/spec/cloud_sesame/query/dsl/block_chaining_methods_spec.rb +73 -0
- data/spec/cloud_sesame/query/dsl/block_methods_spec.rb +117 -0
- data/spec/cloud_sesame/query/dsl/field_array_methods_spec.rb +69 -0
- data/spec/cloud_sesame/query/dsl/field_methods_spec.rb +54 -0
- data/spec/cloud_sesame/query/node/query_spec.rb +16 -9
- data/spec/cloud_sesame_spec.rb +79 -68
- metadata +26 -34
- data/lib/cloud_sesame/query/ast/compound_array.rb +0 -77
- data/lib/cloud_sesame/query/ast/multi_branch.rb +0 -27
- data/lib/cloud_sesame/query/ast/single_branch.rb +0 -27
- data/lib/cloud_sesame/query/dsl/and.rb +0 -19
- data/lib/cloud_sesame/query/dsl/boost.rb +0 -20
- data/lib/cloud_sesame/query/dsl/literal.rb +0 -72
- data/lib/cloud_sesame/query/dsl/or.rb +0 -19
- data/spec/cloud_sesame/query/ast/and_spec.rb +0 -13
- data/spec/cloud_sesame/query/ast/literal_spec.rb +0 -37
- data/spec/cloud_sesame/query/ast/multi_branch_spec.rb +0 -65
- data/spec/cloud_sesame/query/ast/multi_expression_operator_spec.rb +0 -26
- data/spec/cloud_sesame/query/ast/or_spec.rb +0 -13
- data/spec/cloud_sesame/query/ast/root_spec.rb +0 -43
- data/spec/cloud_sesame/query/ast/value_spec.rb +0 -40
- data/spec/cloud_sesame/query/dsl/filter_query_spec.rb +0 -108
- 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
|
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 =
|
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 =
|
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
|
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,10 +1,10 @@
|
|
1
1
|
module CloudSesame
|
2
2
|
module Query
|
3
3
|
module DSL
|
4
|
-
module
|
4
|
+
module ScopeMethods
|
5
5
|
|
6
6
|
def scopes
|
7
|
-
|
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
|
-
|
15
|
+
dsl_return
|
16
16
|
else
|
17
17
|
super
|
18
18
|
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
|
-
|
9
|
-
@page ||=
|
10
|
-
|
8
|
+
def page
|
9
|
+
@page ||= context[:page] || 1
|
10
|
+
end
|
11
11
|
|
12
12
|
def size
|
13
|
-
@size ||=
|
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
|
-
|
7
|
-
|
6
|
+
attr_writer :query
|
7
|
+
|
8
|
+
def query
|
9
|
+
@query ||= context[:query]
|
8
10
|
end
|
9
11
|
|
10
|
-
def
|
11
|
-
|
12
|
+
def compile
|
13
|
+
{ query: join_by_or(query, fuzziness, sloppiness) }
|
12
14
|
end
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
+
private
|
17
|
+
|
18
|
+
def fuzziness
|
19
|
+
context[:fuzziness] ? context[:fuzziness].parse(query) : nil
|
16
20
|
end
|
17
21
|
|
18
|
-
def
|
19
|
-
|
22
|
+
def sloppiness
|
23
|
+
context[:sloppiness] && query.include?(' ') ? "\"#{ query }\"~#{ context[:sloppiness] }" : nil
|
20
24
|
end
|
21
25
|
|
22
|
-
def
|
23
|
-
{
|
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
|
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/
|
20
|
-
require 'cloud_sesame/query/dsl/
|
21
|
-
require 'cloud_sesame/query/dsl/
|
22
|
-
require 'cloud_sesame/query/dsl/
|
23
|
-
|
24
|
-
require 'cloud_sesame/query/dsl/
|
25
|
-
require 'cloud_sesame/query/dsl/
|
26
|
-
require 'cloud_sesame/query/dsl/
|
27
|
-
require 'cloud_sesame/query/dsl/
|
28
|
-
require 'cloud_sesame/query/dsl/
|
29
|
-
require 'cloud_sesame/query/dsl/
|
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/
|
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(:
|
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(:
|
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
|