CloudSesame 0.6.8 → 0.7.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/.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
@@ -1,56 +1,85 @@
|
|
1
1
|
module CloudSesame
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
2
|
+
module Query
|
3
|
+
class Builder
|
4
|
+
extend ClassSpecific
|
5
|
+
include DSL::AppliedFilterQuery
|
6
|
+
include DSL::BlockStyledOperators
|
7
|
+
include DSL::InspectMethod
|
8
|
+
include DSL::PageMethods
|
9
|
+
include DSL::QueryMethods
|
10
|
+
include DSL::ResponseMethods
|
11
|
+
include DSL::ReturnMethods
|
12
|
+
include DSL::ScopeAccessors
|
13
|
+
include DSL::SortMethods
|
14
|
+
|
15
|
+
# ClassSpecific construct class callback
|
16
|
+
#
|
17
|
+
# after construct searchable specific builder,
|
18
|
+
# construct searchable specific DSL::FieldAccessors,
|
19
|
+
# and Domain::Block and include the new field accessors
|
20
|
+
# in both builder and domain block
|
21
|
+
# ===================================================
|
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])
|
25
|
+
@request = Node::Request.construct_class(searchable)
|
26
|
+
|
27
|
+
include field_accessor
|
28
|
+
end
|
29
|
+
|
30
|
+
# Domain::Block getter
|
31
|
+
def self.block_domain
|
32
|
+
@block_domain ||= Domain::Block
|
33
|
+
end
|
34
|
+
|
35
|
+
# Node::Request getter
|
36
|
+
def self.request
|
37
|
+
@request ||= Node::Request
|
38
|
+
end
|
39
|
+
|
40
|
+
# DSL::FieldAccessors getter
|
41
|
+
def self.field_accessor
|
42
|
+
@field_accessor ||= DSL::FieldAccessors
|
43
|
+
end
|
44
|
+
|
45
|
+
# ===================================================
|
46
|
+
|
47
|
+
attr_reader :context, :searchable
|
48
|
+
|
49
|
+
def initialize(context, searchable)
|
50
|
+
@context = context
|
51
|
+
@searchable = searchable
|
52
|
+
end
|
53
|
+
|
54
|
+
def request
|
55
|
+
@request ||= self.class.request.new context
|
56
|
+
end
|
57
|
+
|
58
|
+
def compile
|
59
|
+
request.compile
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def _block_domain(block)
|
65
|
+
if block
|
66
|
+
caller = block.binding.eval("self")
|
67
|
+
self.class.block_domain.new caller, _context
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def _scope
|
72
|
+
request.filter_query.root
|
73
|
+
end
|
74
|
+
|
75
|
+
def _context
|
76
|
+
_scope.context
|
77
|
+
end
|
78
|
+
|
79
|
+
def _return
|
80
|
+
self
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
56
85
|
end
|
@@ -2,14 +2,16 @@ module CloudSesame
|
|
2
2
|
module Query
|
3
3
|
module Domain
|
4
4
|
class Block
|
5
|
+
extend ClassSpecific
|
5
6
|
include DSL::AppliedFilterQuery
|
6
7
|
include DSL::BlockStyledOperators
|
7
|
-
include DSL::FieldAccessors
|
8
8
|
include DSL::Operators
|
9
9
|
include DSL::RangeHelper
|
10
10
|
include DSL::ScopeAccessors
|
11
11
|
include DSL::BindCaller
|
12
12
|
|
13
|
+
after_construct { |_, field_accessor| include field_accessor }
|
14
|
+
|
13
15
|
attr_reader :_caller, :_context, :_scopes
|
14
16
|
|
15
17
|
def initialize(_caller, _context)
|
@@ -4,42 +4,33 @@ module CloudSesame
|
|
4
4
|
module AppliedFilterQuery
|
5
5
|
|
6
6
|
def included?(field, value = nil)
|
7
|
-
|
8
|
-
if value
|
9
|
-
(index = applied.keys.index(value)) &&
|
10
|
-
(applied.values[index] != false)
|
11
|
-
else
|
12
|
-
applied.values.any?
|
13
|
-
end
|
7
|
+
applied?(field, value, true)
|
14
8
|
end
|
15
9
|
|
16
10
|
def excluded?(field, value = nil)
|
17
|
-
|
11
|
+
applied?(field, value, false)
|
12
|
+
end
|
13
|
+
|
14
|
+
def applied?(field, value, included = nil)
|
15
|
+
field = field.to_sym
|
16
|
+
applied = applied_filters(included)
|
18
17
|
if value
|
19
|
-
|
20
|
-
(applied.values[index] == false)
|
18
|
+
applied[field] && applied[field].include?(value)
|
21
19
|
else
|
22
|
-
!applied.
|
20
|
+
applied[field] && !applied[field].empty?
|
23
21
|
end
|
24
22
|
end
|
25
23
|
|
26
|
-
def applied_filters
|
27
|
-
applied = {}
|
28
|
-
|
29
|
-
if
|
30
|
-
|
31
|
-
applied[field] = values
|
24
|
+
def applied_filters(included = nil)
|
25
|
+
applied = Hash.new { |hash, key| hash[key] = [] }
|
26
|
+
_scope.applied.flatten!.compact!.each do |result|
|
27
|
+
if included.nil? || result[:included] == included
|
28
|
+
applied[result[:field]] << result[:value]
|
32
29
|
end
|
33
30
|
end
|
34
31
|
applied
|
35
32
|
end
|
36
33
|
|
37
|
-
private
|
38
|
-
|
39
|
-
def field_options_for(field)
|
40
|
-
_context[:fields][field.to_sym]
|
41
|
-
end
|
42
|
-
|
43
34
|
end
|
44
35
|
end
|
45
36
|
end
|
@@ -1,29 +1,32 @@
|
|
1
1
|
module CloudSesame
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
module Query
|
3
|
+
module DSL
|
4
|
+
module FieldAccessors
|
5
|
+
extend ClassSpecific
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
def self.__define_accessor__(name)
|
8
|
+
define_method name do |*values, &block|
|
9
|
+
literal name, *values, &block
|
10
|
+
end
|
11
|
+
end
|
9
12
|
|
10
|
-
|
11
|
-
|
13
|
+
def literal(name, *values, &block)
|
14
|
+
name = name.to_sym
|
15
|
+
values << __literal_block_handler__(name, block) if block_given?
|
16
|
+
_scope.children.field = name
|
17
|
+
_scope.children._return = _return
|
18
|
+
_scope.children.insert values
|
19
|
+
end
|
12
20
|
|
13
|
-
|
14
|
-
caller = block.binding.eval "self"
|
15
|
-
options = _scope.context[:fields][name]
|
16
|
-
domain = Domain::Literal.new(name, options, caller)
|
17
|
-
node = domain._eval(&block)
|
18
|
-
values << node
|
19
|
-
end
|
21
|
+
private
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
23
|
+
def __literal_block_handler__(name, block)
|
24
|
+
caller = block.binding.eval "self"
|
25
|
+
options = _scope.context[:fields][name]
|
26
|
+
Domain::Literal.new(name, options, caller)._eval(&block)
|
27
|
+
end
|
25
28
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
29
32
|
end
|
@@ -60,7 +60,7 @@ module CloudSesame
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def build_literal(value)
|
63
|
-
if value.kind_of?(AST::SingleExpressionOperator) || value.is_a?(AST::Literal)
|
63
|
+
if value.kind_of?(AST::Abstract::SingleExpressionOperator) || value.is_a?(AST::Literal)
|
64
64
|
value.is_for field, _context[:fields][field]
|
65
65
|
value
|
66
66
|
else
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module CloudSesame
|
2
|
+
module Query
|
3
|
+
module DSL
|
4
|
+
module InspectMethod
|
5
|
+
|
6
|
+
def inspect
|
7
|
+
string = green("#<#{ self.class }:#{ object_id }\n{")
|
8
|
+
|
9
|
+
string << compile.map { |k, v| "#{ green(k) } => #{ yellow(v) }" }.join(",\n ")
|
10
|
+
string << green('}')
|
11
|
+
string
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def green(string)
|
17
|
+
color(32, string)
|
18
|
+
end
|
19
|
+
|
20
|
+
def yellow(string)
|
21
|
+
color(33, string)
|
22
|
+
end
|
23
|
+
|
24
|
+
def color(code, string)
|
25
|
+
"\e[#{ code }m#{ string }\e[0m"
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -4,15 +4,16 @@ module CloudSesame
|
|
4
4
|
module SortMethods
|
5
5
|
|
6
6
|
def sort(input = false)
|
7
|
-
if input.is_a?
|
8
|
-
request.sort.
|
7
|
+
if input.is_a?(Hash)
|
8
|
+
request.sort.attributes = input
|
9
9
|
return self
|
10
10
|
elsif input
|
11
|
-
request.sort[input]
|
11
|
+
request.sort[input] = nil
|
12
|
+
return self
|
12
13
|
elsif input.nil?
|
13
14
|
return self
|
14
15
|
else
|
15
|
-
request.sort.
|
16
|
+
request.sort.attributes
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
@@ -3,12 +3,25 @@ module CloudSesame
|
|
3
3
|
module Node
|
4
4
|
class FilterQuery < Abstract
|
5
5
|
|
6
|
+
EXCESS_WHITESPACES = Regexp.new(/\s{2,}/).freeze
|
7
|
+
ENDING_WHITESPACES = Regexp.new(/\s+\)$/).freeze
|
8
|
+
|
6
9
|
def compile
|
7
|
-
|
10
|
+
if (compiled = root.compile) && !(compiled = strip(compiled)).empty?
|
11
|
+
compiled
|
12
|
+
end
|
8
13
|
end
|
9
14
|
|
10
15
|
def root
|
11
|
-
@root ||=
|
16
|
+
@root ||= AST::Root.new context
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def strip(string)
|
22
|
+
string.gsub!(EXCESS_WHITESPACES, ' '.freeze)
|
23
|
+
string.gsub!(ENDING_WHITESPACES, ')'.freeze)
|
24
|
+
string
|
12
25
|
end
|
13
26
|
|
14
27
|
end
|
@@ -3,7 +3,7 @@ module CloudSesame
|
|
3
3
|
module Node
|
4
4
|
class Fuzziness
|
5
5
|
|
6
|
-
EXCLUDING_TERMS =
|
6
|
+
EXCLUDING_TERMS = /^\-/.freeze
|
7
7
|
|
8
8
|
def initialize(&block)
|
9
9
|
|
@@ -28,13 +28,14 @@ module CloudSesame
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def compile(string)
|
31
|
-
|
31
|
+
(compiled = each_word_in(string) { |word| fuzziness(word) }).compact!
|
32
|
+
"(#{ compiled.join('+') })"
|
32
33
|
end
|
33
34
|
|
34
35
|
private
|
35
36
|
|
36
37
|
def each_word_in(string, &block)
|
37
|
-
string.split(' ').map(&block)
|
38
|
+
string.split(' ').map!(&block)
|
38
39
|
end
|
39
40
|
|
40
41
|
def fuzziness(word)
|
@@ -2,37 +2,24 @@ module CloudSesame
|
|
2
2
|
module Query
|
3
3
|
module Node
|
4
4
|
class Query < Abstract
|
5
|
+
extend ClassSpecific
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
def query
|
9
|
-
@query ||= context[:query]
|
10
|
-
end
|
7
|
+
attr_accessor :query
|
11
8
|
|
12
9
|
def compile
|
13
10
|
if query && !query.empty?
|
14
11
|
compiled = "(#{ query })"
|
15
12
|
|
16
|
-
[fuzziness, sloppiness].each do |parser|
|
13
|
+
[context[:fuzziness], context[:sloppiness]].each do |parser|
|
17
14
|
if parser && (parsed = parser.compile(query))
|
18
15
|
compiled << "|" << parsed
|
19
16
|
end
|
20
17
|
end
|
21
18
|
|
22
|
-
|
19
|
+
compiled
|
23
20
|
end
|
24
21
|
end
|
25
22
|
|
26
|
-
private
|
27
|
-
|
28
|
-
def fuzziness
|
29
|
-
context[:fuzziness]
|
30
|
-
end
|
31
|
-
|
32
|
-
def sloppiness
|
33
|
-
context[:sloppiness]
|
34
|
-
end
|
35
|
-
|
36
23
|
end
|
37
24
|
end
|
38
25
|
end
|
@@ -4,31 +4,21 @@ module CloudSesame
|
|
4
4
|
class QueryOptions < Abstract
|
5
5
|
|
6
6
|
def fields
|
7
|
-
@fields ||=
|
7
|
+
@fields ||= build(context[:fields])
|
8
8
|
end
|
9
9
|
|
10
10
|
def compile
|
11
|
-
{
|
12
|
-
query_options: JSON.dump({
|
13
|
-
fields: compile_fields
|
14
|
-
})
|
15
|
-
} unless fields.empty?
|
11
|
+
JSON.dump({ fields: fields.map(&:compile) }) unless fields.empty?
|
16
12
|
end
|
17
13
|
|
18
14
|
private
|
19
15
|
|
20
|
-
def
|
21
|
-
fields.map(
|
16
|
+
def build(fields)
|
17
|
+
fields ? fields.map { |field, opt| build_field(field, opt) } : []
|
22
18
|
end
|
23
19
|
|
24
|
-
def
|
25
|
-
|
26
|
-
context[:fields].map do |field, options|
|
27
|
-
QueryOptionsField.new field, options[:weight]
|
28
|
-
end
|
29
|
-
else
|
30
|
-
[]
|
31
|
-
end
|
20
|
+
def build_field(field, options)
|
21
|
+
QueryOptionsField.new field, options[:weight]
|
32
22
|
end
|
33
23
|
|
34
24
|
end
|
@@ -3,22 +3,20 @@ module CloudSesame
|
|
3
3
|
module Node
|
4
4
|
class QueryParser < Abstract
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
def type
|
7
|
+
@type ||= "simple"
|
8
|
+
end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
self.type = type; self
|
13
|
-
end
|
10
|
+
def simple
|
11
|
+
@type = "simple"
|
14
12
|
end
|
15
13
|
|
16
|
-
def
|
17
|
-
@type
|
14
|
+
def structured
|
15
|
+
@type = "structured"
|
18
16
|
end
|
19
17
|
|
20
18
|
def compile
|
21
|
-
|
19
|
+
type.to_s
|
22
20
|
end
|
23
21
|
|
24
22
|
end
|