CloudSesame 0.6.8 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.editorconfig +12 -0
- data/.gitignore +1 -1
- data/Gemfile.lock +13 -13
- data/Guardfile +1 -0
- data/cloud_sesame.gemspec +2 -2
- data/coverage/.last_run.json +1 -1
- data/coverage/.resultset.json +679 -591
- data/lib/cloud_sesame/config/credential.rb +6 -6
- data/lib/cloud_sesame/context.rb +0 -5
- data/lib/cloud_sesame/domain/base.rb +147 -128
- data/lib/cloud_sesame/domain/client.rb +25 -25
- data/lib/cloud_sesame/domain/client_module/caching/base.rb +19 -23
- data/lib/cloud_sesame/domain/client_module/caching/no_cache.rb +11 -11
- data/lib/cloud_sesame/domain/client_module/caching/rails_cache.rb +32 -28
- data/lib/cloud_sesame/domain/client_module/caching.rb +19 -28
- data/lib/cloud_sesame/domain/client_module/retry.rb +6 -6
- data/lib/cloud_sesame/domain/config.rb +6 -6
- data/lib/cloud_sesame/query/ast/abstract/multi_expression_operator.rb +37 -0
- data/lib/cloud_sesame/query/ast/abstract/operator.rb +27 -0
- data/lib/cloud_sesame/query/ast/abstract/single_expression_operator.rb +39 -0
- data/lib/cloud_sesame/query/ast/abstract/value.rb +88 -0
- data/lib/cloud_sesame/query/ast/and.rb +1 -1
- data/lib/cloud_sesame/query/ast/date_value.rb +19 -3
- data/lib/cloud_sesame/query/ast/literal.rb +13 -28
- data/lib/cloud_sesame/query/ast/near.rb +4 -4
- data/lib/cloud_sesame/query/ast/not.rb +6 -7
- data/lib/cloud_sesame/query/ast/numeric_value.rb +20 -12
- data/lib/cloud_sesame/query/ast/or.rb +1 -1
- data/lib/cloud_sesame/query/ast/phrase.rb +1 -1
- data/lib/cloud_sesame/query/ast/prefix.rb +1 -1
- data/lib/cloud_sesame/query/ast/range_value.rb +40 -39
- data/lib/cloud_sesame/query/ast/root.rb +2 -6
- data/lib/cloud_sesame/query/ast/string_value.rb +26 -0
- data/lib/cloud_sesame/query/ast/term.rb +1 -1
- data/lib/cloud_sesame/query/ast/value.rb +25 -54
- data/lib/cloud_sesame/query/builder.rb +83 -54
- data/lib/cloud_sesame/query/domain/block.rb +3 -1
- data/lib/cloud_sesame/query/dsl/applied_filter_query.rb +14 -23
- data/lib/cloud_sesame/query/dsl/field_accessors.rb +25 -22
- data/lib/cloud_sesame/query/dsl/field_array_methods.rb +1 -1
- data/lib/cloud_sesame/query/dsl/inspect_method.rb +31 -0
- data/lib/cloud_sesame/query/dsl/sort_methods.rb +5 -4
- data/lib/cloud_sesame/query/node/abstract.rb +1 -2
- data/lib/cloud_sesame/query/node/facet.rb +1 -5
- data/lib/cloud_sesame/query/node/filter_query.rb +15 -2
- data/lib/cloud_sesame/query/node/fuzziness.rb +4 -3
- data/lib/cloud_sesame/query/node/page.rb +2 -2
- data/lib/cloud_sesame/query/node/query.rb +4 -17
- data/lib/cloud_sesame/query/node/query_options.rb +6 -16
- data/lib/cloud_sesame/query/node/query_options_field.rb +3 -1
- data/lib/cloud_sesame/query/node/query_parser.rb +8 -10
- data/lib/cloud_sesame/query/node/request.rb +57 -31
- data/lib/cloud_sesame/query/node/sort.rb +25 -11
- data/lib/cloud_sesame.rb +15 -12
- data/lib/{abstract_object.rb → services/abstract_object.rb} +0 -0
- data/lib/services/class_specific.rb +44 -0
- data/lib/services/lazy_object.rb +19 -0
- data/spec/cloud_sesame/domain/base_spec.rb +26 -11
- data/spec/cloud_sesame/domain/client_module/caching/base_spec.rb +2 -1
- data/spec/cloud_sesame/domain/client_module/caching/no_cache_spec.rb +2 -3
- data/spec/cloud_sesame/domain/client_module/caching/rails_cache_spec.rb +6 -6
- data/spec/cloud_sesame/domain/client_module/caching_spec.rb +33 -32
- data/spec/cloud_sesame/query/ast/abstract/multi_expression_operator_spec.rb +67 -0
- data/spec/cloud_sesame/query/ast/abstract/operator_spec.rb +29 -0
- data/spec/cloud_sesame/query/ast/abstract/single_expression_operator_spec.rb +70 -0
- data/spec/cloud_sesame/query/ast/abstract/value_spec.rb +118 -0
- data/spec/cloud_sesame/query/ast/and_spec.rb +1 -1
- data/spec/cloud_sesame/query/ast/or_spec.rb +1 -1
- data/spec/cloud_sesame/query/ast/range_value_spec.rb +5 -11
- data/spec/cloud_sesame/query/builder_spec.rb +10 -4
- data/spec/cloud_sesame/query/domain/block_spec.rb +15 -8
- data/spec/cloud_sesame/query/dsl/{block_methods_spec.rb → block_styled_operators_spec.rb} +0 -0
- data/spec/cloud_sesame/query/dsl/field_accessors_spec.rb +88 -50
- data/spec/cloud_sesame/query/dsl/field_array_methods_spec.rb +0 -2
- data/spec/cloud_sesame/query/node/facet_spec.rb +1 -15
- data/spec/cloud_sesame/query/node/filter_query_spec.rb +16 -2
- data/spec/cloud_sesame/query/node/page_spec.rb +3 -2
- data/spec/cloud_sesame/query/node/query_options_spec.rb +1 -1
- data/spec/cloud_sesame/query/node/query_parser_spec.rb +1 -7
- data/spec/cloud_sesame/query/node/query_spec.rb +10 -28
- data/spec/cloud_sesame/query/node/sort_spec.rb +19 -28
- data/spec/cloud_sesame_spec.rb +2 -156
- data/spec/helpers/benchmark_helper.rb +12 -0
- data/spec/integration/filter_query_spec.rb +0 -0
- data/spec/profiling_spec.rb +155 -0
- data/spec/{abstract_object_spec.rb → services/abstract_object_spec.rb} +0 -0
- data/spec/services/class_specific_spec.rb +135 -0
- data/spec/spec_helper.rb +3 -0
- metadata +32 -22
- data/lib/active_support/core_ext/object/deep_dup.rb +0 -53
- data/lib/active_support/core_ext/object/duplicable.rb +0 -98
- data/lib/cloud_sesame/query/ast/multi_expression_operator.rb +0 -35
- data/lib/cloud_sesame/query/ast/operator.rb +0 -25
- data/lib/cloud_sesame/query/ast/single_expression_operator.rb +0 -35
- data/lib/cloud_sesame/query/scope.rb +0 -21
- data/profiler.rb +0 -91
- data/spec/cloud_sesame/query/ast/multi_expression_operator_spec.rb +0 -76
- data/spec/cloud_sesame/query/ast/operator_spec.rb +0 -29
- data/spec/cloud_sesame/query/ast/single_expression_operator_spec.rb +0 -78
- data/spec/context_spec.rb +0 -17
@@ -2,77 +2,103 @@ module CloudSesame
|
|
2
2
|
module Query
|
3
3
|
module Node
|
4
4
|
class Request < Abstract
|
5
|
+
extend ClassSpecific
|
6
|
+
|
7
|
+
after_construct do |searchable|
|
8
|
+
@query = Query.construct_class(searchable)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.query
|
12
|
+
@query
|
13
|
+
end
|
5
14
|
|
6
15
|
# CHILDREN
|
7
16
|
# =========================================
|
8
17
|
|
9
18
|
def query
|
10
|
-
@query ||=
|
19
|
+
@query ||= self.class.query.new(context[:query])
|
11
20
|
end
|
12
21
|
|
13
22
|
def query_options
|
14
|
-
@query_options ||= QueryOptions.new(context[:query_options]
|
23
|
+
@query_options ||= QueryOptions.new(context[:query_options])
|
15
24
|
end
|
16
25
|
|
17
26
|
def query_parser
|
18
|
-
@query_parser ||= QueryParser.new(context[:query_parser]
|
27
|
+
@query_parser ||= QueryParser.new(context[:query_parser])
|
19
28
|
end
|
20
29
|
|
21
30
|
def filter_query
|
22
|
-
@filter_query ||= FilterQuery.new(context[:filter_query]
|
31
|
+
@filter_query ||= FilterQuery.new(context[:filter_query])
|
23
32
|
end
|
24
33
|
|
25
34
|
def facet
|
26
|
-
@facet ||= Facet.new(context[:facet]
|
35
|
+
@facet ||= Facet.new(context[:facet])
|
27
36
|
end
|
28
37
|
|
29
38
|
def page
|
30
|
-
@page ||= Page.new(context[:page]
|
39
|
+
@page ||= Page.new(context[:page])
|
31
40
|
end
|
32
41
|
|
33
42
|
def sort
|
34
|
-
@sort ||= Sort.new(context[:sort]
|
43
|
+
@sort ||= Sort.new(context[:sort])
|
35
44
|
end
|
36
45
|
|
37
46
|
def return_field
|
38
|
-
@return ||= Return.new(context[:return]
|
47
|
+
@return ||= Return.new(context[:return])
|
39
48
|
end
|
40
49
|
|
41
50
|
# EVALUATION
|
42
51
|
# =========================================
|
43
52
|
|
44
53
|
def compile
|
45
|
-
compiled =
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
object.merge!(node.compile || {})
|
56
|
-
end
|
54
|
+
compiled = {}
|
55
|
+
insert_query compiled
|
56
|
+
insert_filter_query compiled
|
57
|
+
insert_query_parser compiled
|
58
|
+
insert_rest compiled
|
59
|
+
insert_page compiled
|
60
|
+
compiled
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
57
64
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
convert_to_structured_query(compiled)
|
65
|
+
def insert_query(compiled)
|
66
|
+
if (compiled_query = query.compile) && !compiled_query.empty?
|
67
|
+
compiled[:query] = compiled_query
|
62
68
|
end
|
69
|
+
end
|
63
70
|
|
64
|
-
|
71
|
+
def insert_filter_query(compiled)
|
72
|
+
if (compiled_fq = filter_query.compile)
|
73
|
+
if compiled[:query]
|
74
|
+
query_parser.simple
|
75
|
+
compiled[:filter_query] = compiled_fq
|
76
|
+
else
|
77
|
+
query_parser.structured
|
78
|
+
compiled[:query] = compiled_fq
|
79
|
+
end
|
80
|
+
end
|
65
81
|
end
|
66
82
|
|
67
|
-
|
83
|
+
def insert_query_parser(compiled)
|
84
|
+
compiled[:query_parser] = query_parser.compile
|
85
|
+
end
|
68
86
|
|
69
|
-
def
|
70
|
-
|
87
|
+
def insert_rest(compiled)
|
88
|
+
{
|
89
|
+
query_options: query_options,
|
90
|
+
facet: facet,
|
91
|
+
sort: sort,
|
92
|
+
return: return_field
|
93
|
+
}.each do |name, node|
|
94
|
+
compiled_node = node.compile
|
95
|
+
compiled[name] = compiled_node if compiled_node
|
96
|
+
end
|
97
|
+
compiled
|
71
98
|
end
|
72
99
|
|
73
|
-
def
|
74
|
-
|
75
|
-
hash
|
100
|
+
def insert_page(compiled)
|
101
|
+
compiled.merge! page.compile
|
76
102
|
end
|
77
103
|
|
78
104
|
end
|
@@ -3,32 +3,46 @@ module CloudSesame
|
|
3
3
|
module Node
|
4
4
|
class Sort < Abstract
|
5
5
|
|
6
|
-
attr_writer :
|
6
|
+
attr_writer :attributes
|
7
7
|
|
8
|
-
def
|
9
|
-
@
|
8
|
+
def attributes
|
9
|
+
@attributes ||= {}
|
10
10
|
end
|
11
11
|
|
12
12
|
def [](attribute)
|
13
|
-
|
13
|
+
attributes[attribute.to_sym]
|
14
14
|
end
|
15
15
|
|
16
|
-
def []=(attribute, order
|
17
|
-
|
16
|
+
def []=(attribute, order)
|
17
|
+
attributes[attribute.to_sym] = order
|
18
18
|
end
|
19
19
|
|
20
20
|
def compile
|
21
|
-
(
|
21
|
+
unless (compiled = serialize attributes).empty?
|
22
|
+
compiled
|
23
|
+
end
|
22
24
|
end
|
23
25
|
|
24
26
|
private
|
25
27
|
|
26
|
-
def serialize(hash
|
27
|
-
hash.
|
28
|
+
def serialize(hash)
|
29
|
+
hash.each_with_object("") do |(k, v), o|
|
30
|
+
o << (o.empty? ? '' : ',') << serialize_field(k, v)
|
31
|
+
end
|
28
32
|
end
|
29
33
|
|
30
|
-
def
|
31
|
-
|
34
|
+
def serialize_field(name, value)
|
35
|
+
"#{ field_name(name) } #{ value }"
|
36
|
+
end
|
37
|
+
|
38
|
+
def field_name(key)
|
39
|
+
(name = alias_field(key)) ? name : key
|
40
|
+
end
|
41
|
+
|
42
|
+
def alias_field(key)
|
43
|
+
context[:fields] &&
|
44
|
+
context[:fields][key] &&
|
45
|
+
context[:fields][key][:as]
|
32
46
|
end
|
33
47
|
|
34
48
|
end
|
data/lib/cloud_sesame.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# External Libraries
|
2
2
|
# ===============================================
|
3
|
-
require 'active_support/core_ext/object/deep_dup'
|
4
3
|
require 'aws-sdk'
|
5
4
|
require 'forwardable'
|
6
5
|
|
7
6
|
# Internal Libraries
|
8
7
|
# ===============================================
|
9
|
-
require 'abstract_object'
|
10
|
-
require '
|
8
|
+
require 'services/abstract_object'
|
9
|
+
require 'services/class_specific'
|
10
|
+
require 'services/lazy_object'
|
11
11
|
|
12
12
|
# Custom Errors
|
13
13
|
# ===============================================
|
@@ -16,6 +16,10 @@ require 'cloud_sesame/query/error/missing_operator_symbol'
|
|
16
16
|
require 'cloud_sesame/query/error/missing_query'
|
17
17
|
require 'cloud_sesame/query/error/scope_not_defined'
|
18
18
|
|
19
|
+
# Global Credential
|
20
|
+
# ===============================================
|
21
|
+
require 'cloud_sesame/config/credential'
|
22
|
+
|
19
23
|
# Query DSL Methods
|
20
24
|
# ===============================================
|
21
25
|
require 'cloud_sesame/query/dsl/applied_filter_query'
|
@@ -25,14 +29,12 @@ require 'cloud_sesame/query/dsl/field_accessors'
|
|
25
29
|
require 'cloud_sesame/query/dsl/scope_accessors'
|
26
30
|
require 'cloud_sesame/query/dsl/operators'
|
27
31
|
require 'cloud_sesame/query/dsl/field_array_methods'
|
28
|
-
|
29
|
-
require 'cloud_sesame/query/dsl/range_helper'
|
32
|
+
require 'cloud_sesame/query/dsl/inspect_method'
|
30
33
|
require 'cloud_sesame/query/dsl/page_methods'
|
31
34
|
require 'cloud_sesame/query/dsl/query_methods'
|
32
|
-
|
35
|
+
require 'cloud_sesame/query/dsl/range_helper'
|
33
36
|
require 'cloud_sesame/query/dsl/response_methods'
|
34
37
|
require 'cloud_sesame/query/dsl/return_methods'
|
35
|
-
|
36
38
|
require 'cloud_sesame/query/dsl/sort_methods'
|
37
39
|
|
38
40
|
# Query Query Domain Objects
|
@@ -43,9 +45,10 @@ require 'cloud_sesame/query/domain/literal'
|
|
43
45
|
|
44
46
|
# Query Query Filter Query AST Tree
|
45
47
|
# ===============================================
|
46
|
-
require 'cloud_sesame/query/ast/operator'
|
47
|
-
require 'cloud_sesame/query/ast/multi_expression_operator'
|
48
|
-
require 'cloud_sesame/query/ast/single_expression_operator'
|
48
|
+
require 'cloud_sesame/query/ast/abstract/operator'
|
49
|
+
require 'cloud_sesame/query/ast/abstract/multi_expression_operator'
|
50
|
+
require 'cloud_sesame/query/ast/abstract/single_expression_operator'
|
51
|
+
require 'cloud_sesame/query/ast/abstract/value'
|
49
52
|
require 'cloud_sesame/query/ast/field_array'
|
50
53
|
require 'cloud_sesame/query/ast/and'
|
51
54
|
require 'cloud_sesame/query/ast/or'
|
@@ -55,10 +58,11 @@ require 'cloud_sesame/query/ast/phrase'
|
|
55
58
|
require 'cloud_sesame/query/ast/prefix'
|
56
59
|
require 'cloud_sesame/query/ast/term'
|
57
60
|
require 'cloud_sesame/query/ast/literal'
|
58
|
-
require 'cloud_sesame/query/ast/
|
61
|
+
require 'cloud_sesame/query/ast/string_value'
|
59
62
|
require 'cloud_sesame/query/ast/date_value'
|
60
63
|
require 'cloud_sesame/query/ast/numeric_value'
|
61
64
|
require 'cloud_sesame/query/ast/range_value'
|
65
|
+
require 'cloud_sesame/query/ast/value'
|
62
66
|
require 'cloud_sesame/query/ast/root'
|
63
67
|
|
64
68
|
# Query Request Nodes
|
@@ -80,7 +84,6 @@ require 'cloud_sesame/query/node/return'
|
|
80
84
|
# Query Builder Interface
|
81
85
|
# ===============================================
|
82
86
|
require 'cloud_sesame/query/builder'
|
83
|
-
require 'cloud_sesame/query/scope'
|
84
87
|
|
85
88
|
# Domain Objects
|
86
89
|
# ===============================================
|
File without changes
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module ClassSpecific
|
2
|
+
|
3
|
+
def construct_class(klass, callback_args: [])
|
4
|
+
__constructor__(klass, callback_args) { |name| __define_subclass__ name, self }
|
5
|
+
end
|
6
|
+
|
7
|
+
def construct_module(klass, callback_args: [])
|
8
|
+
__constructor__(klass, callback_args) { |name| __define_submodule__ name, self }
|
9
|
+
end
|
10
|
+
|
11
|
+
def after_construct(&block)
|
12
|
+
@__construct_callback__ = block
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def __constructor__(klass, callback_args)
|
18
|
+
constant = !(name = __get_constant_name__(klass)) ? self :
|
19
|
+
constants(false).include?(name.to_sym) ? const_get(name) :
|
20
|
+
yield(name)
|
21
|
+
|
22
|
+
__invoke_callback__(constant, klass, *callback_args) if @__construct_callback__
|
23
|
+
constant
|
24
|
+
end
|
25
|
+
|
26
|
+
def __invoke_callback__(constant, klass, *args)
|
27
|
+
eval_method = constant.is_a?(Class) ? :class_exec : :module_exec
|
28
|
+
constant.send(eval_method, klass, *args, &@__construct_callback__)
|
29
|
+
@__construct_callback__ = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def __define_subclass__(name, parent)
|
33
|
+
parent.const_set(name, Class.new(parent))
|
34
|
+
end
|
35
|
+
|
36
|
+
def __define_submodule__(name, parent)
|
37
|
+
parent.const_set(name, parent.clone)
|
38
|
+
end
|
39
|
+
|
40
|
+
def __get_constant_name__(constant)
|
41
|
+
(name = constant.to_s) ? name.slice(/(?=\:\:)?\w+$/) : nil
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class LazyObject < BasicObject
|
2
|
+
|
3
|
+
def initialize(&callable)
|
4
|
+
@callable = callable
|
5
|
+
end
|
6
|
+
|
7
|
+
def __target_object__
|
8
|
+
@__target_object__ ||= @callable.call
|
9
|
+
end
|
10
|
+
|
11
|
+
def ==(object)
|
12
|
+
__target_object__ == object
|
13
|
+
end
|
14
|
+
|
15
|
+
def method_missing(method_name, *args, &block)
|
16
|
+
__target_object__.send(method_name, *args, &block)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -177,18 +177,12 @@ module CloudSesame
|
|
177
177
|
end
|
178
178
|
|
179
179
|
context 'when options :default is passed in' do
|
180
|
-
let(:proc) { Proc.new {
|
180
|
+
let(:proc) { Proc.new { } }
|
181
181
|
let(:options) {{ default: proc }}
|
182
182
|
it 'should remove the default lambda or proc from the options' do
|
183
183
|
expect(options).to receive(:delete).with(:default)
|
184
184
|
subject.field field_name, options
|
185
185
|
end
|
186
|
-
it 'should create a literal node using Query::Domain::Literal' do
|
187
|
-
domain = Query::Domain::Literal.new(field_name, {}, self)
|
188
|
-
expect(Query::Domain::Literal).to receive(:new).with(field_name, {}, self).and_return(domain)
|
189
|
-
expect(domain).to receive(:_eval) { |&block| expect(block).to eq proc }
|
190
|
-
subject.field field_name, options
|
191
|
-
end
|
192
186
|
|
193
187
|
context 'when default proc/lambda returns value' do
|
194
188
|
let(:proc) { Proc.new { "name" } }
|
@@ -208,9 +202,30 @@ module CloudSesame
|
|
208
202
|
end
|
209
203
|
end
|
210
204
|
|
211
|
-
|
212
|
-
|
213
|
-
|
205
|
+
context 'when option type is given' do
|
206
|
+
let(:options) {{ type: type }}
|
207
|
+
context 'and type is valid' do
|
208
|
+
let(:type) { :string }
|
209
|
+
it 'should reaplce the type symbol with the corresponded class' do
|
210
|
+
subject.field field_name, options
|
211
|
+
expect(subject.context[:filter_query][:fields][field_name]).to include({type: CloudSesame::Query::AST::StringValue })
|
212
|
+
end
|
213
|
+
end
|
214
|
+
context 'and type is not valid' do
|
215
|
+
let(:type) { nil }
|
216
|
+
it 'should reaplce the type symbol with the default value class' do
|
217
|
+
subject.field field_name, options
|
218
|
+
expect(subject.context[:filter_query][:fields][field_name]).to include({type: CloudSesame::Query::AST::Value })
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
context 'when option type is not given' do
|
224
|
+
let(:options) {{}}
|
225
|
+
it 'should set the field type to the default value class' do
|
226
|
+
subject.field field_name, options
|
227
|
+
expect(subject.context[:filter_query][:fields][field_name]).to include({type: CloudSesame::Query::AST::Value })
|
228
|
+
end
|
214
229
|
end
|
215
230
|
|
216
231
|
context 'when options is passed in' do
|
@@ -224,7 +239,7 @@ module CloudSesame
|
|
224
239
|
context 'when no options is passed in' do
|
225
240
|
it 'should create a options in filter query fields' do
|
226
241
|
subject.field field_name
|
227
|
-
expect(subject.context[:filter_query][:fields][field_name]).to
|
242
|
+
expect(subject.context[:filter_query][:fields][field_name]).to include({type: CloudSesame::Query::AST::Value})
|
228
243
|
end
|
229
244
|
end
|
230
245
|
end
|
@@ -6,9 +6,8 @@ module CloudSesame
|
|
6
6
|
|
7
7
|
class Searchable; end
|
8
8
|
|
9
|
-
let(:client) {
|
10
|
-
|
11
|
-
subject { NoCache.new(Searchable) { client } }
|
9
|
+
let(:client) { instance_double(Client) }
|
10
|
+
subject { NoCache.new(client, Searchable) }
|
12
11
|
|
13
12
|
describe 'fetch' do
|
14
13
|
let(:params) {{}}
|
@@ -27,20 +27,20 @@ module CloudSesame
|
|
27
27
|
|
28
28
|
# HELPERS
|
29
29
|
# =====================================
|
30
|
-
def
|
31
|
-
subject.send(:
|
30
|
+
def hexdigest(params)
|
31
|
+
subject.send(:hexdigest, params)
|
32
32
|
end
|
33
33
|
|
34
34
|
# TESTS
|
35
35
|
# =====================================
|
36
36
|
|
37
|
-
let(:client) {
|
38
|
-
subject { RailsCache.new(Searchable)
|
37
|
+
let(:client) { instance_double(Client) }
|
38
|
+
subject { RailsCache.new(client, Searchable) }
|
39
39
|
|
40
40
|
shared_examples 'cache stored' do
|
41
41
|
it 'should cache the result' do
|
42
42
|
expect{ subject.fetch(params) }.to change{ Rails.cache.table.keys.size }
|
43
|
-
expect(Rails.cache.table[
|
43
|
+
expect(Rails.cache.table[hexdigest(params)]).to eq results
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
@@ -54,7 +54,7 @@ module CloudSesame
|
|
54
54
|
end
|
55
55
|
|
56
56
|
it 'should use the hash key generated from params to fetch the cache from Rails' do
|
57
|
-
hash_key =
|
57
|
+
hash_key = hexdigest(params)
|
58
58
|
expect(Rails.cache).to receive(:fetch).with(hash_key)
|
59
59
|
subject.fetch(params)
|
60
60
|
end
|
@@ -3,67 +3,68 @@ module CloudSesame
|
|
3
3
|
module ClientModule
|
4
4
|
describe Caching do
|
5
5
|
|
6
|
-
|
7
|
-
# =======================================
|
8
|
-
|
9
|
-
class Caching::GoodCache < Caching::Base
|
6
|
+
class Caching::GoodCache < Caching::Base
|
10
7
|
def fetch(params); end
|
11
8
|
end
|
12
9
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
class TestClient
|
17
|
-
include Caching
|
18
|
-
|
19
|
-
def aws_client
|
20
|
-
nil
|
10
|
+
let(:custom_cache) do
|
11
|
+
Class.new(Caching::Base) do
|
12
|
+
def fetch(params); end
|
21
13
|
end
|
14
|
+
end
|
22
15
|
|
23
|
-
|
24
|
-
|
16
|
+
let(:test_client) do
|
17
|
+
Class.new do
|
18
|
+
include Caching
|
19
|
+
def aws_client; end
|
20
|
+
def searchable; end
|
25
21
|
end
|
26
22
|
end
|
27
23
|
|
28
|
-
|
29
|
-
|
24
|
+
subject { test_client.new }
|
25
|
+
let(:aws_client) { subject.aws_client }
|
26
|
+
let(:searchable) { subject.searchable }
|
30
27
|
|
31
|
-
|
28
|
+
before { custom_cache }
|
32
29
|
|
33
30
|
describe '#caching_with' do
|
34
31
|
context 'when giving an existing caching module' do
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
it 'should set executor to the caching module' do
|
40
|
-
expect(subject.send(:executor)).to be_kind_of caching_module
|
41
|
-
end
|
32
|
+
let(:caching_module) { Caching::GoodCache }
|
33
|
+
before { subject.caching_with(:GoodCache) }
|
34
|
+
it 'should set executor to the caching module' do
|
35
|
+
expect(subject.executor).to be_kind_of caching_module
|
42
36
|
end
|
43
37
|
end
|
44
38
|
context 'when giving a non-existing caching module' do
|
45
39
|
it 'should raise Unrecognized Caching Module' do
|
46
|
-
expect{ subject.caching_with(:
|
40
|
+
expect{ subject.caching_with(:UnknowCache) }.to raise_error(NameError)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
context 'when give a class directly' do
|
44
|
+
let(:caching_module) { custom_cache }
|
45
|
+
before { subject.caching_with(caching_module) }
|
46
|
+
it 'should set executor as the caching module' do
|
47
|
+
expect(subject.executor).to be_kind_of caching_module
|
47
48
|
end
|
48
49
|
end
|
49
50
|
end
|
50
51
|
|
51
52
|
describe 'executor getter' do
|
52
|
-
it 'should return an Caching::NoCache executor by default' do
|
53
|
-
expect(subject.executor).to be_kind_of(Caching::NoCache)
|
54
|
-
end
|
55
53
|
it 'should default to Caching::NoCache' do
|
56
|
-
expect(Caching::NoCache).to receive(:new).with(
|
57
|
-
expect(
|
54
|
+
expect(Caching::NoCache).to receive(:new).with(aws_client, searchable) do |client, _|
|
55
|
+
expect(client).to eq subject.aws_client
|
58
56
|
end
|
59
57
|
subject.executor
|
60
58
|
end
|
59
|
+
it 'should return an Caching::NoCache executor by default' do
|
60
|
+
expect(subject.executor).to be_kind_of(Caching::NoCache)
|
61
|
+
end
|
61
62
|
end
|
62
63
|
|
63
64
|
describe 'executor setter' do
|
64
65
|
it 'should accept a caching module' do
|
65
|
-
expect(Caching::GoodCache).to receive(:new).with(
|
66
|
-
expect(
|
66
|
+
expect(Caching::GoodCache).to receive(:new).with(aws_client, searchable) do |client, _|
|
67
|
+
expect(client).to eq aws_client
|
67
68
|
end
|
68
69
|
subject.executor = Caching::GoodCache
|
69
70
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module CloudSesame
|
2
|
+
module Query
|
3
|
+
module AST
|
4
|
+
module Abstract
|
5
|
+
describe MultiExpressionOperator do
|
6
|
+
|
7
|
+
let(:context) { {} }
|
8
|
+
let(:options) { {} }
|
9
|
+
let(:block) { Proc.new {} }
|
10
|
+
|
11
|
+
subject { MultiExpressionOperator.new(context, options, &block) }
|
12
|
+
|
13
|
+
it 'should be a type of operator' do
|
14
|
+
expect(MultiExpressionOperator.ancestors).to include(Operator)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#children' do
|
18
|
+
it 'should be empty by default' do
|
19
|
+
expect(subject.children).to be_empty
|
20
|
+
end
|
21
|
+
it 'should be an Field Array' do
|
22
|
+
expect(subject.children).to be_a AST::FieldArray
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#compile' do
|
27
|
+
context 'when theres children' do
|
28
|
+
let(:child) { OpenStruct.new(compile: "compiled") }
|
29
|
+
before { subject.children << child }
|
30
|
+
|
31
|
+
it 'should compile to children' do
|
32
|
+
expect(subject.children).to receive(:compile)
|
33
|
+
subject.compile
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'and boost options is given' do
|
37
|
+
before { subject.options[:boost] = 2 }
|
38
|
+
it 'should return compiled string with boost' do
|
39
|
+
expect(subject.compile).to eq "( boost=2 compiled)"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
context 'and boost options is not given' do
|
43
|
+
it 'should return compiled string with boost' do
|
44
|
+
expect(subject.compile).to eq "( compiled)"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
context 'when theres no children' do
|
49
|
+
it 'should return nothing' do
|
50
|
+
expect(subject.compile).to eq nil
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#<<' do
|
56
|
+
it 'should push object into the children' do
|
57
|
+
object = :hello
|
58
|
+
expect(subject.children).to receive(:<<).with(object)
|
59
|
+
subject << object
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module CloudSesame
|
2
|
+
module Query
|
3
|
+
module AST
|
4
|
+
module Abstract
|
5
|
+
describe Operator do
|
6
|
+
let(:context) {{}}
|
7
|
+
let(:options) {{}}
|
8
|
+
let(:block) { Proc.new {} }
|
9
|
+
subject { Operator.new(context, options, &block) }
|
10
|
+
|
11
|
+
describe '#boost' do
|
12
|
+
context 'given boost option' do
|
13
|
+
let(:options) { { boost: 2 } }
|
14
|
+
it 'should return an compiled boost value' do
|
15
|
+
expect(subject.boost).to eq " boost=2"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
context 'given no boost option' do
|
19
|
+
it 'should return nothing' do
|
20
|
+
expect(subject.boost).to eq nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|