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
@@ -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
|