CloudSesame 0.3.6 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 37c4c9374c039f8cdab3da4ec22d17706baa23a4
4
- data.tar.gz: 9600876e639d302f4138da57c116e947087afd43
3
+ metadata.gz: a97ed18065996a1ded5cc2b8719d43e668383f4f
4
+ data.tar.gz: 94b4b851f28cbe7b50cd7f3b7d0ce45373e07e87
5
5
  SHA512:
6
- metadata.gz: bc23ba7626029370ac200ddac02a57b0731cdb695d7023f8388774f116cff99a583a6c930240f12d95ac3c702b71ecc5598d0ee82304d96c958b883ec7476383
7
- data.tar.gz: 7316b4b97c6bebe8beba9320df8e2e2fde31a797ec788b2257b2922e566ac17dedc61bc576417d00a5b131d73514c2d5144e63a53ffb996277e4a23404029216
6
+ metadata.gz: 2f62458643e0f3e95e404b326317016c07b94657a7f17ce471601d9f603667077affd7cf4319d7dd34553818f1e85f9a6e099973f701e5cc2c4e599e0893c08d
7
+ data.tar.gz: 756f7b2e14460b142b8ed59d5ac63dbd3f66deff02f4af71f57b4e9213e5b8ac3c5655e42796d2a20a399c0e9eedf26c88fe00d4bf295e6ddc4a1978eb242652
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- CloudSesame (0.3.6)
4
+ CloudSesame (0.4.0)
5
5
  aws-sdk (~> 2)
6
6
 
7
7
  GEM
data/cloud_sesame.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'CloudSesame'
3
- s.version = '0.3.6'
3
+ s.version = '0.4.0'
4
4
  s.date = '2016-01-20'
5
5
  s.summary = "AWS CloudSearch Query DSL"
6
6
  s.description = "AWS CloudSearch Query DSL"
@@ -11,12 +11,10 @@ module CloudSesame
11
11
 
12
12
  def initialize(field = nil, value = nil, options = {}, &block)
13
13
  @field = field
14
-
15
14
  @value = Value.parse value if value
16
15
  @value = Value.parse ValueEvaluator.new.instance_exec &block if block_given?
17
-
18
16
  @options = options || {}
19
- (@options[:included] ||= []) << @value
17
+ applied[@value] = true
20
18
  end
21
19
 
22
20
  def is_for(field, options)
@@ -25,27 +23,21 @@ module CloudSesame
25
23
  end
26
24
 
27
25
  def is_excluded
28
- options[:included].delete value
29
- (options[:excluded] ||= []) << value
26
+ applied[value] = applied[value] == false ? true : false
30
27
  end
31
28
 
32
29
  def as_field
33
- @as_field ||= (options[:as] || field).to_s
30
+ options[:as] || field
34
31
  end
35
32
 
36
33
  def compile(detailed = false)
37
- updated? ? recompile(detailed) : @compiled
34
+ detailed ? detailed_format : standard_format
38
35
  end
39
36
 
40
37
  private
41
38
 
42
- def updated?
43
- @compiled_value != value
44
- end
45
-
46
- def recompile(detailed)
47
- @compiled_value = value
48
- @compiled = detailed ? detailed_format : standard_format
39
+ def applied
40
+ options[:applied] ||= {}
49
41
  end
50
42
 
51
43
  def standard_format
@@ -53,7 +45,7 @@ module CloudSesame
53
45
  end
54
46
 
55
47
  def detailed_format
56
- "field=#{ escape as_field } #{ value.compile }"
48
+ "field=#{ escape as_field.to_s } #{ value.compile }"
57
49
  end
58
50
 
59
51
  def escape(data)
@@ -5,8 +5,8 @@ module CloudSesame
5
5
  DETAILED = true
6
6
  SYMBOL = :near
7
7
 
8
- def compile
9
- "(#{ symbol }#{ boost }#{ distance } #{ child.compile detailed })" if child
8
+ def compile(detailed = nil)
9
+ "(#{ symbol }#{ boost }#{ distance } #{ child.compile operator_detailed })" if child
10
10
  end
11
11
 
12
12
  def distance
@@ -6,10 +6,10 @@ module CloudSesame
6
6
 
7
7
  def <<(object)
8
8
  object.is_excluded
9
- super
9
+ self.child = object
10
10
  end
11
11
 
12
- def compile(detailed = nil)
12
+ def compile
13
13
  "(#{ symbol }#{ boost } #{ child.compile })" if child
14
14
  end
15
15
 
@@ -9,7 +9,6 @@ module CloudSesame
9
9
  def initialize(context, options = {}, &block)
10
10
  @context = context
11
11
  @options = options
12
- instance_eval &block if block_given?
13
12
  end
14
13
 
15
14
  def boost
@@ -3,22 +3,18 @@ module CloudSesame
3
3
  module AST
4
4
  class RangeValue < Value
5
5
 
6
- STRING_FORMAT = /\A(\[|{)(.*),(.*)(\}|\])\z/
6
+ RANGE_FORMAT = /\A(\[|{)(.*),(.*)(\}|\])\z/
7
7
 
8
8
  def initialize(value = nil)
9
9
  @data = if value.kind_of?(Range)
10
10
  range_to_array(value)
11
- elsif value.is_a?(String) && (match = STRING_FORMAT.match value)
11
+ elsif value.is_a?(String) && (match = string_format?(value))
12
12
  @data = match.captures
13
13
  else
14
14
  default_range
15
15
  end
16
16
  end
17
17
 
18
- def compile
19
- "#{ lb }#{ l.to_s },#{ u.to_s }#{ ub }"
20
- end
21
-
22
18
  def gt(value = nil)
23
19
  data[0], data[1] = '{', Value.parse(value) if value
24
20
  return self
@@ -39,18 +35,22 @@ module CloudSesame
39
35
  return self
40
36
  end
41
37
 
42
- def l
43
- data[1]
38
+ def compile
39
+ "#{ lb }#{ l.to_s },#{ u.to_s }#{ ub }"
44
40
  end
45
41
 
46
- def u
47
- data[2]
42
+ def ==(object)
43
+ data == Value.parse(object).data
48
44
  end
49
45
 
50
46
  private
51
47
 
52
- def range_to_array(r)
53
- ['[', r.begin, r.end, end_symbol(r)]
48
+ def string_format?(string)
49
+ RANGE_FORMAT.match string.tr(' ', '')
50
+ end
51
+
52
+ def range_to_array(range)
53
+ ['[', range.begin, range.end, end_symbol(range)]
54
54
  end
55
55
 
56
56
  def end_symbol(value)
@@ -61,6 +61,14 @@ module CloudSesame
61
61
  ['{', nil, nil, '}']
62
62
  end
63
63
 
64
+ def l
65
+ data[1]
66
+ end
67
+
68
+ def u
69
+ data[2]
70
+ end
71
+
64
72
  def lb
65
73
  data[1] ? data[0] : '{'
66
74
  end
@@ -21,11 +21,11 @@ module CloudSesame
21
21
  self.child = object
22
22
  end
23
23
 
24
- def compile
25
- "(#{ symbol }#{ boost } #{ child.compile detailed })" if child
24
+ def compile(detailed = nil)
25
+ "(#{ symbol }#{ boost } #{ child.compile operator_detailed })" if child
26
26
  end
27
27
 
28
- def detailed
28
+ def operator_detailed
29
29
  self.class::DETAILED
30
30
  end
31
31
 
@@ -3,7 +3,7 @@ module CloudSesame
3
3
  module AST
4
4
  class Value
5
5
 
6
- RANGE_FORMAT = /\A[\[\{].*[\]\}]\z/
6
+ RANGE_FORMAT = /\A(\[|{)(.*),(.*)(\}|\])\z/
7
7
  DIGIT_FORMAT = /\A\d+(.\d+)?\z/
8
8
  SINGLE_QUATE = /\'/
9
9
  ESCAPE_QUATE = "\\'"
@@ -12,15 +12,14 @@ module CloudSesame
12
12
 
13
13
  def self.parse(value)
14
14
  return value if value.kind_of? AST::Value
15
+ return AST::NumericValue.new(value) if value.is_a?(Numeric) || (value.is_a?(String) && DIGIT_FORMAT =~ value)
15
16
  return AST::DateValue.new(value) if value.kind_of?(Date) || value.kind_of?(Time)
16
17
  return AST::RangeValue.new(value) if value.kind_of?(Range) || (value.is_a?(String) && RANGE_FORMAT =~ value)
17
- return AST::NumericValue.new(value) if value.is_a?(Numeric) || (value.is_a?(String) && DIGIT_FORMAT =~ value)
18
18
  AST::Value.new(value)
19
19
  end
20
20
 
21
21
  def initialize(data)
22
22
  @data = data
23
- @compiled = compile
24
23
  end
25
24
 
26
25
  def compile
@@ -46,7 +45,7 @@ module CloudSesame
46
45
  @compiled = escape @compiled_data
47
46
  end
48
47
 
49
- def escape(data = "")
48
+ def escape(data)
50
49
  "'#{ data.gsub(SINGLE_QUATE) { ESCAPE_QUATE } }'"
51
50
  end
52
51
 
@@ -58,7 +58,7 @@ module CloudSesame
58
58
  def search
59
59
  compiled = request.compile
60
60
  raise Error::MissingQuery.new("Query or FilterQuery can not be empty!") if !compiled[:query] || compiled[:query].empty?
61
- @response = client.search compiled
61
+ @response = searchable.cloudsearch.client.search compiled
62
62
  end
63
63
 
64
64
  private
@@ -13,6 +13,10 @@ module CloudSesame
13
13
  dsl_scope.context
14
14
  end
15
15
 
16
+ def dsl_caller
17
+ dsl_context[:caller]
18
+ end
19
+
16
20
  def dsl_return(node = nil)
17
21
  node || dsl_scope
18
22
  end
@@ -26,19 +26,33 @@ module CloudSesame
26
26
  private
27
27
 
28
28
  def block_style_dsl(klass, options, &block)
29
- node = klass.new dsl_context, options, &block
29
+ node = klass.new dsl_context, options
30
30
  if block_given?
31
+ extract_caller_from block if on_root_level?
32
+ node.instance_eval &block
31
33
  dsl_scope << node
32
34
  dsl_return node
33
35
  else
34
- return_chaining_relation(node)
36
+ chaining_relation_for(node)
35
37
  end
36
38
  end
37
39
 
38
- def return_chaining_relation(node)
40
+ def chaining_relation_for(node)
39
41
  AST::BlockChainingRelation.new(dsl_scope, dsl_return, node)
40
42
  end
41
43
 
44
+ def on_root_level?
45
+ dsl_scope.is_a?(AST::Root)
46
+ end
47
+
48
+ def extract_caller_from(block)
49
+ dsl_context[:caller] = block.binding.eval "self"
50
+ end
51
+
52
+ def method_missing(name, *args, &block)
53
+ dsl_caller ? dsl_caller.send(name, *args, &block) : super
54
+ end
55
+
42
56
  end
43
57
  end
44
58
  end
@@ -4,27 +4,42 @@ module CloudSesame
4
4
  module FilterQueryMethods
5
5
 
6
6
  def included?(field, value = nil)
7
- (field_options = dsl_context[:fields][field]) && (
8
- (value && field_options_is(:included, field_options, value)) ||
9
- (!value && field_options_not_empty_in(:included, field_options))
7
+ !!(
8
+ (field_options = dsl_context[:fields][field]) &&
9
+ (applied = field_options[:applied]) &&
10
+ (
11
+ (!value && applied.values.any?) ||
12
+ (
13
+ value && (index = applied.keys.index(value)) &&
14
+ (field_options[:applied].values[index] != false)
15
+ )
16
+ )
10
17
  )
11
18
  end
12
19
 
13
20
  def excluded?(field, value = nil)
14
- (field_options = dsl_context[:fields][field]) && (
15
- (value && field_options_is(:excluded, field_options, value)) ||
16
- (!value && field_options_not_empty_in(:excluded, field_options))
21
+ !!(
22
+ (field_options = dsl_context[:fields][field]) &&
23
+ (applied = field_options[:applied]) &&
24
+ (
25
+ (!value && !applied.values.all?) ||
26
+ (
27
+ value && (index = applied.keys.index(value)) &&
28
+ field_options[:applied].values[index] == false
29
+ )
30
+ )
17
31
  )
18
32
  end
19
33
 
20
- private
21
-
22
- def field_options_is(type, field_options, value)
23
- (values = field_options[type]) && values.include?(value)
24
- end
25
-
26
- def field_options_not_empty_in(type, field_options)
27
- field_options[type] && !field_options[type].empty?
34
+ def applied_filters
35
+ applied = {}
36
+ dsl_context[:fields].each do |field, options|
37
+ if options && options[:applied] &&
38
+ !(values = options[:applied].select { |k, v| v }.keys).empty?
39
+ applied[field] = values
40
+ end
41
+ end
42
+ applied
28
43
  end
29
44
 
30
45
  end
@@ -9,15 +9,6 @@ module CloudSesame
9
9
  let(:block) { Proc.new {} }
10
10
  subject { Operator.new(context, options, &block) }
11
11
 
12
- describe '#initialize' do
13
- context 'given a block' do
14
- let(:block) { Proc.new { context[:name] = :test } }
15
- it 'should evalute the block' do
16
- expect(subject.context[:name]).to eq :test
17
- end
18
- end
19
- end
20
-
21
12
  describe '#boost' do
22
13
  context 'given boost option' do
23
14
  let(:options) {{ boost: 2 }}
@@ -62,22 +62,23 @@
62
62
  # end
63
63
 
64
64
 
65
- # # n = 500
66
- # # result = RubyProf.profile do
67
- # # n.times do
65
+ # n = 10_000
66
+ # q = nil
67
+ # result = RubyProf.profile do
68
+ # n.times do
68
69
  # q = Product.cloudsearch.query("black jacket").sort(price: :asc).page(1).size(1000).and {
69
70
  # or! {
70
- # tags "men", "women"
71
+ # tags "1", "2"
71
72
  # and! {
72
- # tags.not "child", "home"
73
+ # tags.not "3", "4"
73
74
  # }
74
75
  # and!.not {
75
- # tags.start_with "great", "nice"
76
- # tags.not.start_with "super"
77
- # tags.not.near "hello world"
78
- # tags start_with("wifi"), near("electronic")
79
- # tags term "cool"
80
- # tags phrase "flash_deal"
76
+ # tags.start_with "5", "6"
77
+ # tags.not.start_with "7"
78
+ # tags.not.near "8"
79
+ # tags start_with("9"), near("10")
80
+ # tags term "11"
81
+ # tags phrase "12"
81
82
  # }
82
83
  # or!.not {
83
84
  # price 25..100
@@ -91,15 +92,31 @@
91
92
  # created_at gte(Date.today).lt(Date.today + 3)
92
93
  # }
93
94
  # }
94
- # }.compile
95
-
96
- # # end
97
- # # end
98
- # # printer = RubyProf::FlatPrinter.new(result)
99
- # # printer.print(STDOUT, {})
100
-
101
- # # q = Product.cloudsearch.and {
102
- # binding.pry
103
- # # }
95
+ # }
96
+ # a = q.applied_filters
104
97
 
98
+ # end
99
+ # end
100
+ # printer = RubyProf::FlatPrinter.new(result)
101
+ # printer.print(STDOUT, {})
102
+
103
+ # binding.pry
104
+
105
+ # # class TestClass
106
+ # # def initialize
107
+ # # @name = "scott"
108
+ # # end
109
+ # # def greeting
110
+ # # "hello world!"
111
+ # # end
112
+ # # def test_method
113
+ # # local = :test
114
+ # # q = Product.cloudsearch.and {
115
+ # # binding.pry
116
+ # # }
117
+ # # end
118
+ # # end
119
+
120
+ # # test = TestClass.new
121
+ # # test.test_method
105
122
  # end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: CloudSesame
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.6
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Chu