search_flip 3.4.0 → 4.0.0.beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  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