es-elasticity 0.3.4 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b02eaa02e7e32429215a8c3156656dcb52dd2f18
4
- data.tar.gz: ad74ef063faa4c5d03fb695c95c2b2463c454d69
3
+ metadata.gz: a99e45f5ef9e625931db6d140fa43abeebb0719e
4
+ data.tar.gz: 9b8542e68c9c00ce4109c5a67c227dae68804a03
5
5
  SHA512:
6
- metadata.gz: a0aa8fe83e2d62c2503c5f925c760bd0ce32d9cf4f8388658edcf9de1bac39d9dd845237716c55bca22d22cd0007b331eb0d64779d2526c5c55cbde8e9c243c4
7
- data.tar.gz: 4027fa989f33220a9da7b2a08c2cf287cfa117e5a75db6df9571df7719237684d42931bc97fbf60ad840e2dc4005be9b5e3c91803b5e3b5beafbefb2285c2564
6
+ metadata.gz: ac65a4a90720bb4aa1887dd1f47d33e27ad623a9dfb1f0378d3578608ede383d58b85da0d1a7f5a0eaf36fa803ce52de16a98eca665efded0ab9d61bf69de289
7
+ data.tar.gz: f75cc2f3ae6c90ed308f9ead04fe8eadde0c3ec052c65cce87a56708a483966285ac0fd0c993595c487ce170b7ddba51dbbe94d0102dd9fa96825466af44d062
data/README.md CHANGED
@@ -2,16 +2,18 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.org/doximity/es-elasticity.svg)](https://travis-ci.org/doximity/es-elasticity) [![Test Coverage](https://codeclimate.com/github/doximity/es-elasticity/badges/coverage.svg)](https://codeclimate.com/github/doximity/es-elasticity) [![Code Climate](https://codeclimate.com/github/doximity/es-elasticity/badges/gpa.svg)](https://codeclimate.com/github/doximity/es-elasticity) [![Dependency Status](https://gemnasium.com/doximity/es-elasticity.svg)](https://gemnasium.com/doximity/es-elasticity)
4
4
 
5
- Elasticity provides a higher level abstraction on top of [elasticsearch-ruby](https://github.com/elasticsearch/elasticsearch-ruby) gem.
5
+ Elasticity is a model oriented approach to Elasticsearch. In simple words, a Document is represented by it's own class, similar to what ActiveRecord does for database rows.
6
6
 
7
- Mainly, it provides a model-oriented approach to Elasticsearch, similar to what [ActiveRecord](https://github.com/rails/rails/tree/master/activerecord) provides to relational databases. It leverages [ActiveModel](https://github.com/rails/rails/tree/master/activemodel) to provide a familiar format for Rails developers.
7
+ In Elasticsearch terminology, a document is an entity stored in Elasticsearch and associated to an index. Whenever a search is performed, a collection of documents is returned.
8
+
9
+ Elasticity maps those documents into objects, providing a rich object representation of a document.
8
10
 
9
11
  ## Installation
10
12
 
11
13
  Add this line to your application's Gemfile:
12
14
 
13
15
  ```ruby
14
- gem 'elasticity'
16
+ gem 'es-elasticity', require "elasticity"
15
17
  ```
16
18
 
17
19
  And then execute:
@@ -20,55 +22,74 @@ And then execute:
20
22
 
21
23
  Or install it yourself as:
22
24
 
23
- $ gem install elasticity
25
+ $ gem install es-elasticity
26
+
27
+ ## Usage
24
28
 
25
- ## Usage overview
29
+ ### Document model definition
26
30
 
27
- The first thing to do, is setup a model class for a index and document type that inherits from `Elasticity::Document`.
31
+ The first thing to do, is setup a model representing your documents. The class level represents the index, while the instance level represents each Document stored in the index. This is similar to how ActiveRecord maps tables vs rows.
28
32
 
29
33
  ```ruby
30
34
  class Search::User < Elasticity::Document
31
- # All models automatically have the id attribute but you need to define the others.
32
- attr_accessor :name, :birthdate
35
+ configure do |c|
36
+ # Defines how the index will be named, the final name
37
+ # will depend on the stragy being used.
38
+ c.index_base_name = "users"
39
+
40
+ # Defines the document type that this class represents.
41
+ c.document_type = "user"
42
+
43
+ # Select which strategy should be used. AliasIndex uses two aliases
44
+ # in order to support hot remapping of indexes. This is the recommended
45
+ # strategy.
46
+ c.strategy = Elasticity::Strategies::AliasIndex
33
47
 
34
- # Define the index mapping for the index and document type this model represents.
35
- self.mappings = {
36
- properties: {
37
- name: { type: "string" },
38
- birthdate: { type: "date" },
48
+ # Defines the mapping for this index/document_type.
49
+ c.mapping = {
50
+ properties: {
51
+ name: { type: "string" },
52
+ birthdate: { type: "date" },
53
+ }
39
54
  }
40
- }
55
+ end
41
56
 
42
57
  # Defines a search method.
43
58
  def self.adults
44
59
  date = Date.today - 21.years
45
60
 
46
- # This is the query that will be submited to ES, same format ES would expect,
47
- # translated to a Ruby hash.
61
+ # This is the query that will be submited to ES, same format ES would
62
+ # expect, translated to a Ruby hash.
48
63
  body = {
49
64
  filter: {
50
65
  { range: { birthdate: { gte: date.iso8601 }}},
51
66
  },
52
67
  }
53
68
 
54
- # Creates a search object from the body and return it. The returned object is a
55
- # lazy evaluated search that behaves like a collection, being automatically
56
- # triggered when data is iterated over.
69
+ # Creates a search object from the body and return it.
70
+ # The returned object # is a lazy evaluated search that behaves like a collection, being
71
+ # automatically triggered when data is iterated over.
57
72
  self.search(body)
58
73
  end
59
74
 
75
+ # All models automatically have the id attribute but you need to define the
76
+ # other accessors so that they can be set and get properly.
77
+ attr_accessor :name, :birthdate
78
+
60
79
  # to_document is the only required method that needs to be implemented so an
61
80
  # instance of this model can be indexed.
62
81
  def to_document
63
82
  {
64
83
  name: self.name,
65
- birthdate: self.birthdate.iso8601,
84
+ birthdate: self.birthdate.iso8601
66
85
  }
67
86
  end
68
87
  end
69
88
  ```
70
89
 
71
- Then instances of that model can be indexed pretty easily by just calling the `update` method.
90
+ ### Indexing
91
+
92
+ An instance of the model is an in-memory representation of a Document. The document can be stored on the index by calling the `update` method.
72
93
 
73
94
  ```ruby
74
95
  # Creates a new document on the index
@@ -80,7 +101,23 @@ u.name = "Jonh Jon"
80
101
  u.update
81
102
  ```
82
103
 
83
- Getting the results of a search is also pretty straightforward:
104
+ If you need to index a collection of documents, you can use `bulk_index`:
105
+
106
+ ```ruby
107
+ users = [
108
+ Search::User.new(id: 1, name: "John", birthdate: Date.civil(1985, 10, 31)),
109
+ Search::User.new(id: 2, name: "Mary", birthdate: Date.civil(1986, 9, 24)),
110
+ ]
111
+
112
+ Search::User.bulk_index(users)
113
+ ```
114
+
115
+
116
+ ### Searching
117
+
118
+ Class methods have access to the `search` method, which returns a lazy evaluated search. That means that the search will only be performed when the data is necessary, not when the `search` method is called.
119
+
120
+ The search object implements `Enumerable`, so it can be treated as a collection:
84
121
 
85
122
  ```ruby
86
123
  # Get the search object, which is an instance of `Elasticity::DocumentSearchProxy`.
@@ -91,24 +128,153 @@ adults = User.adults
91
128
  adults.each do |user|
92
129
  # do something with user
93
130
  end
131
+ ```
132
+
133
+ It also has some pretty interesting methods that affects the way the query is performed. Here is a list of available search types:
134
+
135
+ ```ruby
136
+ # Returns an array of document instances, this is the default and what the
137
+ # enumerable methods will delegate to.
138
+ adults.documents
94
139
 
95
- # Or you can also, map the results back to an ActiveRecord relation.
96
- # In this case, only the ids will be fetched.
97
- adults.active_recors(Database::User) # => Array of Database::User instances
140
+ # Returns an array of hashes representing the documents.
141
+ adults.document_hashes
142
+
143
+ # Performs the search using scan&scroll. It returns a cursor that will lazily
144
+ # fetch all the pages of the search. It can be iterated by batch/page or by
145
+ # document.
146
+ cursor = adults.scan_documents
147
+ cursor.each_batch { |batch| ... }
148
+ cursor.each { |doc| ... }
149
+
150
+ # Lastly, a search that maps back to an ActiveRecord::Relation.
151
+ adults = adults.active_record(User)
98
152
  ```
99
153
 
100
- ## Design Goals
154
+ For more information about the `active_record` method, read [ActiveRecord integration](#activerecord-integration).
155
+
156
+ ### Strategies and Hot-remapping
157
+
158
+ Strategies define how index creation and index operation happens on the lower level. Basically it define the structure that backs the document model. Currently, there are two strategies available: single-index and alias-index.
159
+
160
+ The single-index strategy is the most straightforward one. It causes one index to be created and any operation will be performed directly on that index. It's very simple but it has the downside of being a lot harder to update existing mapping since you'll have to drop the index and recreate from scratch.
161
+
162
+ The alias-index strategy is a bit more complex but it allows for seameless hot remapping. It works by creating an index and two aliases pointing to that index. Any operation is performed on the aliases rather than the index, which allows hot swapping due atomic aliases updates.
163
+
164
+ Here is what it looks like:
165
+
166
+ ```
167
+ |¯¯¯¯¯¯¯¯¯¯¯¯¯|
168
+ | MainAlias |---------|
169
+ |_____________| |------------> |¯¯¯¯¯¯¯¯¯¯¯¯¯|
170
+ | Index |
171
+ |¯¯¯¯¯¯¯¯¯¯¯¯¯| |------------> |_____________|
172
+ | UpdateAlias |---------|
173
+ |_____________|
174
+ ```
175
+
176
+ Everytime a search operation is performed, it is performed against the main alias; when an update operation is performed, it is performed against the update alias; and, when a delete operation is performed, it is performed against the indexes pointed by both aliases.
177
+
178
+ When the mapping needs to change, a hot remapping can be performed by doing the following:
101
179
 
102
- - Provide model specific for Elasticsearch documents instead of an ActiveRecord mixin;
103
- - proper separation of concerns and de-coupling;
104
- - lazy search evaluation and easy composition of multi-searches;
105
- - easy of debug;
106
- - higher level API that resembles Elasticsearch API;
180
+ 1. Create a new index with the new mapping;
181
+ 2. change the update alias to point to the new index, and change main alias to point to both indexes; at this point it will look something like this:
182
+
183
+ ```
184
+ |¯¯¯¯¯¯¯¯¯¯¯¯¯|----------------------> |¯¯¯¯¯¯¯¯¯¯¯¯¯|
185
+ | MainAlias | | Old Index |
186
+ |_____________|----------| |_____________|
187
+ |
188
+ |¯¯¯¯¯¯¯¯¯¯¯¯¯| |-----------> |¯¯¯¯¯¯¯¯¯¯¯¯¯|
189
+ | UpdateAlias |----------------------> | New Index |
190
+ |_____________| |_____________|
191
+ ```
192
+
193
+ 3. iterate over all documents on the old index, copying them to the new index;
194
+ 4. change aliases to point only to the new index;
195
+ 5. delete the old index.
196
+
197
+ This is a simplified version, there are other things that happen to ensure consistency and avoid race conditions. For full understanding see `Elasticity::Strategies::AliasIndex#remap`.
198
+
199
+ ### ActiveRecord integration
200
+
201
+ ActiveRecord integration is mainly a set of conventions rather than implementation, with the exception of one method that allows mapping documents back to a relation. Here is the list of conventions:
202
+
203
+ * have a class method on the document called `from_active_record` that creates a document object from the active record object;
204
+ * have a class method on the Document for rebuilding the index from the records;
205
+ * have an `after_save` and an `after_destroy` callbacks on the ActiveRecord model;
206
+
207
+ For example:
208
+
209
+ ```ruby
210
+ class User < ActiveRecord::Base
211
+ after_save :update_index_document
212
+ after_destroy :delete_index_document
213
+
214
+ def update_index_document
215
+ Search::User.from_active_record(self).update
216
+ end
217
+
218
+ def remove_index_document
219
+ Search::User.delete(self.id)
220
+ end
221
+ end
222
+
223
+ class Search::User < Elasticity::Document
224
+ # ... configuration
225
+
226
+ def self.from_active_record(ar)
227
+ new(name: ar.name, birthdate: ar.birthdate)
228
+ end
229
+
230
+ def self.rebuild_index
231
+ self.recreate_index
232
+
233
+ User.find_in_batches do |batch|
234
+ documents = batch.map { |record| from_active_record(record) }
235
+ self.bulk_index(documents)
236
+ end
237
+ end
238
+ end
239
+ ```
240
+
241
+ This makes the code very clear in intent, easier to see when and how things happen and under the developer control, keeping both parts very decoupled.
242
+
243
+ The only ActiveRecord specific utility this library have is a way to lazily map a Elasticsearch search to an ActiveRecord relation.
244
+
245
+ To extend on the previous example, imagine the `Search::User` class also have the following simple search method.
246
+
247
+ ```ruby
248
+ def self.adults
249
+ date = Date.today - 21.years
250
+
251
+ body = {
252
+ filter: {
253
+ { range: { birthdate: { gte: date.iso8601 }}},
254
+ },
255
+ }
256
+
257
+ self.search(body)
258
+ end
259
+ ```
260
+
261
+ Because the return of that method is a lazy-evaluated search, it allows specific search strategies to be used, one of them being ActiveRecord specific:
262
+
263
+ ```ruby
264
+ adults = Search::User.adults.active_record(User)
265
+ adults.class # => ActiveRecord::Relation
266
+ adults.all # => [#<User: id: 1, name: "John", birthdate: 1985-10-31>, ...]
267
+ ```
268
+
269
+ Note that the method takes a relation and not a class, so the following is also possible:
270
+
271
+ ```ruby
272
+ Search::User.adults.active_record(User.where(active: true))
273
+ ```
107
274
 
108
275
  ## Roadmap
109
276
 
110
- - [x] Index aliasing support
111
- - [x] Index hot swapping support
277
+ - [ ] Make Elasticity::Strategies::AliasIndex the default
112
278
  - [ ] Use mapping instead of mappings, we wanna be consistent to ES not to elasticsearch-ruby
113
279
  - [ ] Define from_active_record interface
114
280
  - [ ] Write more detailed documentation section for:
@@ -91,6 +91,10 @@ module Elasticity
91
91
  response["hits"]["total"]
92
92
  end
93
93
 
94
+ def aggregations
95
+ response["aggregations"] ||= {}
96
+ end
97
+
94
98
  def suggestions
95
99
  response["hits"]["suggest"] ||= {}
96
100
  end
@@ -1,3 +1,3 @@
1
1
  module Elasticity
2
- VERSION = "0.3.4"
2
+ VERSION = "0.3.5"
3
3
  end
@@ -13,6 +13,30 @@ RSpec.describe "Search" do
13
13
  ]}}
14
14
  end
15
15
 
16
+ let :aggregations do
17
+ {
18
+ "logins_count" => { "value" => 1495 },
19
+ "gender" => {
20
+ "buckets" => [
21
+ {
22
+ "doc_count" => 100,
23
+ "key" => "M"
24
+ },
25
+ {
26
+ "doc_count" => 100,
27
+ "key" => "F"
28
+ }
29
+ ],
30
+ "doc_count_error_upper_bound" => 0,
31
+ "sum_other_doc_count" => 0
32
+ }
33
+ }
34
+ end
35
+
36
+ let :full_response_with_aggregations do
37
+ full_response.merge("aggregations" => aggregations)
38
+ end
39
+
16
40
  let :ids_response do
17
41
  { "hits" => { "total" => 2, "hits" => [
18
42
  { "_id" => 1 },
@@ -74,6 +98,13 @@ RSpec.describe "Search" do
74
98
  expect(Array(docs)).to eq expected
75
99
  end
76
100
 
101
+ it "searches and the index returns aggregations" do
102
+ expect(client).to receive(:search).with(index: index_name, type: document_type, body: body).and_return(full_response_with_aggregations)
103
+
104
+ docs = subject.documents(klass)
105
+ expect(docs.aggregations).to eq aggregations
106
+ end
107
+
77
108
  it "searches using scan&scroll" do
78
109
  expect(client).to receive(:search).with(index: index_name, type: document_type, body: body, search_type: "scan", size: 100, scroll: "1m").and_return(scan_response)
79
110
  expect(client).to receive(:scroll).with(scroll_id: "abc123", scroll: "1m").and_return(scroll_response)
metadata CHANGED
@@ -1,167 +1,167 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: es-elasticity
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rodrigo Kochenburger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-20 00:00:00.000000000 Z
11
+ date: 2015-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.7'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.7'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '10.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: 3.1.0
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 3.1.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: simplecov
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: 0.7.1
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 0.7.1
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: oj
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: pry
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '>='
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '>='
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: codeclimate-test-reporter
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - '>='
101
+ - - ">="
102
102
  - !ruby/object:Gem::Version
103
103
  version: '0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - '>='
108
+ - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: redis
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - '>='
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
117
  version: '0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - '>='
122
+ - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: activesupport
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - ~>
129
+ - - "~>"
130
130
  - !ruby/object:Gem::Version
131
131
  version: '4.0'
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - ~>
136
+ - - "~>"
137
137
  - !ruby/object:Gem::Version
138
138
  version: '4.0'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: activemodel
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - ~>
143
+ - - "~>"
144
144
  - !ruby/object:Gem::Version
145
145
  version: '4.0'
146
146
  type: :runtime
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - ~>
150
+ - - "~>"
151
151
  - !ruby/object:Gem::Version
152
152
  version: '4.0'
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: elasticsearch
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
- - - ~>
157
+ - - "~>"
158
158
  - !ruby/object:Gem::Version
159
159
  version: 1.0.5
160
160
  type: :runtime
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
- - - ~>
164
+ - - "~>"
165
165
  - !ruby/object:Gem::Version
166
166
  version: 1.0.5
167
167
  description: Elasticity provides a higher level abstraction on top of [elasticsearch-ruby](https://github.com/elasticsearch/elasticsearch-ruby)
@@ -172,10 +172,10 @@ executables: []
172
172
  extensions: []
173
173
  extra_rdoc_files: []
174
174
  files:
175
- - .gitignore
176
- - .rspec
177
- - .simplecov
178
- - .travis.yml
175
+ - ".gitignore"
176
+ - ".rspec"
177
+ - ".simplecov"
178
+ - ".travis.yml"
179
179
  - Gemfile
180
180
  - LICENSE.txt
181
181
  - README.md
@@ -212,17 +212,17 @@ require_paths:
212
212
  - lib
213
213
  required_ruby_version: !ruby/object:Gem::Requirement
214
214
  requirements:
215
- - - '>='
215
+ - - ">="
216
216
  - !ruby/object:Gem::Version
217
217
  version: '0'
218
218
  required_rubygems_version: !ruby/object:Gem::Requirement
219
219
  requirements:
220
- - - '>='
220
+ - - ">="
221
221
  - !ruby/object:Gem::Version
222
222
  version: '0'
223
223
  requirements: []
224
224
  rubyforge_project:
225
- rubygems_version: 2.0.0
225
+ rubygems_version: 2.2.2
226
226
  signing_key:
227
227
  specification_version: 4
228
228
  summary: ActiveModel-based library for working with Elasticsearch
@@ -233,4 +233,3 @@ test_files:
233
233
  - spec/units/multi_search_spec.rb
234
234
  - spec/units/search_spec.rb
235
235
  - spec/units/strategies/single_index_spec.rb
236
- has_rdoc: