elasticsearch-model 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -95,6 +95,18 @@ if ENV["MONGODB_AVAILABLE"]
95
95
  end
96
96
  end
97
97
 
98
+ should "preserve the search results order for records" do
99
+ response = MongoidArticle.search('title:code')
100
+
101
+ response.records.each_with_hit do |r, h|
102
+ assert_equal h._id, r.id.to_s
103
+ end
104
+
105
+ response.records.map_with_hit do |r, h|
106
+ assert_equal h._id, r.id.to_s
107
+ end
108
+ end
109
+
98
110
  should "remove document from index on destroy" do
99
111
  article = MongoidArticle.first
100
112
 
@@ -82,13 +82,42 @@ class Elasticsearch::Model::AdapterActiveRecordTest < Test::Unit::TestCase
82
82
  end
83
83
 
84
84
  context "Importing" do
85
+ setup do
86
+ DummyClassForActiveRecord.__send__ :extend, Elasticsearch::Model::Adapter::ActiveRecord::Importing
87
+ end
88
+
89
+ should "raise an exception when passing an invalid scope" do
90
+ assert_raise NoMethodError do
91
+ DummyClassForActiveRecord.__find_in_batches(scope: :not_found_method) do; end
92
+ end
93
+ end
94
+
85
95
  should "implement the __find_in_batches method" do
86
96
  DummyClassForActiveRecord.expects(:find_in_batches).returns([])
87
-
88
- DummyClassForActiveRecord.__send__ :extend, Elasticsearch::Model::Adapter::ActiveRecord::Importing
89
97
  DummyClassForActiveRecord.__find_in_batches do; end
90
98
  end
91
- end
92
99
 
100
+ should "limit the relation to a specific scope" do
101
+ DummyClassForActiveRecord.expects(:find_in_batches).returns([])
102
+ DummyClassForActiveRecord.expects(:published).returns(DummyClassForActiveRecord)
103
+
104
+ DummyClassForActiveRecord.__find_in_batches(scope: :published) do; end
105
+ end
106
+
107
+ context "when transforming models" do
108
+ setup do
109
+ @transform = DummyClassForActiveRecord.__transform
110
+ end
111
+
112
+ should "provide an object that responds to #call" do
113
+ assert_respond_to @transform, :call
114
+ end
115
+
116
+ should "provide default transformation" do
117
+ model = mock("model", id: 1, __elasticsearch__: stub(as_indexed_json: {}))
118
+ assert_equal @transform.call(model), { index: { _id: 1, data: {} } }
119
+ end
120
+ end
121
+ end
93
122
  end
94
123
  end
@@ -19,11 +19,21 @@ class Elasticsearch::Model::AdapterDefaultTest < Test::Unit::TestCase
19
19
  assert_instance_of Module, Elasticsearch::Model::Adapter::Default::Callbacks
20
20
  end
21
21
 
22
- should "have the default Importing implementation" do
23
- DummyClassForDefaultAdapter.__send__ :include, Elasticsearch::Model::Adapter::Default::Importing
22
+ context "concerning abstract methods" do
23
+ setup do
24
+ DummyClassForDefaultAdapter.__send__ :include, Elasticsearch::Model::Adapter::Default::Importing
25
+ end
26
+
27
+ should "have the default Importing implementation" do
28
+ assert_raise Elasticsearch::Model::NotImplemented do
29
+ DummyClassForDefaultAdapter.new.__find_in_batches
30
+ end
31
+ end
24
32
 
25
- assert_raise Elasticsearch::Model::NotImplemented do
26
- DummyClassForDefaultAdapter.new.__find_in_batches
33
+ should "have the default transform implementation" do
34
+ assert_raise Elasticsearch::Model::NotImplemented do
35
+ DummyClassForDefaultAdapter.new.__transform
36
+ end
27
37
  end
28
38
  end
29
39
 
@@ -81,6 +81,21 @@ class Elasticsearch::Model::AdapterMongoidTest < Test::Unit::TestCase
81
81
  DummyClassForMongoid.__send__ :extend, Elasticsearch::Model::Adapter::Mongoid::Importing
82
82
  DummyClassForMongoid.__find_in_batches do; end
83
83
  end
84
+
85
+ context "when transforming models" do
86
+ setup do
87
+ @transform = DummyClassForMongoid.__transform
88
+ end
89
+
90
+ should "provide an object that responds to #call" do
91
+ assert_respond_to @transform, :call
92
+ end
93
+
94
+ should "provide basic transformation" do
95
+ model = mock("model", id: 1, as_indexed_json: {})
96
+ assert_equal @transform.call(model), { index: { _id: "1", data: {} } }
97
+ end
98
+ end
84
99
  end
85
100
 
86
101
  end
@@ -10,6 +10,9 @@ class Elasticsearch::Model::ImportingTest < Test::Unit::TestCase
10
10
  def __find_in_batches(options={}, &block)
11
11
  yield if block_given?
12
12
  end
13
+ def __transform
14
+ lambda {|a|}
15
+ end
13
16
  end
14
17
 
15
18
  def importing_mixin
@@ -41,7 +44,7 @@ class Elasticsearch::Model::ImportingTest < Test::Unit::TestCase
41
44
  DummyImportingModel.expects(:client).returns(client)
42
45
  DummyImportingModel.expects(:index_name).returns('foo')
43
46
  DummyImportingModel.expects(:document_type).returns('foo')
44
-
47
+ DummyImportingModel.stubs(:__batch_to_bulk)
45
48
  assert_equal 0, DummyImportingModel.import
46
49
  end
47
50
 
@@ -58,6 +61,7 @@ class Elasticsearch::Model::ImportingTest < Test::Unit::TestCase
58
61
  DummyImportingModel.stubs(:client).returns(client)
59
62
  DummyImportingModel.stubs(:index_name).returns('foo')
60
63
  DummyImportingModel.stubs(:document_type).returns('foo')
64
+ DummyImportingModel.stubs(:__batch_to_bulk)
61
65
 
62
66
  assert_equal 1, DummyImportingModel.import
63
67
  end
@@ -75,6 +79,7 @@ class Elasticsearch::Model::ImportingTest < Test::Unit::TestCase
75
79
  DummyImportingModel.stubs(:client).returns(client)
76
80
  DummyImportingModel.stubs(:index_name).returns('foo')
77
81
  DummyImportingModel.stubs(:document_type).returns('foo')
82
+ DummyImportingModel.stubs(:__batch_to_bulk)
78
83
 
79
84
  DummyImportingModel.import do |response|
80
85
  assert_equal 2, response['items'].size
@@ -116,8 +121,36 @@ class Elasticsearch::Model::ImportingTest < Test::Unit::TestCase
116
121
  .returns({'items' => [ {'index' => {} }]})
117
122
 
118
123
  DummyImportingModel.stubs(:client).returns(client)
124
+ DummyImportingModel.stubs(:__batch_to_bulk)
119
125
 
120
126
  DummyImportingModel.import index: 'my-new-index', type: 'my-other-type'
121
127
  end
128
+
129
+ should "use the default transform from adapter" do
130
+ client = mock('client', bulk: {'items' => []})
131
+ transform = lambda {|a|}
132
+
133
+ DummyImportingModel.stubs(:client).returns(client)
134
+ DummyImportingModel.expects(:__transform).returns(transform)
135
+ DummyImportingModel.expects(:__batch_to_bulk).with(anything, transform)
136
+
137
+ DummyImportingModel.import index: 'foo', type: 'bar'
138
+ end
139
+
140
+ should "use the transformer from options" do
141
+ client = mock('client', bulk: {'items' => []})
142
+ transform = lambda {|a|}
143
+
144
+ DummyImportingModel.stubs(:client).returns(client)
145
+ DummyImportingModel.expects(:__batch_to_bulk).with(anything, transform)
146
+
147
+ DummyImportingModel.import index: 'foo', type: 'bar', transform: transform
148
+ end
149
+
150
+ should "raise an ArgumentError if transform doesn't respond to the call method" do
151
+ assert_raise ArgumentError do
152
+ DummyImportingModel.import index: 'foo', type: 'bar', transform: "not_callable"
153
+ end
154
+ end
122
155
  end
123
156
  end
@@ -47,6 +47,12 @@ class Elasticsearch::Model::IndexingTest < Test::Unit::TestCase
47
47
  assert_instance_of Elasticsearch::Model::Indexing::Mappings, DummyIndexingModel.mappings
48
48
  end
49
49
 
50
+ should "raise an exception when not passed type" do
51
+ assert_raise ArgumentError do
52
+ Elasticsearch::Model::Indexing::Mappings.new
53
+ end
54
+ end
55
+
50
56
  should "be convertible to hash" do
51
57
  mappings = Elasticsearch::Model::Indexing::Mappings.new :mytype, { foo: 'bar' }
52
58
  assert_equal( { :mytype => { foo: 'bar', :properties => {} } }, mappings.to_hash )
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class Elasticsearch::Model::ResponsePaginationTest < Test::Unit::TestCase
3
+ class Elasticsearch::Model::ResponsePaginationKaminariTest < Test::Unit::TestCase
4
4
  context "Response pagination" do
5
5
  class ModelClass
6
6
  include ::Kaminari::ConfigurationMethods
@@ -0,0 +1,189 @@
1
+ require 'test_helper'
2
+ require 'will_paginate'
3
+ require 'will_paginate/collection'
4
+
5
+ class Elasticsearch::Model::ResponsePaginationWillPaginateTest < Test::Unit::TestCase
6
+ context "Response pagination" do
7
+ class ModelClass
8
+ def self.index_name; 'foo'; end
9
+ def self.document_type; 'bar'; end
10
+
11
+ # WillPaginate adds this method to models (see WillPaginate::PerPage module)
12
+ def self.per_page
13
+ 33
14
+ end
15
+ end
16
+
17
+ # Subsclass Response so we can include WillPaginate module without conflicts with Kaminari.
18
+ class WillPaginateResponse < Elasticsearch::Model::Response::Response
19
+ include Elasticsearch::Model::Response::Pagination::WillPaginate
20
+ end
21
+
22
+ RESPONSE = { 'took' => '5', 'timed_out' => false, '_shards' => {'one' => 'OK'},
23
+ 'hits' => { 'total' => 100, 'hits' => (1..100).to_a.map { |i| { _id: i } } } }
24
+
25
+ setup do
26
+ @search = Elasticsearch::Model::Searching::SearchRequest.new ModelClass, '*'
27
+ @response = WillPaginateResponse.new ModelClass, @search, RESPONSE
28
+ @response.klass.stubs(:client).returns mock('client')
29
+
30
+ @expected_methods = [
31
+ # methods needed by WillPaginate::CollectionMethods
32
+ :current_page,
33
+ :per_page,
34
+ :total_entries,
35
+
36
+ # methods defined by WillPaginate::CollectionMethods
37
+ :total_pages,
38
+ :previous_page,
39
+ :next_page,
40
+ :out_of_bounds?,
41
+ ]
42
+ end
43
+
44
+ should "have pagination methods" do
45
+ assert_respond_to @response, :paginate
46
+
47
+ @expected_methods.each do |method|
48
+ assert_respond_to @response, method
49
+ end
50
+ end
51
+
52
+ context "response.results" do
53
+ should "have pagination methods" do
54
+ @expected_methods.each do |method|
55
+ assert_respond_to @response.results, method
56
+ end
57
+ end
58
+ end
59
+
60
+ context "response.records" do
61
+ should "have pagination methods" do
62
+ @expected_methods.each do |method|
63
+ @response.klass.stubs(:find).returns([])
64
+ assert_respond_to @response.records, method
65
+ end
66
+ end
67
+ end
68
+
69
+ context "#paginate method" do
70
+ should "set from/size using defaults" do
71
+ @response.klass.client
72
+ .expects(:search)
73
+ .with do |definition|
74
+ assert_equal 0, definition[:from]
75
+ assert_equal 33, definition[:size]
76
+ end
77
+ .returns(RESPONSE)
78
+
79
+ assert_nil @response.search.definition[:from]
80
+ assert_nil @response.search.definition[:size]
81
+
82
+ @response.paginate(page: nil).to_a
83
+ assert_equal 0, @response.search.definition[:from]
84
+ assert_equal 33, @response.search.definition[:size]
85
+ end
86
+
87
+ should "set from/size using default per_page" do
88
+ @response.klass.client
89
+ .expects(:search)
90
+ .with do |definition|
91
+ assert_equal 33, definition[:from]
92
+ assert_equal 33, definition[:size]
93
+ end
94
+ .returns(RESPONSE)
95
+
96
+ assert_nil @response.search.definition[:from]
97
+ assert_nil @response.search.definition[:size]
98
+
99
+ @response.paginate(page: 2).to_a
100
+ assert_equal 33, @response.search.definition[:from]
101
+ assert_equal 33, @response.search.definition[:size]
102
+ end
103
+
104
+ should "set from/size using custom page and per_page" do
105
+ @response.klass.client
106
+ .expects(:search)
107
+ .with do |definition|
108
+ assert_equal 18, definition[:from]
109
+ assert_equal 9, definition[:size]
110
+ end
111
+ .returns(RESPONSE)
112
+
113
+ assert_nil @response.search.definition[:from]
114
+ assert_nil @response.search.definition[:size]
115
+
116
+ @response.paginate(page: 3, per_page: 9).to_a
117
+ assert_equal 18, @response.search.definition[:from]
118
+ assert_equal 9, @response.search.definition[:size]
119
+ end
120
+
121
+ should "searches for page 1 if specified page is < 1" do
122
+ @response.klass.client
123
+ .expects(:search)
124
+ .with do |definition|
125
+ assert_equal 0, definition[:from]
126
+ assert_equal 33, definition[:size]
127
+ end
128
+ .returns(RESPONSE)
129
+
130
+ assert_nil @response.search.definition[:from]
131
+ assert_nil @response.search.definition[:size]
132
+
133
+ @response.paginate(page: "-1").to_a
134
+ assert_equal 0, @response.search.definition[:from]
135
+ assert_equal 33, @response.search.definition[:size]
136
+ end
137
+ end
138
+
139
+ context "#page and #per_page shorthand methods" do
140
+ should "set from/size using default per_page" do
141
+ @response.page(5)
142
+ assert_equal 132, @response.search.definition[:from]
143
+ assert_equal 33, @response.search.definition[:size]
144
+ end
145
+
146
+ should "set from/size when calling #page then #per_page" do
147
+ @response.page(5).per_page(3)
148
+ assert_equal 12, @response.search.definition[:from]
149
+ assert_equal 3, @response.search.definition[:size]
150
+ end
151
+
152
+ should "set from/size when calling #per_page then #page" do
153
+ @response.per_page(3).page(5)
154
+ assert_equal 12, @response.search.definition[:from]
155
+ assert_equal 3, @response.search.definition[:size]
156
+ end
157
+ end
158
+
159
+ context "#current_page method" do
160
+ should "return 1 by default" do
161
+ @response.paginate({})
162
+ assert_equal 1, @response.current_page
163
+ end
164
+
165
+ should "return current page number" do
166
+ @response.paginate(page: 3, per_page: 9)
167
+ assert_equal 3, @response.current_page
168
+ end
169
+
170
+ should "return nil if not pagination set" do
171
+ assert_equal nil, @response.current_page
172
+ end
173
+ end
174
+
175
+ context "#per_page method" do
176
+ should "return value set in paginate call" do
177
+ @response.paginate(per_page: 8)
178
+ assert_equal 8, @response.per_page
179
+ end
180
+ end
181
+
182
+ context "#total_entries method" do
183
+ should "return total from response" do
184
+ @response.expects(:results).returns(mock('results', total: 100))
185
+ assert_equal 100, @response.total_entries
186
+ end
187
+ end
188
+ end
189
+ end
@@ -15,6 +15,20 @@ class Elasticsearch::Model::ResultTest < Test::Unit::TestCase
15
15
  assert_raise(NoMethodError) { result.xoxo }
16
16
  end
17
17
 
18
+ should "return _id as #id" do
19
+ result = Elasticsearch::Model::Response::Result.new foo: 'bar', _id: 42, _source: { id: 12 }
20
+
21
+ assert_equal 42, result.id
22
+ assert_equal 12, result._source.id
23
+ end
24
+
25
+ should "return _type as #type" do
26
+ result = Elasticsearch::Model::Response::Result.new foo: 'bar', _type: 'baz', _source: { type: 'BAM' }
27
+
28
+ assert_equal 'baz', result.type
29
+ assert_equal 'BAM', result._source.type
30
+ end
31
+
18
32
  should "delegate method calls to `_source` when available" do
19
33
  result = Elasticsearch::Model::Response::Result.new foo: 'bar', _source: { bar: 'baz' }
20
34
 
@@ -27,12 +41,27 @@ class Elasticsearch::Model::ResultTest < Test::Unit::TestCase
27
41
  assert_equal 'baz', result.bar
28
42
  end
29
43
 
44
+ should "delegate existence method calls to `_source`" do
45
+ result = Elasticsearch::Model::Response::Result.new foo: 'bar', _source: { bar: { bam: 'baz' } }
46
+
47
+ assert_respond_to result._source, :bar?
48
+ assert_respond_to result, :bar?
49
+
50
+ assert_equal true, result._source.bar?
51
+ assert_equal true, result.bar?
52
+ assert_equal false, result.boo?
53
+
54
+ assert_equal true, result.bar.bam?
55
+ assert_equal false, result.bar.boo?
56
+ end
57
+
30
58
  should "delegate methods to @result" do
31
59
  result = Elasticsearch::Model::Response::Result.new foo: 'bar'
32
60
 
33
- assert_equal 'bar', result.foo
34
- assert_equal 'bar', result.fetch('foo')
35
- assert_equal 'moo', result.fetch('NOT_EXIST', 'moo')
61
+ assert_equal 'bar', result.foo
62
+ assert_equal 'bar', result.fetch('foo')
63
+ assert_equal 'moo', result.fetch('NOT_EXIST', 'moo')
64
+ assert_equal ['foo'], result.keys
36
65
 
37
66
  assert_respond_to result, :to_hash
38
67
  assert_equal({'foo' => 'bar'}, result.to_hash)
@@ -40,6 +69,16 @@ class Elasticsearch::Model::ResultTest < Test::Unit::TestCase
40
69
  assert_raise(NoMethodError) { result.does_not_exist }
41
70
  end
42
71
 
72
+ should "delegate existence method calls to @result" do
73
+ result = Elasticsearch::Model::Response::Result.new foo: 'bar', _source: { bar: 'bam' }
74
+ assert_respond_to result, :foo?
75
+
76
+ assert_equal true, result.foo?
77
+ assert_equal false, result.boo?
78
+ assert_equal false, result._source.foo?
79
+ assert_equal false, result._source.boo?
80
+ end
81
+
43
82
  should "delegate as_json to @result even when ActiveSupport changed half of Ruby" do
44
83
  require 'active_support/json/encoding'
45
84
  result = Elasticsearch::Model::Response::Result.new foo: 'bar'
@@ -47,6 +86,5 @@ class Elasticsearch::Model::ResultTest < Test::Unit::TestCase
47
86
  result.instance_variable_get(:@result).expects(:as_json)
48
87
  result.as_json(except: 'foo')
49
88
  end
50
-
51
89
  end
52
90
  end