search_flip 3.4.0 → 4.0.0.beta

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
  SHA256:
3
- metadata.gz: 6722b210d8b3d0baa98e3370f26e2f293a21ea7db15dd08ba47deb2a1dba4e1c
4
- data.tar.gz: a66d9f5482e06ae11cffeece148a8eb290523ee6ec4c91f510c1258b1c780225
3
+ metadata.gz: b023bc6411647eaecfcb8f5b0fe535379974a0824d49699dd74ef867a67c69eb
4
+ data.tar.gz: 5dc4a0439f9442811f3966e86b0c6b09d09c54450a04234c3738ae0ab7935900
5
5
  SHA512:
6
- metadata.gz: 4e60dbae8d1bf0c4be3964bd0daf0740c4dd89827d61481d21960af17f34b237b512dde09f08111949d9b728bc3290c59a535930e168aaa562c30c9f74faa841
7
- data.tar.gz: 3b7d941dee59924dc47b486e5cd3d88af8a3a9a42e8f6952e14934087e2a0acbe0014ee09caabec373640c35c5ae1d72a433e2100fcd2257e8d920c09f39e3b6
6
+ metadata.gz: a5fc637e8c016531df22af678adcae60a4f4169e5f1d2215d52be0a0dff1111b849cb4d79ca36d6cbf315c8516bc51d543852ab5026339d59cb1f5d08ba356f7
7
+ data.tar.gz: 7cf9d55a9aca5d6d63401750d40bc656fcc345101d8ce92a300c24649e38810d399d43ff225611bbdd91a257d6cb15eee26a6c811974b987e92e72e67eded704
@@ -11,11 +11,11 @@ jobs:
11
11
  - elasticsearch:5.4
12
12
  - docker.elastic.co/elasticsearch/elasticsearch:6.7.0
13
13
  - docker.elastic.co/elasticsearch/elasticsearch:7.0.0
14
- - docker.elastic.co/elasticsearch/elasticsearch:7.11.2
14
+ - docker.elastic.co/elasticsearch/elasticsearch:7.9.0
15
15
  ruby:
16
+ - 2.5
16
17
  - 2.6
17
18
  - 2.7
18
- - 3.0
19
19
  services:
20
20
  elasticsearch:
21
21
  image: ${{ matrix.elasticsearch }}
@@ -28,7 +28,6 @@ jobs:
28
28
  - uses: actions/setup-ruby@v1
29
29
  with:
30
30
  ruby-version: ${{ matrix.ruby }}
31
- - run: gem install bundler
32
31
  - run: bundle
33
32
  - run: sleep 10
34
33
  - run: bundle exec rspec
data/.rubocop.yml CHANGED
@@ -1,14 +1,13 @@
1
1
  AllCops:
2
2
  NewCops: enable
3
- TargetRubyVersion: 2.5
4
- SuggestExtensions: false
5
-
6
- Layout/EmptyLineBetweenDefs:
7
- EmptyLineBetweenClassDefs: false
3
+ TargetRubyVersion: 2.4
8
4
 
9
5
  Gemspec/RequiredRubyVersion:
10
6
  Enabled: false
11
7
 
8
+ Style/CaseLikeIf:
9
+ Enabled: false
10
+
12
11
  Style/ExplicitBlockArgument:
13
12
  Enabled: false
14
13
 
data/CHANGELOG.md CHANGED
@@ -1,24 +1,13 @@
1
1
 
2
2
  # CHANGELOG
3
3
 
4
- ## v3.4.0
4
+ ## v4.0.0
5
5
 
6
- * Expose `Http#timeout` via `SearchFlip::HTTPClient`
7
-
8
- ## v3.3.0
9
-
10
- * Update httprb
11
- * Changed oj default options
12
- * Allow to set oj json options
13
-
14
- ## v3.2.1
15
-
16
- * Fix `refresh` having a empty body breaking in elasticsearch 7.11
17
-
18
- ## v3.2.0
19
-
20
- * Fix `index_scope` not being passed in `each_record` without block
21
- * Added `SearchFlip::Criteria#match_none`
6
+ * [BREAKING] For performance reasons, `SearchFlip::Result` now no longer
7
+ inherits `Hashie::Mash`
8
+ * It no longer supports symbol based access like `result[:id]`
9
+ * It no longer supports question mark methods like `result.title?`
10
+ * It no longer supports method based assignment like `result.some_key = "value"`
22
11
 
23
12
  ## v3.1.2
24
13
 
data/README.md CHANGED
@@ -51,7 +51,7 @@ CommentIndex.search("hello world").where(available: true).sort(id: "desc").aggre
51
51
 
52
52
  ```
53
53
 
54
- Finally, SearchFlip comes with a minimal set of dependencies.
54
+ Finally, SearchFlip comes with a minimal set of dependencies (http-rb and oj only).
55
55
 
56
56
  ## Reference Docs
57
57
 
@@ -418,14 +418,6 @@ Simply matches all documents:
418
418
  CommentIndex.match_all
419
419
  ```
420
420
 
421
- * `match_none`
422
-
423
- Simply matches none documents at all:
424
-
425
- ```ruby
426
- CommentIndex.match_none
427
- ```
428
-
429
421
  * `all`
430
422
 
431
423
  Simply returns the criteria as is or an empty criteria when called on the index
@@ -482,8 +474,8 @@ end
482
474
  ```
483
475
 
484
476
  Generally, aggregation results returned by Elasticsearch are returned as a
485
- `SearchFlip::Result`, which basically is a `Hashie::Mash`, such that you can
486
- access them via:
477
+ `SearchFlip::Result`, which basically is a Hash with method-like access, such
478
+ that you can access them via:
487
479
 
488
480
  ```ruby
489
481
  query.aggregations(:username)["mrkamel"].revenue.value
@@ -756,7 +748,7 @@ end
756
748
  This allows to use different clusters per index e.g. when migrating indices to
757
749
  new versions of Elasticsearch.
758
750
 
759
- You can specify basic auth, additional headers, request timeouts, etc via:
751
+ You can specify basic auth, additional headers, etc via:
760
752
 
761
753
  ```ruby
762
754
  http_client = SearchFlip::HTTPClient.new
@@ -773,9 +765,6 @@ http_client = http_client.via("proxy.host", 8080)
773
765
  # Custom headers
774
766
  http_client = http_client.headers(key: "value")
775
767
 
776
- # Timeouts
777
- http_client = http_client.timeout(20)
778
-
779
768
  SearchFlip::Connection.new(base_url: "...", http_client: http_client)
780
769
  ```
781
770
 
@@ -885,52 +874,57 @@ Thus, if your ORM supports `.find_each`, `#id` and `#where` you are already
885
874
  good to go. Otherwise, simply add your custom implementation of those methods
886
875
  that work with whatever ORM you use.
887
876
 
888
- ## JSON
877
+ ## Date and Timestamps in JSON
889
878
 
890
- SearchFlip is using the [Oj gem](https://github.com/ohler55/oj) to generate
891
- JSON. More concretely, SearchFlip is using:
879
+ Elasticsearch requires dates and timestamps to have one of the formats listed
880
+ here: [https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#strict-date-time](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#strict-date-time).
881
+
882
+ However, `JSON.generate` in ruby by default outputs something like:
892
883
 
893
884
  ```ruby
894
- Oj.dump({ key: "value" }, mode: :custom, use_to_json: true, time_format: :xmlschema, bigdecimal_as_decimal: false)
885
+ JSON.generate(time: Time.now.utc)
886
+ # => "{\"time\":\"2018-02-22 18:19:33 UTC\"}"
895
887
  ```
896
888
 
897
- The `use_to_json` option is used for maximum compatibility, most importantly
898
- when using rails `ActiveSupport::TimeWithZone` timestamps, which `oj` can not
899
- serialize natively. However, `use_to_json` adds performance overhead. You can
900
- change the json options via:
889
+ This format is not compatible with Elasticsearch by default. If you're on
890
+ Rails, ActiveSupport adds its own `#to_json` methods to `Time`, `Date`, etc.
891
+ However, ActiveSupport checks whether they are used in combination with
892
+ `JSON.generate` or not and adapt:
901
893
 
902
894
  ```ruby
903
- SearchFlip::Config[:json_options] = {
904
- mode: :custom,
905
- use_to_json: false,
906
- time_format: :xmlschema,
907
- bigdecimal_as_decimal: false
908
- }
895
+ Time.now.utc.to_json
896
+ => "\"2018-02-22T18:18:22.088Z\""
897
+
898
+ JSON.generate(time: Time.now.utc)
899
+ => "{\"time\":\"2018-02-22 18:18:59 UTC\"}"
909
900
  ```
910
901
 
911
- However, you then have to convert timestamps manually for indexation via e.g.:
902
+ SearchFlip is using the [Oj gem](https://github.com/ohler55/oj) to generate
903
+ JSON. More concretely, SearchFlip is using:
912
904
 
913
905
  ```ruby
914
- class MyIndex
915
- # ...
906
+ Oj.dump({ key: "value" }, mode: :custom, use_to_json: true)
907
+ ```
916
908
 
917
- def self.serialize(model)
918
- {
919
- # ...
909
+ This mitigates the issues if you're on Rails:
920
910
 
921
- created_at: model.created_at.to_time
922
- }
923
- end
924
- end
911
+ ```ruby
912
+ Oj.dump(Time.now, mode: :custom, use_to_json: true)
913
+ # => "\"2018-02-22T18:21:21.064Z\""
925
914
  ```
926
915
 
927
- Please check out the oj docs for more details.
916
+ However, if you're not on Rails, you need to add `#to_json` methods to `Time`,
917
+ `Date` and `DateTime` to get proper serialization. You can either add them on
918
+ your own, via other libraries or by simply using:
919
+
920
+ ```ruby
921
+ require "search_flip/to_json"
922
+ ```
928
923
 
929
924
  ## Feature Support
930
925
 
931
926
  * for Elasticsearch 2.x, the delete-by-query plugin is required to delete
932
927
  records via queries
933
- * `#match_none` is only available with Elasticsearch >= 5
934
928
  * `#track_total_hits` is only available with Elasticsearch >= 7
935
929
 
936
930
  ## Keeping your Models and Indices in Sync
data/UPDATING.md CHANGED
@@ -1,6 +1,46 @@
1
1
 
2
2
  # Updating from previous SearchFlip versions
3
3
 
4
+ ## Update 3.x to 4.x
5
+
6
+ **[BREAKING]** For performance reasons, `SearchFlip::Result` no longer
7
+ inherits `Hashie::Mash`
8
+
9
+ * It no longer supports symbol based access like `result[:id]`
10
+
11
+ 2.x:
12
+
13
+ ```ruby
14
+ CommentIndex.match_all.results.first[:id]
15
+ CommentIndex.aggregate(:tags).aggregations(:tags).values.first[:doc_count]
16
+ ```
17
+
18
+ 3.x
19
+
20
+ ```ruby
21
+ CommentIndex.match_all.results.first["id"] # or .id
22
+ CommentIndex.aggregate(:tags).aggregations(:tags).values.first["doc_count"] # or .doc_count
23
+ ```
24
+
25
+ * It no longer supports question mark methods like `result.title?`
26
+
27
+ 2.x:
28
+
29
+ ```ruby
30
+ CommentIndex.match_all.results.first.is_published?
31
+ ```
32
+
33
+ 3.x
34
+
35
+ ```ruby
36
+ CommentIndex.match_all.results.first.is_published == true
37
+ ```
38
+
39
+ * It no longer supports method based assignment like `result.some_key = "value"`.
40
+
41
+ However, this should not have any practical implications, as changing the
42
+ results is not considered to be a common use case.
43
+
4
44
  ## Update 2.x to 3.x
5
45
 
6
46
  * **[BREAKING]** No longer pass multiple arguments to `#must`, `#must_not`,
data/lib/search_flip.rb CHANGED
@@ -1,9 +1,7 @@
1
1
  require "ruby2_keywords"
2
2
  require "forwardable"
3
3
  require "http"
4
- require "hashie"
5
4
  require "thread"
6
- require "json"
7
5
  require "oj"
8
6
  require "set"
9
7
 
@@ -143,7 +143,7 @@ module SearchFlip
143
143
 
144
144
  return if options[:raise] == false
145
145
 
146
- parsed_response = SearchFlip::JSON.parse(response.to_s)
146
+ parsed_response = response.parse
147
147
 
148
148
  return unless parsed_response["errors"]
149
149
 
@@ -5,12 +5,6 @@ module SearchFlip
5
5
  bulk_limit: 1_000,
6
6
  bulk_max_mb: 100,
7
7
  auto_refresh: false,
8
- instrumenter: NullInstrumenter.new,
9
- json_options: {
10
- mode: :custom,
11
- use_to_json: true,
12
- time_format: :xmlschema,
13
- bigdecimal_as_decimal: false
14
- }
8
+ instrumenter: NullInstrumenter.new
15
9
  }
16
10
  end
@@ -28,11 +28,7 @@ module SearchFlip
28
28
 
29
29
  def version
30
30
  @version_mutex.synchronize do
31
- @version ||= begin
32
- response = http_client.headers(accept: "application/json").get("#{base_url}/")
33
-
34
- SearchFlip::JSON.parse(response.to_s)["version"]["number"]
35
- end
31
+ @version ||= http_client.headers(accept: "application/json").get("#{base_url}/").parse["version"]["number"]
36
32
  end
37
33
  end
38
34
 
@@ -44,9 +40,7 @@ module SearchFlip
44
40
  # @return [Hash] The raw response
45
41
 
46
42
  def cluster_health
47
- response = http_client.headers(accept: "application/json").get("#{base_url}/_cluster/health")
48
-
49
- SearchFlip::JSON.parse(response.to_s)
43
+ http_client.headers(accept: "application/json").get("#{base_url}/_cluster/health").parse
50
44
  end
51
45
 
52
46
  # Uses the Elasticsearch Multi Search API to execute multiple search requests
@@ -96,11 +90,10 @@ module SearchFlip
96
90
  # @return [Hash] The raw response
97
91
 
98
92
  def update_aliases(payload)
99
- response = http_client
93
+ http_client
100
94
  .headers(accept: "application/json", content_type: "application/json")
101
95
  .post("#{base_url}/_aliases", body: SearchFlip::JSON.generate(payload))
102
-
103
- SearchFlip::JSON.parse(response.to_s)
96
+ .parse
104
97
  end
105
98
 
106
99
  # Sends an analyze request to Elasticsearch. Raises
@@ -112,11 +105,10 @@ module SearchFlip
112
105
  # @return [Hash] The raw response
113
106
 
114
107
  def analyze(request, params = {})
115
- response = http_client
108
+ http_client
116
109
  .headers(accept: "application/json")
117
110
  .post("#{base_url}/_analyze", json: request, params: params)
118
-
119
- SearchFlip::JSON.parse(response.to_s)
111
+ .parse
120
112
  end
121
113
 
122
114
  # Fetches information about the specified index aliases. Raises
@@ -132,11 +124,10 @@ module SearchFlip
132
124
  # @return [Hash] The raw response
133
125
 
134
126
  def get_aliases(index_name: "*", alias_name: "*")
135
- response = http_client
127
+ http_client
136
128
  .headers(accept: "application/json", content_type: "application/json")
137
129
  .get("#{base_url}/#{index_name}/_alias/#{alias_name}")
138
-
139
- SearchFlip::JSON.parse(response.to_s)
130
+ .parse
140
131
  end
141
132
 
142
133
  # Returns whether or not the associated Elasticsearch alias already
@@ -168,11 +159,10 @@ module SearchFlip
168
159
  # @return [Array] The raw response
169
160
 
170
161
  def get_indices(name = "*", params: {})
171
- response = http_client
162
+ http_client
172
163
  .headers(accept: "application/json", content_type: "application/json")
173
164
  .get("#{base_url}/_cat/indices/#{name}", params: params)
174
-
175
- SearchFlip::JSON.parse(response.to_s)
165
+ .parse
176
166
  end
177
167
 
178
168
  alias_method :cat_indices, :get_indices
@@ -269,11 +259,10 @@ module SearchFlip
269
259
  # @return [Hash] The index settings
270
260
 
271
261
  def get_index_settings(index_name)
272
- response = http_client
262
+ http_client
273
263
  .headers(accept: "application/json")
274
264
  .get("#{index_url(index_name)}/_settings")
275
-
276
- SearchFlip::JSON.parse(response.to_s)
265
+ .parse
277
266
  end
278
267
 
279
268
  # Sends a refresh request to Elasticsearch. Raises
@@ -283,7 +272,7 @@ module SearchFlip
283
272
  # @return [Boolean] Returns true or raises SearchFlip::ResponseError
284
273
 
285
274
  def refresh(index_names = nil)
286
- http_client.post("#{index_names ? index_url(Array(index_names).join(",")) : base_url}/_refresh")
275
+ http_client.post("#{index_names ? index_url(Array(index_names).join(",")) : base_url}/_refresh", json: {})
287
276
 
288
277
  true
289
278
  end
@@ -321,9 +310,7 @@ module SearchFlip
321
310
  url = type_name ? type_url(index_name, type_name) : index_url(index_name)
322
311
  params = type_name && version.to_f >= 6.7 ? { include_type_name: true } : {}
323
312
 
324
- response = http_client.headers(accept: "application/json").get("#{url}/_mapping", params: params)
325
-
326
- SearchFlip::JSON.parse(response.to_s)
313
+ http_client.headers(accept: "application/json").get("#{url}/_mapping", params: params).parse
327
314
  end
328
315
 
329
316
  # Deletes the specified index from Elasticsearch. Raises
@@ -235,22 +235,6 @@ module SearchFlip
235
235
  filter(match_all: options)
236
236
  end
237
237
 
238
- # Adds a match none filter to the criteria, which simply matches none
239
- # documents at all. Check out the Elasticsearch docs for further details.
240
- #
241
- # @example Basic usage
242
- # CommentIndex.match_none
243
- #
244
- # @example Filter chaining
245
- # query = CommentIndex.search("...")
246
- # query = query.match_none unless current_user.admin?
247
- #
248
- # @return [SearchFlip::Criteria] A newly created extended criteria
249
-
250
- def match_none
251
- filter(match_none: {})
252
- end
253
-
254
238
  # Adds an exists filter to the criteria, which selects all documents for
255
239
  # which the specified field has a non-null value.
256
240
  #
@@ -1,28 +1,7 @@
1
1
  module SearchFlip
2
- # The SearchFlip::HTTPClient class wraps the http gem and responsible for the
3
- # http request/response handling, ie communicating with Elasticsearch. You
4
- # only need to use it directly if you need authentication to communicate with
5
- # Elasticsearch or if you want to set some custom http settings.
6
- #
7
- # @example
8
- # http_client = SearchFlip::HTTPClient.new
9
- #
10
- # # Basic Auth
11
- # http_client = http_client.basic_auth(user: "username", pass: "password")
12
- #
13
- # # Raw Auth Header
14
- # http_client = http_client.auth("Bearer VGhlIEhUVFAgR2VtLCBST0NLUw")
15
- #
16
- # # Proxy Settings
17
- # http_client = http_client.via("proxy.host", 8080)
18
- #
19
- # # Custom headers
20
- # http_client = http_client.headers(key: "value")
21
- #
22
- # # Timeouts
23
- # http_client = http_client.timeout(20)
24
- #
25
- # SearchFlip::Connection.new(base_url: "...", http_client: http_client)
2
+ # The SearchFlip::HTTPClient class wraps the http gem, is for internal use
3
+ # and responsible for the http request/response handling, ie communicating
4
+ # with Elasticsearch.
26
5
 
27
6
  class HTTPClient
28
7
  attr_accessor :request, :plugins
@@ -35,11 +14,11 @@ module SearchFlip
35
14
  class << self
36
15
  extend Forwardable
37
16
 
38
- def_delegators :new, :headers, :via, :basic_auth, :auth, :timeout
17
+ def_delegators :new, :headers, :via, :basic_auth, :auth
39
18
  def_delegators :new, :get, :post, :put, :delete, :head
40
19
  end
41
20
 
42
- [:headers, :via, :basic_auth, :auth, :timeout].each do |method|
21
+ [:headers, :via, :basic_auth, :auth].each do |method|
43
22
  define_method method do |*args|
44
23
  dup.tap do |client|
45
24
  client.request = request.send(method, *args)
@@ -153,7 +153,7 @@ module SearchFlip
153
153
  # scope to be applied to the scope
154
154
 
155
155
  def each_record(scope, index_scope: false)
156
- return enum_for(:each_record, scope, index_scope: index_scope) unless block_given?
156
+ return enum_for(:each_record, scope) unless block_given?
157
157
 
158
158
  if scope.respond_to?(:find_each)
159
159
  (index_scope ? self.index_scope(scope) : scope).find_each do |record|
@@ -247,8 +247,8 @@ module SearchFlip
247
247
  SearchFlip::Criteria.new(target: self)
248
248
  end
249
249
 
250
- def_delegators :criteria, :all, :profile, :where, :where_not, :filter, :range, :match_all, :match_none,
251
- :exists, :exists_not, :post_where, :post_where_not, :post_range, :post_exists, :post_exists_not,
250
+ def_delegators :criteria, :all, :profile, :where, :where_not, :filter, :range, :match_all, :exists,
251
+ :exists_not, :post_where, :post_where_not, :post_range, :post_exists, :post_exists_not,
252
252
  :post_filter, :post_must, :post_must_not, :post_should, :aggregate, :scroll, :source,
253
253
  :includes, :eager_load, :preload, :sort, :resort, :order, :reorder, :offset, :limit, :paginate,
254
254
  :page, :per, :search, :highlight, :suggest, :custom, :find_in_batches, :find_results_in_batches,
@@ -487,9 +487,7 @@ module SearchFlip
487
487
  # @return [Hash] The raw response
488
488
 
489
489
  def analyze(request, params = {})
490
- response = connection.http_client.headers(accept: "application/json").post("#{index_url}/_analyze", json: request, params: params)
491
-
492
- SearchFlip::JSON.parse(response.to_s)
490
+ connection.http_client.headers(accept: "application/json").post("#{index_url}/_analyze", json: request, params: params).parse
493
491
  end
494
492
 
495
493
  # Sends a index refresh request to Elasticsearch. Raises
@@ -1,11 +1,11 @@
1
1
  module SearchFlip
2
2
  class JSON
3
3
  def self.generate(obj)
4
- Oj.dump(obj, SearchFlip::Config[:json_options])
4
+ Oj.dump(obj, mode: :custom, use_to_json: true)
5
5
  end
6
6
 
7
- def self.parse(json)
8
- ::JSON.parse(json)
7
+ def self.parse(str)
8
+ Oj.load(str)
9
9
  end
10
10
  end
11
11
  end
@@ -156,8 +156,7 @@ module SearchFlip
156
156
  end
157
157
 
158
158
  # Returns the results, ie hits, wrapped in a SearchFlip::Result object
159
- # which basically is a Hashie::Mash. Check out the Hashie docs for further
160
- # details.
159
+ # which basically is a Hash with method-like access.
161
160
  #
162
161
  # @example
163
162
  # CommentIndex.search("hello world").results
@@ -166,7 +165,7 @@ module SearchFlip
166
165
  # @return [Array] An array of results
167
166
 
168
167
  def results
169
- @results ||= hits["hits"].map { |hit| Result.from_hit(hit) }
168
+ @results ||= hits["hits"].map { |hit| SearchFlip::Result.from_hit(hit) }
170
169
  end
171
170
 
172
171
  # Returns the named sugggetion, if a name is specified or alle suggestions.
@@ -304,13 +303,13 @@ module SearchFlip
304
303
 
305
304
  @aggregations[key] =
306
305
  if response["aggregations"].nil? || response["aggregations"][key].nil?
307
- Result.new
306
+ SearchFlip::Result.new
308
307
  elsif response["aggregations"][key]["buckets"].is_a?(Array)
309
- response["aggregations"][key]["buckets"].each_with_object({}) { |bucket, hash| hash[bucket["key"]] = Result.new(bucket) }
308
+ response["aggregations"][key]["buckets"].each_with_object({}) { |bucket, hash| hash[bucket["key"]] = SearchFlip::Result.convert(bucket) }
310
309
  elsif response["aggregations"][key]["buckets"].is_a?(Hash)
311
- Result.new response["aggregations"][key]["buckets"]
310
+ SearchFlip::Result.convert(response["aggregations"][key]["buckets"])
312
311
  else
313
- Result.new response["aggregations"][key]
312
+ SearchFlip::Result.convert(response["aggregations"][key])
314
313
  end
315
314
  end
316
315
  end
@@ -1,29 +1,55 @@
1
1
  module SearchFlip
2
- # The SearchFlip::Result class basically is a hash wrapper that uses
3
- # Hashie::Mash to provide convenient method access to the hash attributes.
2
+ # The SearchFlip::Result class is a simple Hash, but extended with
3
+ # method-like access. Keys assigned via methods are stored as strings.
4
+ #
5
+ # @example method access
6
+ # result = SearchFlip::Result.new
7
+ # result["some_key"] = "value"
8
+ # result.some_key # => "value"
4
9
 
5
- class Result < Hashie::Mash
6
- def self.disable_warnings?(*args)
7
- true
8
- end
10
+ class Result < Hash
11
+ def self.convert(hash)
12
+ res = self[hash]
9
13
 
10
- # Creates a SearchFlip::Result object from a raw hit. Useful for e.g.
11
- # top hits aggregations.
12
- #
13
- # @example
14
- # query = ProductIndex.aggregate(top_sales: { top_hits: "..." })
15
- # top_sales_hits = query.aggregations(:top_sales).top_hits.hits.hits
16
- #
17
- # SearchFlip::Result.from_hit(top_sales_hits.first)
14
+ res.each do |key, value|
15
+ if value.is_a?(Hash)
16
+ res[key] = convert(value)
17
+ elsif value.is_a?(Array)
18
+ res[key] = convert_array(value)
19
+ end
20
+ end
18
21
 
19
- def self.from_hit(hit)
20
- raw_result = (hit["_source"] || {}).dup
22
+ res
23
+ end
21
24
 
22
- raw_result["_hit"] = hit.each_with_object({}) do |(key, value), hash|
23
- hash[key] = value if key != "_source"
25
+ def self.convert_array(arr)
26
+ arr.map do |obj|
27
+ if obj.is_a?(Hash)
28
+ convert(obj)
29
+ elsif obj.is_a?(Array)
30
+ convert_array(obj)
31
+ else
32
+ obj
33
+ end
24
34
  end
35
+ end
36
+
37
+ # rubocop:disable Lint/MissingSuper
25
38
 
26
- new(raw_result)
39
+ def method_missing(name, *args, &block)
40
+ self[name.to_s]
41
+ end
42
+
43
+ # rubocop:enable Lint/MissingSuper
44
+
45
+ def respond_to_missing?(name, include_private = false)
46
+ key?(name.to_s) || super
47
+ end
48
+
49
+ def self.from_hit(hit)
50
+ res = convert(hit["_source"] || {})
51
+ res["_hit"] = convert(self[hit].tap { |hash| hash.delete("_source") })
52
+ res
27
53
  end
28
54
  end
29
55
  end
@@ -1 +1,29 @@
1
- warn "[DEPRECATION] Using search_flip/to_json is not neccessary anymore"
1
+ require "time"
2
+ require "date"
3
+ require "json"
4
+
5
+ class Time
6
+ def to_json(*args)
7
+ iso8601(6).to_json
8
+ end
9
+ end
10
+
11
+ class Date
12
+ def to_json(*args)
13
+ iso8601.to_json
14
+ end
15
+ end
16
+
17
+ class DateTime
18
+ def to_json(*args)
19
+ iso8601(6).to_json
20
+ end
21
+ end
22
+
23
+ if defined?(ActiveSupport)
24
+ class ActiveSupport::TimeWithZone
25
+ def to_json(*args)
26
+ iso8601(6).to_json
27
+ end
28
+ end
29
+ end
@@ -1,3 +1,3 @@
1
1
  module SearchFlip
2
- VERSION = "3.4.0"
2
+ VERSION = "4.0.0.beta"
3
3
  end
data/search_flip.gemspec CHANGED
@@ -35,9 +35,7 @@ Gem::Specification.new do |spec|
35
35
  spec.add_development_dependency "timecop"
36
36
  spec.add_development_dependency "webmock"
37
37
 
38
- spec.add_dependency "hashie"
39
38
  spec.add_dependency "http"
40
- spec.add_dependency "json"
41
39
  spec.add_dependency "oj"
42
40
  spec.add_dependency "ruby2_keywords"
43
41
  end
@@ -15,7 +15,7 @@ RSpec.describe SearchFlip::Aggregation do
15
15
  aggregation.where(title: "title").where(description: "description").aggregate(:category)
16
16
  end
17
17
 
18
- aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
18
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
19
19
 
20
20
  expect(aggregations).to eq("category1" => 2, "category2" => 1)
21
21
  end
@@ -36,7 +36,7 @@ RSpec.describe SearchFlip::Aggregation do
36
36
  .aggregate(:category)
37
37
  end
38
38
 
39
- aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
39
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
40
40
 
41
41
  expect(aggregations).to eq("category1" => 2, "category2" => 1)
42
42
  end
@@ -54,7 +54,7 @@ RSpec.describe SearchFlip::Aggregation do
54
54
  aggregation.where(title: "title1".."title3").where(price: 100..200).aggregate(:category)
55
55
  end
56
56
 
57
- aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
57
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
58
58
 
59
59
  expect(aggregations).to eq("category1" => 2, "category2" => 1)
60
60
  end
@@ -74,7 +74,7 @@ RSpec.describe SearchFlip::Aggregation do
74
74
  aggregation.where_not(title: "title4").where_not(title: "title5").aggregate(:category)
75
75
  end
76
76
 
77
- aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
77
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
78
78
 
79
79
  expect(aggregations).to eq("category1" => 2, "category2" => 1)
80
80
  end
@@ -94,7 +94,7 @@ RSpec.describe SearchFlip::Aggregation do
94
94
  aggregation.where_not(title: ["title1", "title2"]).where_not(title: ["title6", "title7"]).aggregate(:category)
95
95
  end
96
96
 
97
- aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
97
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
98
98
 
99
99
  expect(aggregations).to eq("category1" => 2, "category2" => 1)
100
100
  end
@@ -114,7 +114,7 @@ RSpec.describe SearchFlip::Aggregation do
114
114
  aggregation.where_not(price: 100..150).where_not(title: "title6".."title7").aggregate(:category)
115
115
  end
116
116
 
117
- aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
117
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
118
118
 
119
119
  expect(aggregations).to eq("category1" => 2, "category2" => 1)
120
120
  end
@@ -134,7 +134,7 @@ RSpec.describe SearchFlip::Aggregation do
134
134
  aggregation.filter(range: { price: { gte: 100, lte: 200 } }).filter(term: { title: "title" }).aggregate(:category)
135
135
  end
136
136
 
137
- aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
137
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
138
138
 
139
139
  expect(aggregations).to eq("category1" => 2, "category2" => 1)
140
140
  end
@@ -156,7 +156,7 @@ RSpec.describe SearchFlip::Aggregation do
156
156
  aggregation.range(:price, gte: 100, lte: 200).range(:title, gte: "title1", lte: "title3").aggregate(:category)
157
157
  end
158
158
 
159
- aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
159
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
160
160
 
161
161
  expect(aggregations).to eq("category1" => 2, "category2" => 1)
162
162
  end
@@ -174,7 +174,7 @@ RSpec.describe SearchFlip::Aggregation do
174
174
  aggregation.match_all.aggregate(:category)
175
175
  end
176
176
 
177
- aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
177
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
178
178
 
179
179
  expect(aggregations).to eq("category1" => 2, "category2" => 1)
180
180
  end
@@ -194,7 +194,7 @@ RSpec.describe SearchFlip::Aggregation do
194
194
  aggregation.exists(:title).exists(:price).aggregate(:category)
195
195
  end
196
196
 
197
- aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
197
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
198
198
 
199
199
  expect(aggregations).to eq("category1" => 2, "category2" => 1)
200
200
  end
@@ -214,7 +214,7 @@ RSpec.describe SearchFlip::Aggregation do
214
214
  aggregation.exists_not(:title).exists_not(:price).aggregate(:category)
215
215
  end
216
216
 
217
- aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[:key]] = bucket.doc_count }
217
+ aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
218
218
 
219
219
  expect(aggregations).to eq("category1" => 2, "category2" => 1)
220
220
  end
@@ -244,21 +244,21 @@ RSpec.describe SearchFlip::Aggregation do
244
244
  expect(aggregations).to eq("category1" => 3, "category2" => 3)
245
245
 
246
246
  aggregations = query.aggregations(:category)["category1"].title.buckets.each_with_object({}) do |bucket, hash|
247
- hash[bucket[:key]] = bucket.doc_count
247
+ hash[bucket["key"]] = bucket.doc_count
248
248
  end
249
249
 
250
250
  expect(aggregations).to eq("title1" => 2, "title2" => 1)
251
251
 
252
252
  aggregations = query.aggregations(:category)["category2"].title.buckets.each_with_object({}) do |bucket, hash|
253
- hash[bucket[:key]] = bucket.doc_count
253
+ hash[bucket["key"]] = bucket.doc_count
254
254
  end
255
255
 
256
256
  expect(aggregations).to eq("title1" => 1, "title2" => 2)
257
257
 
258
- expect(query.aggregations(:category)["category1"].title.buckets.detect { |bucket| bucket[:key] == "title1" }.price.value).to eq(30)
259
- expect(query.aggregations(:category)["category1"].title.buckets.detect { |bucket| bucket[:key] == "title2" }.price.value).to eq(15)
260
- expect(query.aggregations(:category)["category2"].title.buckets.detect { |bucket| bucket[:key] == "title1" }.price.value).to eq(30)
261
- expect(query.aggregations(:category)["category2"].title.buckets.detect { |bucket| bucket[:key] == "title2" }.price.value).to eq(60)
258
+ expect(query.aggregations(:category)["category1"].title.buckets.detect { |bucket| bucket["key"] == "title1" }.price.value).to eq(30)
259
+ expect(query.aggregations(:category)["category1"].title.buckets.detect { |bucket| bucket["key"] == "title2" }.price.value).to eq(15)
260
+ expect(query.aggregations(:category)["category2"].title.buckets.detect { |bucket| bucket["key"] == "title1" }.price.value).to eq(30)
261
+ expect(query.aggregations(:category)["category2"].title.buckets.detect { |bucket| bucket["key"] == "title2" }.price.value).to eq(60)
262
262
  end
263
263
  end
264
264
 
@@ -416,18 +416,6 @@ RSpec.describe SearchFlip::Criteria do
416
416
  end
417
417
  end
418
418
 
419
- describe "#match_none" do
420
- it "does not match any documents" do
421
- if ProductIndex.connection.version.to_i >= 5
422
- ProductIndex.import create(:product)
423
-
424
- query = ProductIndex.match_none
425
-
426
- expect(query.records).to eq([])
427
- end
428
- end
429
- end
430
-
431
419
  describe "#exists" do
432
420
  it "sets up the constraints correctly and is chainable" do
433
421
  product1 = create(:product, title: "title1", description: "description1")
@@ -1313,7 +1301,7 @@ RSpec.describe SearchFlip::Criteria do
1313
1301
  ProductIndex.import create(:product)
1314
1302
 
1315
1303
  query = ProductIndex.match_all.explain(true)
1316
- expect(query.results.first._hit.key?(:_explanation)).to eq(true)
1304
+ expect(query.results.first._hit.key?("_explanation")).to eq(true)
1317
1305
  end
1318
1306
  end
1319
1307
 
@@ -7,7 +7,7 @@ class HttpTestRequest
7
7
  self.calls = []
8
8
  end
9
9
 
10
- [:headers, :via, :basic_auth, :auth, :timeout].each do |method|
10
+ [:via, :basic_auth, :auth].each do |method|
11
11
  define_method method do |*args|
12
12
  dup.tap do |request|
13
13
  request.calls = calls + [[method, args]]
@@ -20,7 +20,7 @@ RSpec.describe SearchFlip::HTTPClient do
20
20
  describe "delegation" do
21
21
  subject { SearchFlip::HTTPClient }
22
22
 
23
- [:headers, :via, :basic_auth, :auth, :timeout].each do |method|
23
+ [:headers, :via, :basic_auth, :auth].each do |method|
24
24
  it { should delegate(method).to(:new) }
25
25
  end
26
26
 
@@ -56,12 +56,8 @@ RSpec.describe SearchFlip::HTTPClient do
56
56
  end
57
57
  end
58
58
 
59
- [:headers, :via, :basic_auth, :auth, :timeout].each do |method|
59
+ [:via, :basic_auth, :auth].each do |method|
60
60
  describe "##{method}" do
61
- it "is understood by HTTP" do
62
- expect(HTTP.respond_to?(method)).to eq(true)
63
- end
64
-
65
61
  it "creates a dupped instance" do
66
62
  client = SearchFlip::HTTPClient.new
67
63
  client.request = HttpTestRequest.new
@@ -5,8 +5,8 @@ RSpec.describe SearchFlip::Index do
5
5
  subject { ProductIndex }
6
6
 
7
7
  methods = [
8
- :all, :profile, :where, :where_not, :filter, :range, :match_all, :match_none,
9
- :exists, :exists_not, :post_where, :post_where_not, :post_filter, :post_must,
8
+ :all, :profile, :where, :where_not, :filter, :range, :match_all, :exists,
9
+ :exists_not, :post_where, :post_where_not, :post_filter, :post_must,
10
10
  :post_must_not, :post_should, :post_range, :post_exists, :post_exists_not,
11
11
  :aggregate, :scroll, :source, :includes, :eager_load, :preload, :sort, :resort,
12
12
  :order, :reorder, :offset, :limit, :paginate, :page, :per, :search,
@@ -211,18 +211,12 @@ RSpec.describe SearchFlip::Index do
211
211
  mapping = { properties: { id: { type: "long" } } }
212
212
 
213
213
  allow(TestIndex).to receive(:mapping).and_return(mapping)
214
- allow(TestIndex.connection).to receive(:update_mapping)
214
+ allow(TestIndex.connection).to receive(:update_mapping).and_call_original
215
215
 
216
216
  TestIndex.update_mapping
217
217
 
218
218
  expect(TestIndex.connection).to have_received(:update_mapping).with("test", { "test" => mapping }, type_name: "test")
219
219
  end
220
-
221
- it "updates the mapping" do
222
- TestIndex.create_index
223
-
224
- expect(TestIndex.update_mapping).to eq(true)
225
- end
226
220
  end
227
221
  end
228
222
 
@@ -264,19 +258,12 @@ RSpec.describe SearchFlip::Index do
264
258
  TestIndex.create_index
265
259
  TestIndex.update_mapping
266
260
 
267
- allow(TestIndex.connection).to receive(:get_mapping)
261
+ allow(TestIndex.connection).to receive(:get_mapping).and_call_original
268
262
 
269
263
  TestIndex.get_mapping
270
264
 
271
265
  expect(TestIndex.connection).to have_received(:get_mapping).with("test", type_name: "test")
272
266
  end
273
-
274
- it "returns the mapping" do
275
- TestIndex.create_index
276
- TestIndex.update_mapping
277
-
278
- expect(TestIndex.get_mapping).to be_present
279
- end
280
267
  end
281
268
  end
282
269
 
@@ -2,16 +2,6 @@ require File.expand_path("../spec_helper", __dir__)
2
2
 
3
3
  RSpec.describe SearchFlip::JSON do
4
4
  describe ".generate" do
5
- it "encodes timestamps correctly" do
6
- Timecop.freeze "2020-06-01 12:00:00 UTC" do
7
- expect(described_class.generate(timestamp: Time.now.utc)).to eq('{"timestamp":"2020-06-01T12:00:00.000Z"}')
8
- end
9
- end
10
-
11
- it "encodes bigdecimals as string" do
12
- expect(described_class.generate(value: BigDecimal(1))).to eq('{"value":"1.0"}')
13
- end
14
-
15
5
  it "delegates to Oj" do
16
6
  allow(Oj).to receive(:dump)
17
7
 
@@ -19,7 +9,7 @@ RSpec.describe SearchFlip::JSON do
19
9
 
20
10
  described_class.generate(payload)
21
11
 
22
- expect(Oj).to have_received(:dump).with(payload, mode: :custom, use_to_json: true, time_format: :xmlschema, bigdecimal_as_decimal: false)
12
+ expect(Oj).to have_received(:dump).with(payload, mode: :custom, use_to_json: true)
23
13
  end
24
14
 
25
15
  it "generates json" do
@@ -28,18 +18,14 @@ RSpec.describe SearchFlip::JSON do
28
18
  end
29
19
 
30
20
  describe ".parse" do
31
- it "returns the parsed json payload" do
32
- expect(described_class.parse('{"key":"value"}')).to eq("key" => "value")
33
- end
34
-
35
- it "delegates to JSON" do
36
- allow(JSON).to receive(:parse)
21
+ it "delegates to Oj" do
22
+ allow(Oj).to receive(:load)
37
23
 
38
24
  payload = '{"key":"value"}'
39
25
 
40
26
  described_class.parse(payload)
41
27
 
42
- expect(JSON).to have_received(:parse).with(payload)
28
+ expect(Oj).to have_received(:load).with(payload)
43
29
  end
44
30
  end
45
31
  end
@@ -7,7 +7,7 @@ RSpec.describe SearchFlip::NullInstrumenter do
7
7
  it "calls start" do
8
8
  allow(subject).to receive(:start)
9
9
 
10
- subject.instrument("name", { key: "value" }) { true }
10
+ subject.instrument("name", { key: "value" }) {}
11
11
 
12
12
  expect(subject).to have_received(:start)
13
13
  end
@@ -15,7 +15,7 @@ RSpec.describe SearchFlip::NullInstrumenter do
15
15
  it "calls finish" do
16
16
  allow(subject).to receive(:finish)
17
17
 
18
- subject.instrument("name", { key: "value" }) { true }
18
+ subject.instrument("name", { key: "value" }) {}
19
19
 
20
20
  expect(subject).to have_received(:finish)
21
21
  end
@@ -1,6 +1,29 @@
1
1
  require File.expand_path("../spec_helper", __dir__)
2
2
 
3
3
  RSpec.describe SearchFlip::Result do
4
+ describe ".convert" do
5
+ it "deeply converts hashes and arrays" do
6
+ result = described_class.convert("parent" => { "child" => [{ "key1" => "value" }, { "key2" => 3 }] })
7
+
8
+ expect(result.parent.child[0].key1).to eq("value")
9
+ expect(result.parent.child[1].key2).to eq(3)
10
+ end
11
+ end
12
+
13
+ describe "#method_missing" do
14
+ it "returns the value of the key equal to the message name" do
15
+ expect(described_class.convert("some_key" => "value").some_key).to eq("value")
16
+ expect(described_class.new.some_key).to be_nil
17
+ end
18
+ end
19
+
20
+ describe "#responds_to_missing?" do
21
+ it "returns true/false if the key equal to the message name is present or not" do
22
+ expect(described_class.convert("some_key" => nil).respond_to?(:some_key)).to eq(true)
23
+ expect(described_class.convert("some_key" => nil).respond_to?(:other_key)).to eq(false)
24
+ end
25
+ end
26
+
4
27
  describe ".from_hit" do
5
28
  it "adds a _hit key into _source and merges the hit keys into it" do
6
29
  result = SearchFlip::Result.from_hit("_score" => 1.0, "_source" => { "name" => "Some name" })
@@ -8,12 +31,6 @@ RSpec.describe SearchFlip::Result do
8
31
  expect(result).to eq("name" => "Some name", "_hit" => { "_score" => 1.0 })
9
32
  end
10
33
 
11
- it "allows deep method access" do
12
- result = SearchFlip::Result.from_hit("_source" => { "key1" => [{ "key2" => "value" }] })
13
-
14
- expect(result.key1[0].key2).to eq("value")
15
- end
16
-
17
34
  it "works with the _source being disabled" do
18
35
  result = SearchFlip::Result.from_hit("_id" => 1)
19
36
 
@@ -0,0 +1,28 @@
1
+ require File.expand_path("../spec_helper", __dir__)
2
+ require "search_flip/to_json"
3
+
4
+ RSpec.describe "to_json" do
5
+ it "uses the correct format for Time" do
6
+ Timecop.freeze Time.parse("2018-01-01 12:00:00 UTC") do
7
+ expect(Time.now.utc.to_json).to eq("\"2018-01-01T12:00:00.000000Z\"")
8
+ end
9
+ end
10
+
11
+ it "uses the correct format for Date" do
12
+ Timecop.freeze Time.parse("2018-01-01 12:00:00 UTC") do
13
+ expect(Date.today.to_json).to eq("\"2018-01-01\"")
14
+ end
15
+ end
16
+
17
+ it "uses the correct format for DateTime" do
18
+ Timecop.freeze Time.parse("2018-01-01 12:00:00 UTC") do
19
+ expect(Time.now.utc.to_json).to eq("\"2018-01-01T12:00:00.000000Z\"")
20
+ end
21
+ end
22
+
23
+ it "uses the correct format for TimeWithZone" do
24
+ Timecop.freeze Time.parse("2018-01-01 12:00:00 UTC") do
25
+ expect(Time.find_zone("UTC").now.to_json).to eq("\"2018-01-01T12:00:00.000000Z\"")
26
+ end
27
+ end
28
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: search_flip
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.4.0
4
+ version: 4.0.0.beta
5
5
  platform: ruby
6
6
  authors:
7
7
  - Benjamin Vetter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-15 00:00:00.000000000 Z
11
+ date: 2020-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -150,20 +150,6 @@ dependencies:
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
- - !ruby/object:Gem::Dependency
154
- name: hashie
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - ">="
158
- - !ruby/object:Gem::Version
159
- version: '0'
160
- type: :runtime
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - ">="
165
- - !ruby/object:Gem::Version
166
- version: '0'
167
153
  - !ruby/object:Gem::Dependency
168
154
  name: http
169
155
  requirement: !ruby/object:Gem::Requirement
@@ -178,20 +164,6 @@ dependencies:
178
164
  - - ">="
179
165
  - !ruby/object:Gem::Version
180
166
  version: '0'
181
- - !ruby/object:Gem::Dependency
182
- name: json
183
- requirement: !ruby/object:Gem::Requirement
184
- requirements:
185
- - - ">="
186
- - !ruby/object:Gem::Version
187
- version: '0'
188
- type: :runtime
189
- prerelease: false
190
- version_requirements: !ruby/object:Gem::Requirement
191
- requirements:
192
- - - ">="
193
- - !ruby/object:Gem::Version
194
- version: '0'
195
167
  - !ruby/object:Gem::Dependency
196
168
  name: oj
197
169
  requirement: !ruby/object:Gem::Requirement
@@ -278,6 +250,7 @@ files:
278
250
  - spec/search_flip/null_instrumenter_spec.rb
279
251
  - spec/search_flip/response_spec.rb
280
252
  - spec/search_flip/result_spec.rb
253
+ - spec/search_flip/to_json_spec.rb
281
254
  - spec/spec_helper.rb
282
255
  homepage: https://github.com/mrkamel/search_flip
283
256
  licenses:
@@ -297,11 +270,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
297
270
  version: '0'
298
271
  required_rubygems_version: !ruby/object:Gem::Requirement
299
272
  requirements:
300
- - - ">="
273
+ - - ">"
301
274
  - !ruby/object:Gem::Version
302
- version: '0'
275
+ version: 1.3.1
303
276
  requirements: []
304
- rubygems_version: 3.2.3
277
+ rubygems_version: 3.0.3
305
278
  signing_key:
306
279
  specification_version: 4
307
280
  summary: Full-Featured Elasticsearch Ruby Client with a Chainable DSL
@@ -319,4 +292,5 @@ test_files:
319
292
  - spec/search_flip/null_instrumenter_spec.rb
320
293
  - spec/search_flip/response_spec.rb
321
294
  - spec/search_flip/result_spec.rb
295
+ - spec/search_flip/to_json_spec.rb
322
296
  - spec/spec_helper.rb