CloudSesame 0.4.6 → 0.5.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +4 -1
  3. data/cloud_sesame.gemspec +2 -2
  4. data/lib/cloud_sesame/domain/base.rb +40 -30
  5. data/lib/cloud_sesame/query/ast/field_array.rb +4 -5
  6. data/lib/cloud_sesame/query/ast/literal.rb +11 -12
  7. data/lib/cloud_sesame/query/ast/multi_expression_operator.rb +4 -9
  8. data/lib/cloud_sesame/query/ast/near.rb +3 -1
  9. data/lib/cloud_sesame/query/ast/not.rb +3 -1
  10. data/lib/cloud_sesame/query/ast/root.rb +1 -1
  11. data/lib/cloud_sesame/query/ast/single_expression_operator.rb +3 -3
  12. data/lib/cloud_sesame/query/builder.rb +20 -12
  13. data/lib/cloud_sesame/query/domain/block.rb +65 -0
  14. data/lib/cloud_sesame/query/domain/chaining_block.rb +44 -0
  15. data/lib/cloud_sesame/query/domain/literal.rb +39 -0
  16. data/lib/cloud_sesame/query/dsl/block_methods.rb +6 -27
  17. data/lib/cloud_sesame/query/dsl/field_accessors.rb +24 -0
  18. data/lib/cloud_sesame/query/dsl/field_array_methods.rb +5 -9
  19. data/lib/cloud_sesame/query/dsl/filter_query_methods.rb +3 -3
  20. data/lib/cloud_sesame/query/dsl/operator_methods.rb +8 -15
  21. data/lib/cloud_sesame/query/dsl/range_methods.rb +4 -4
  22. data/lib/cloud_sesame/query/dsl/response_methods.rb +1 -1
  23. data/lib/cloud_sesame/query/dsl/scope_accessors.rb +28 -0
  24. data/lib/cloud_sesame/query/error/scope_not_defined.rb +8 -0
  25. data/lib/cloud_sesame/query/scope.rb +21 -0
  26. data/lib/cloud_sesame.rb +14 -7
  27. data/spec/cloud_sesame/query/ast/single_expression_operator_spec.rb +1 -1
  28. data/spec/cloud_sesame/query/dsl/block_methods_spec.rb +54 -70
  29. data/spec/cloud_sesame/query/dsl/{field_methods_spec.rb → field_accessors_spec.rb} +1 -1
  30. data/spec/cloud_sesame_spec.rb +35 -22
  31. metadata +30 -34
  32. data/lib/cloud_sesame/query/ast/block_chaining_relation.rb +0 -30
  33. data/lib/cloud_sesame/query/dsl/base.rb +0 -27
  34. data/lib/cloud_sesame/query/dsl/block_chaining_methods.rb +0 -26
  35. data/lib/cloud_sesame/query/dsl/field_methods.rb +0 -16
  36. data/lib/cloud_sesame/query/dsl/scope_methods.rb +0 -33
  37. data/spec/cloud_sesame/query/ast/block_chaining_relation_spec.rb +0 -44
  38. data/spec/cloud_sesame/query/dsl/base_spec.rb +0 -31
  39. data/spec/cloud_sesame/query/dsl/block_chaining_methods_spec.rb +0 -64
@@ -5,7 +5,7 @@ module CloudSesame
5
5
 
6
6
  def included?(field, value = nil)
7
7
  !!(
8
- (field_options = dsl_context[:fields][field.to_sym]) &&
8
+ (field_options = _context[:fields][field.to_sym]) &&
9
9
  (applied = field_options[:applied]) &&
10
10
  (
11
11
  (!value && applied.values.any?) ||
@@ -19,7 +19,7 @@ module CloudSesame
19
19
 
20
20
  def excluded?(field, value = nil)
21
21
  !!(
22
- (field_options = dsl_context[:fields][field.to_sym]) &&
22
+ (field_options = _context[:fields][field.to_sym]) &&
23
23
  (applied = field_options[:applied]) &&
24
24
  (
25
25
  (!value && !applied.values.all?) ||
@@ -33,7 +33,7 @@ module CloudSesame
33
33
 
34
34
  def applied_filters
35
35
  applied = {}
36
- dsl_context[:fields].each do |field, options|
36
+ _context[:fields].each do |field, options|
37
37
  if options && options[:applied] &&
38
38
  !(values = options[:applied].select { |k, v| v }.keys).empty?
39
39
  applied[field] = values
@@ -6,7 +6,7 @@ module CloudSesame
6
6
  # NEAR: creates a single NEAR node
7
7
  # =======================================
8
8
  def near(value, options = {})
9
- create_literal AST::Near, options, value
9
+ _build_operator AST::Near, options, value
10
10
  end
11
11
 
12
12
  alias_method :sloppy, :near
@@ -14,7 +14,7 @@ module CloudSesame
14
14
  # PREFIX: creates a single PREFIX node
15
15
  # =======================================
16
16
  def prefix(value, options = {})
17
- create_literal AST::Prefix, options, value
17
+ _build_operator AST::Prefix, options, value
18
18
  end
19
19
 
20
20
  alias_method :start_with, :prefix
@@ -23,28 +23,21 @@ module CloudSesame
23
23
  # PHRASE: creates a single PHRASE node
24
24
  # =======================================
25
25
  def phrase(value, options = {})
26
- create_literal AST::Phrase, options, value
26
+ _build_operator AST::Phrase, options, value
27
27
  end
28
28
 
29
29
  # TERM: creates a single TERM node
30
30
  # =======================================
31
31
  def term(value, options = {})
32
- create_literal AST::Term, options, value
32
+ _build_operator AST::Term, options, value
33
33
  end
34
34
 
35
35
  private
36
36
 
37
- def fields
38
- dsl_context[:fields]
39
- end
40
-
41
- def create_literal(klass, options, value)
42
- (node = klass.new dsl_context, options) << fieldless_literal(value)
43
- return node
44
- end
45
-
46
- def fieldless_literal(value)
47
- AST::Literal.new nil, value
37
+ def _build_operator(klass, options, value)
38
+ node = klass.new _context, options
39
+ node << AST::Literal.new(nil, value)
40
+ node
48
41
  end
49
42
 
50
43
  end
@@ -4,19 +4,19 @@ module CloudSesame
4
4
  module RangeMethods
5
5
 
6
6
  def gt(input)
7
- AST::RangeValue.new.gt(input)
7
+ AST::RangeValue.new.gt input
8
8
  end
9
9
 
10
10
  def gte(input)
11
- AST::RangeValue.new.gte(input)
11
+ AST::RangeValue.new.gte input
12
12
  end
13
13
 
14
14
  def lt(input)
15
- AST::RangeValue.new.lt(input)
15
+ AST::RangeValue.new.lt input
16
16
  end
17
17
 
18
18
  def lte(input)
19
- AST::RangeValue.new.lte(input)
19
+ AST::RangeValue.new.lte input
20
20
  end
21
21
 
22
22
  end
@@ -29,7 +29,7 @@ module CloudSesame
29
29
  def search
30
30
  compiled = request.compile
31
31
  raise Error::MissingQuery.new("Query or FilterQuery can not be empty!") if !compiled[:query] || compiled[:query].empty?
32
- @response = searchable.cloudsearch.client.search compiled
32
+ @response = @searchable.cloudsearch.client.search compiled
33
33
  end
34
34
 
35
35
  end
@@ -0,0 +1,28 @@
1
+ module CloudSesame
2
+ module Query
3
+ module DSL
4
+ module ScopeAccessors
5
+
6
+ def scopes(name = nil, *args)
7
+ defined_scopes = _scope.context[:scopes]
8
+ return _return if name.nil?
9
+ if defined_scopes && (block = defined_scopes[name.to_sym])
10
+ instance_exec *args, &block
11
+ _return
12
+ else
13
+ raise Error::ScopeNotDefined
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def method_missing(name, *args, &block)
20
+ scopes name, *args
21
+ rescue Error::ScopeNotDefined
22
+ super
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,8 @@
1
+ module CloudSesame
2
+ module Query
3
+ module Error
4
+ class ScopeNotDefined < Exception
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,21 @@
1
+ module CloudSesame
2
+ module Query
3
+ class Scope
4
+
5
+ attr_reader :_scope, :_return
6
+
7
+ def initialize(_scope, _return)
8
+ @_scope, @_return = _scope, _return
9
+ end
10
+
11
+ def _context
12
+ _scope.context
13
+ end
14
+
15
+ def <<(object)
16
+ _scope << object
17
+ end
18
+
19
+ end
20
+ end
21
+ end
data/lib/cloud_sesame.rb CHANGED
@@ -14,14 +14,13 @@ require 'cloud_sesame/config/credential'
14
14
  require 'cloud_sesame/query/error/invalid_syntax'
15
15
  require 'cloud_sesame/query/error/missing_operator_symbol'
16
16
  require 'cloud_sesame/query/error/missing_query'
17
+ require 'cloud_sesame/query/error/scope_not_defined'
17
18
 
18
19
  # Query DSL Methods
19
20
  # ===============================================
20
- require 'cloud_sesame/query/dsl/base'
21
21
  require 'cloud_sesame/query/dsl/block_methods'
22
- require 'cloud_sesame/query/dsl/block_chaining_methods'
23
22
  require 'cloud_sesame/query/dsl/field_array_methods'
24
- require 'cloud_sesame/query/dsl/field_methods'
23
+ require 'cloud_sesame/query/dsl/field_accessors'
25
24
  require 'cloud_sesame/query/dsl/filter_query_methods'
26
25
  require 'cloud_sesame/query/dsl/operator_methods'
27
26
  require 'cloud_sesame/query/dsl/page_methods'
@@ -29,15 +28,20 @@ require 'cloud_sesame/query/dsl/query_methods'
29
28
  require 'cloud_sesame/query/dsl/range_methods'
30
29
  require 'cloud_sesame/query/dsl/response_methods'
31
30
  require 'cloud_sesame/query/dsl/return_methods'
32
- require 'cloud_sesame/query/dsl/scope_methods'
31
+ require 'cloud_sesame/query/dsl/scope_accessors'
33
32
  require 'cloud_sesame/query/dsl/sort_methods'
34
33
 
34
+ # Query Query Domain Objects
35
+ # ===============================================
36
+ require 'cloud_sesame/query/domain/block'
37
+ require 'cloud_sesame/query/domain/chaining_block'
38
+ require 'cloud_sesame/query/domain/literal'
39
+
35
40
  # Query Query Filter Query AST Tree
36
41
  # ===============================================
37
42
  require 'cloud_sesame/query/ast/operator'
38
43
  require 'cloud_sesame/query/ast/multi_expression_operator'
39
44
  require 'cloud_sesame/query/ast/single_expression_operator'
40
- require 'cloud_sesame/query/ast/block_chaining_relation'
41
45
  require 'cloud_sesame/query/ast/field_array'
42
46
  require 'cloud_sesame/query/ast/and'
43
47
  require 'cloud_sesame/query/ast/or'
@@ -71,6 +75,7 @@ require 'cloud_sesame/query/node/return'
71
75
  # Query Builder Interface
72
76
  # ===============================================
73
77
  require 'cloud_sesame/query/builder'
78
+ require 'cloud_sesame/query/scope'
74
79
 
75
80
  # Domain Objects
76
81
  # ===============================================
@@ -95,13 +100,15 @@ module CloudSesame
95
100
 
96
101
  def define_cloudsearch(&block)
97
102
  if block_given?
98
- Domain::Base::DEFINITIONS[self] = block
103
+ Domain::Base.definitions[self] = block
104
+ cloudsearch._caller = block.binding.eval "self"
99
105
  cloudsearch.instance_eval &block
106
+ cloudsearch._caller = nil
100
107
  end
101
108
  end
102
109
 
103
110
  def load_definition_from(klass)
104
- if (definition = Domain::Base::DEFINITIONS[self])
111
+ if (definition = Domain::Base.definitions[self])
105
112
  cloudsearch.instance_eval &definition
106
113
  end
107
114
  end
@@ -53,7 +53,7 @@ module CloudSesame
53
53
  describe '#compile' do
54
54
  before {
55
55
  subject.child = OpenStruct.new compile: ""
56
- allow(subject.child).to receive(:compile)
56
+ allow(subject.child).to receive(:compile).and_return(" ")
57
57
  }
58
58
  it 'should compile it\'s child and detailed set to false' do
59
59
  expect(subject.child).to receive(:compile).with(SingleExpressionOperator::DETAILED)
@@ -5,7 +5,9 @@ module CloudSesame
5
5
  module DSL
6
6
  describe BlockMethods do
7
7
 
8
- # Setup Test Class
8
+ # Setup
9
+ # =================================================
10
+
9
11
  class Product
10
12
  include CloudSesame
11
13
  define_cloudsearch {}
@@ -13,99 +15,81 @@ module CloudSesame
13
15
 
14
16
  subject(:cloudsearch) { Product.cloudsearch.builder }
15
17
 
16
- # AND
17
- # =======================================================
18
- describe '#and' do
18
+ # Block Style Clause
19
+ # =================================================
20
+ shared_examples 'block styled clause' do
21
+
22
+ let(:node) { klass1.new({}) }
23
+ let(:root) { subject.request.filter_query.root }
24
+
25
+ let(:empty_block) { Proc.new { } }
26
+ let(:nested_block) { Proc.new { send(method, empty_block) } }
27
+
28
+ let(:clause_call) { subject.send(clause1, &empty_block) }
19
29
 
20
- it 'should create an AND node' do
21
- expect(AST::And).to receive(:new).once
22
- subject.and
30
+ it "should create an multi-expression node" do
31
+ expect(klass1).to receive(:new).once
32
+ subject.send(clause1)
23
33
  end
24
34
 
25
35
  context 'when given a block' do
36
+ before { allow(klass1).to receive(:new).and_return(node) }
26
37
 
27
- context 'when called from cloudsearch' do
28
- it 'should become a child of root node' do
29
- node = nil
30
- subject.and { node = self; }
31
- expect(subject.request.filter_query.root.children).to include(node)
38
+ context 'when called from cloudsearch build' do
39
+ it 'should add to root\'s children' do
40
+ expect{ clause_call }.to change{ root.children.size }.by(1)
41
+ expect(root.children).to include(node)
32
42
  end
33
- it 'should return cloudsearch' do
34
- expect(subject.and {}).to eq subject
35
- end
36
- it 'should use self as the dsl scope in the block' do
37
- block = ->(scope, node) { expect(scope).to eq node }
38
- subject.and { block.call(dsl_scope, self) }
43
+ it 'should return the build itself' do
44
+ expect(clause_call).to eq(subject)
39
45
  end
40
46
  end
41
-
42
- context 'when called from inside a block' do
43
- it 'should become a child of the dsl_scope' do
44
- parent = nil
45
- child = nil
46
- subject.or { parent = self; child = and! {} }
47
- expect(parent.children).to include(child)
47
+ context 'when called within a nested block' do
48
+ it 'should add to scope\'s children' do
49
+ subject.send(clause2) do
50
+ child = send(clause1, &empty_block)
51
+ expect(_scope.children).to include(child)
52
+ end
48
53
  end
49
54
  it 'should return the node it self' do
50
- node = AST::And.new({})
51
- return_node = nil
52
- allow(AST::And).to receive(:new).and_return(node)
53
- subject.or { return_node = and! {} }
54
- expect(return_node).to eq node
55
+ subject.send(clause2) {
56
+ child = send(clause1, &empty_block)
57
+ expect(child).to eq(node)
58
+ }
55
59
  end
56
60
  end
57
-
58
61
  end
59
62
 
60
63
  context 'when not given a block' do
61
- it 'should reutnr a block chaining relation object' do
62
- expect(subject.and).to be_kind_of(AST::BlockChainingRelation)
64
+ it 'should return a chaining block domain object' do
65
+ expect(subject.send(clause1)).to be_kind_of(Domain::ChainingBlock)
63
66
  end
64
- it 'should not add a child to it\'s dsl scope' do
65
- expect{ subject.and }.to_not change { subject.request.filter_query.root.children.size }
67
+ it 'should NOT add any children to the scope node' do
68
+ expect{ subject.send(clause1) }.to_not change{ root.children.size }
66
69
  end
67
70
  end
71
+ end
72
+
68
73
 
74
+ # AND
75
+ # =======================================================
76
+ describe '#and' do
77
+ it_behaves_like 'block styled clause' do
78
+ let(:klass1) { AST::And }
79
+ let(:klass2) { AST::Or }
80
+ let(:clause1) { :and! }
81
+ let(:clause2) { :or! }
82
+ end
69
83
  end
70
84
 
71
85
  # OR
72
86
  # =======================================================
73
87
  describe '#or' do
74
-
75
- it 'should create an Or node' do
76
- expect(AST::Or).to receive(:new).once
77
- subject.or
78
- end
79
-
80
- context 'when called from cloudsearch' do
81
- it 'should become a child of root node' do
82
- node = nil
83
- subject.or { node = self; }
84
- expect(subject.request.filter_query.root.children).to include(node)
85
- end
86
- it 'should return cloudsearch' do
87
- expect(subject.or {}).to eq subject
88
- end
89
- it 'should use self as the dsl scope in the block' do
90
- block = ->(scope, node) { expect(scope).to eq node }
91
- subject.and { block.call(dsl_scope, self) }
92
- end
93
- end
94
-
95
- context 'when called from inside a block' do
96
- it 'should become a child of the dsl_scope' do
97
- parent = nil
98
- child = nil
99
- subject.and { parent = self; child = or! {} }
100
- expect(parent.children).to include(child)
101
- end
102
- it 'should return the node it self' do
103
- node = AST::Or.new({})
104
- return_node = nil
105
- allow(AST::Or).to receive(:new).and_return(node)
106
- subject.and { return_node = or! {} }
107
- expect(return_node).to eq node
108
- end
88
+ it_behaves_like 'block styled clause' do
89
+ let(:klass1) { AST::Or }
90
+ let(:klass2) { AST::And }
91
+ let(:clause1) { :or! }
92
+ let(:clause2) { :and! }
109
93
  end
110
94
  end
111
95
 
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  module CloudSesame
4
4
  module Query
5
5
  module DSL
6
- describe FieldMethods do
6
+ describe FieldAccessors do
7
7
 
8
8
  # Setup Test Class
9
9
  class Product
@@ -25,6 +25,10 @@
25
25
  # class Product
26
26
  # include CloudSesame
27
27
 
28
+ # def self.greeting
29
+ # "hello world!"
30
+ # end
31
+
28
32
  # define_cloudsearch do
29
33
  # # Product CloudSesame Config
30
34
  # config.endpoint = ENV['AWS_ENDPOINT']
@@ -62,26 +66,31 @@
62
66
  # end
63
67
 
64
68
 
65
- # # n = 10_000
66
- # # q = nil
67
- # # result = RubyProf.profile do
68
- # # n.times do
69
- # q = Product.cloudsearch.query("black jacket").sort(price: :asc).page(1).size(1000).and {
69
+ # @tags = [1, 2]
70
+ # n = 10_000
71
+ # q = nil
72
+ # result = RubyProf.profile do
73
+ # n.times do
74
+ # q = Product.cloudsearch.query("black jacket").sort(price: :asc).page(1).size(1000)
75
+ # .price { gt 100 }
76
+ # .and {
70
77
  # or! {
71
- # tags "1", "2"
78
+ # tags *@tags
79
+ # tags
80
+ # tags nil
72
81
  # and! {
73
82
  # tags.not "3", "4"
74
83
  # }
75
84
  # and!.not {
76
85
  # tags.start_with "5", "6"
77
- # tags.not.start_with "7"
78
- # tags.not.near "8"
86
+ # tags.not.start_with("7")
87
+ # tags.not.near("8", distance: 7)
79
88
  # tags start_with("9"), near("10")
80
- # tags term "11"
81
- # tags phrase "12"
89
+ # tags term("11", boost: 2)
90
+ # tags.not phrase "12"
82
91
  # }
83
92
  # or!.not {
84
- # price 25..100
93
+ # price(25..100)
85
94
  # price 100...200
86
95
  # price gte(200).lt(300)
87
96
  # price gte(300)
@@ -93,30 +102,34 @@
93
102
  # }
94
103
  # }
95
104
  # }
96
- # # q.applied_filters
105
+ # q.applied_filters
97
106
 
98
- # # end
99
- # # end
100
- # # printer = RubyProf::FlatPrinter.new(result)
101
- # # printer.print(STDOUT, {})
107
+ # end
108
+ # end
109
+ # printer = RubyProf::FlatPrinter.new(result)
110
+ # printer.print(STDOUT, {})
102
111
 
103
112
  # binding.pry
104
113
 
105
- # # class TestClass
106
- # # def initialize
114
+ # # class ProductController
115
+
116
+ # # def load_user
107
117
  # # @name = "scott"
108
118
  # # end
119
+
109
120
  # # def greeting
110
121
  # # "hello world!"
111
122
  # # end
112
- # # def test_method
113
- # # local = :test
123
+
124
+ # # def search
125
+ # # load_user
114
126
  # # q = Product.cloudsearch.and {
115
127
  # # binding.pry
116
128
  # # }
117
129
  # # end
130
+
118
131
  # # end
119
132
 
120
- # # test = TestClass.new
121
- # # test.test_method
133
+ # # test = ProductController.new
134
+ # # test.search
122
135
  # end