search_flip 3.1.2 → 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: 51aeb6ec190e4ee6ff8d291d46e038e55bec7eb2b09cfc5eb410b9f523b75f8a
4
- data.tar.gz: 89882033f77adf5c29104ae35e5c0ee2fd4d4222111ba98ad76cfb508a92da8d
3
+ metadata.gz: b023bc6411647eaecfcb8f5b0fe535379974a0824d49699dd74ef867a67c69eb
4
+ data.tar.gz: 5dc4a0439f9442811f3966e86b0c6b09d09c54450a04234c3738ae0ab7935900
5
5
  SHA512:
6
- metadata.gz: 5fd5f110807947f0a1bc9906ced03be0c20a1c79a792321cd472d24b0c50a68e6ed88927f1db087ce64f45fd1544d85a5b434b25365f90f2ef83f9d06a8cb6db
7
- data.tar.gz: cf8e8c77ec27b895249d39e8498207f4a4484776d9f3aefb79f163f5c9e262c80516e4ff99573e833f83ad1de96659a1b2707c1ae7d2786bd72d5d59631ba00b
6
+ metadata.gz: a5fc637e8c016531df22af678adcae60a4f4169e5f1d2215d52be0a0dff1111b849cb4d79ca36d6cbf315c8516bc51d543852ab5026339d59cb1f5d08ba356f7
7
+ data.tar.gz: 7cf9d55a9aca5d6d63401750d40bc656fcc345101d8ce92a300c24649e38810d399d43ff225611bbdd91a257d6cb15eee26a6c811974b987e92e72e67eded704
@@ -0,0 +1,34 @@
1
+ on: push
2
+ name: test
3
+ jobs:
4
+ test:
5
+ runs-on: ubuntu-latest
6
+ strategy:
7
+ fail-fast: false
8
+ matrix:
9
+ elasticsearch:
10
+ - plainpicture/elasticsearch:2.4.1_delete-by-query
11
+ - elasticsearch:5.4
12
+ - docker.elastic.co/elasticsearch/elasticsearch:6.7.0
13
+ - docker.elastic.co/elasticsearch/elasticsearch:7.0.0
14
+ - docker.elastic.co/elasticsearch/elasticsearch:7.9.0
15
+ ruby:
16
+ - 2.5
17
+ - 2.6
18
+ - 2.7
19
+ services:
20
+ elasticsearch:
21
+ image: ${{ matrix.elasticsearch }}
22
+ env:
23
+ discovery.type: single-node
24
+ ports:
25
+ - 9200:9200
26
+ steps:
27
+ - uses: actions/checkout@v1
28
+ - uses: actions/setup-ruby@v1
29
+ with:
30
+ ruby-version: ${{ matrix.ruby }}
31
+ - run: bundle
32
+ - run: sleep 10
33
+ - run: bundle exec rspec
34
+ - run: bundle exec rubocop
@@ -5,6 +5,9 @@ AllCops:
5
5
  Gemspec/RequiredRubyVersion:
6
6
  Enabled: false
7
7
 
8
+ Style/CaseLikeIf:
9
+ Enabled: false
10
+
8
11
  Style/ExplicitBlockArgument:
9
12
  Enabled: false
10
13
 
@@ -1,6 +1,14 @@
1
1
 
2
2
  # CHANGELOG
3
3
 
4
+ ## v4.0.0
5
+
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"`
11
+
4
12
  ## v3.1.2
5
13
 
6
14
  * Fix ignored false value for source when merging criterias
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  **Full-Featured Elasticsearch Ruby Client with a Chainable DSL**
5
5
 
6
- [![Build Status](https://secure.travis-ci.org/mrkamel/search_flip.svg?branch=master)](http://travis-ci.org/mrkamel/search_flip)
6
+ [![Build](https://github.com/mrkamel/search_flip/workflows/test/badge.svg)](https://github.com/mrkamel/search_flip/actions?query=workflow%3Atest+branch%3Amaster)
7
7
  [![Gem Version](https://badge.fury.io/rb/search_flip.svg)](http://badge.fury.io/rb/search_flip)
8
8
 
9
9
  Using SearchFlip it is dead-simple to create index classes that correspond to
@@ -51,8 +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 (http-rb, hashie
55
- and oj only).
54
+ Finally, SearchFlip comes with a minimal set of dependencies (http-rb and oj only).
56
55
 
57
56
  ## Reference Docs
58
57
 
@@ -475,8 +474,8 @@ end
475
474
  ```
476
475
 
477
476
  Generally, aggregation results returned by Elasticsearch are returned as a
478
- `SearchFlip::Result`, which basically is a `Hashie::Mash`, such that you can
479
- access them via:
477
+ `SearchFlip::Result`, which basically is a Hash with method-like access, such
478
+ that you can access them via:
480
479
 
481
480
  ```ruby
482
481
  query.aggregations(:username)["mrkamel"].revenue.value
@@ -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`,
@@ -1,7 +1,6 @@
1
1
  require "ruby2_keywords"
2
2
  require "forwardable"
3
3
  require "http"
4
- require "hashie"
5
4
  require "thread"
6
5
  require "oj"
7
6
  require "set"
@@ -71,7 +71,7 @@ module SearchFlip
71
71
  .headers(accept: "application/json", content_type: "application/x-ndjson")
72
72
  .post("#{base_url}/_msearch", body: payload)
73
73
 
74
- raw_response.parse["responses"].map.with_index do |response, index|
74
+ SearchFlip::JSON.parse(raw_response.to_s)["responses"].map.with_index do |response, index|
75
75
  SearchFlip::Response.new(criterias[index], response)
76
76
  end
77
77
  end
@@ -608,7 +608,7 @@ module SearchFlip
608
608
  http_request.post("#{target.type_url}/_search", params: request_params, json: request)
609
609
  end
610
610
 
611
- SearchFlip::Response.new(self, http_response.parse)
611
+ SearchFlip::Response.new(self, SearchFlip::JSON.parse(http_response.to_s))
612
612
  rescue SearchFlip::ConnectionError, SearchFlip::ResponseError => e
613
613
  raise e unless failsafe_value
614
614
 
@@ -455,7 +455,9 @@ module SearchFlip
455
455
  # @return [Hash] The specified document
456
456
 
457
457
  def get(id, params = {})
458
- connection.http_client.headers(accept: "application/json").get("#{type_url}/#{id}", params: params).parse
458
+ response = connection.http_client.headers(accept: "application/json").get("#{type_url}/#{id}", params: params)
459
+
460
+ SearchFlip::JSON.parse(response.to_s)
459
461
  end
460
462
 
461
463
  # Retrieves the documents specified by ids from elasticsearch.
@@ -471,7 +473,9 @@ module SearchFlip
471
473
  # @return [Hash] The raw response
472
474
 
473
475
  def mget(request, params = {})
474
- connection.http_client.headers(accept: "application/json").post("#{type_url}/_mget", json: request, params: params).parse
476
+ response = connection.http_client.headers(accept: "application/json").post("#{type_url}/_mget", json: request, params: params)
477
+
478
+ SearchFlip::JSON.parse(response.to_s)
475
479
  end
476
480
 
477
481
  # Sends an analyze request to Elasticsearch. Raises
@@ -1,16 +1,11 @@
1
1
  module SearchFlip
2
2
  class JSON
3
- @default_options = {
4
- mode: :custom,
5
- use_to_json: true
6
- }
7
-
8
- def self.default_options
9
- @default_options
3
+ def self.generate(obj)
4
+ Oj.dump(obj, mode: :custom, use_to_json: true)
10
5
  end
11
6
 
12
- def self.generate(obj)
13
- Oj.dump(obj, default_options)
7
+ def self.parse(str)
8
+ Oj.load(str)
14
9
  end
15
10
  end
16
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,3 +1,3 @@
1
1
  module SearchFlip
2
- VERSION = "3.1.2"
2
+ VERSION = "4.0.0.beta"
3
3
  end
@@ -35,7 +35,6 @@ 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
39
  spec.add_dependency "oj"
41
40
  spec.add_dependency "ruby2_keywords"
@@ -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
 
@@ -1301,7 +1301,7 @@ RSpec.describe SearchFlip::Criteria do
1301
1301
  ProductIndex.import create(:product)
1302
1302
 
1303
1303
  query = ProductIndex.match_all.explain(true)
1304
- expect(query.results.first._hit.key?(:_explanation)).to eq(true)
1304
+ expect(query.results.first._hit.key?("_explanation")).to eq(true)
1305
1305
  end
1306
1306
  end
1307
1307
 
@@ -0,0 +1,31 @@
1
+ require File.expand_path("../spec_helper", __dir__)
2
+
3
+ RSpec.describe SearchFlip::JSON do
4
+ describe ".generate" do
5
+ it "delegates to Oj" do
6
+ allow(Oj).to receive(:dump)
7
+
8
+ payload = { key: "value" }
9
+
10
+ described_class.generate(payload)
11
+
12
+ expect(Oj).to have_received(:dump).with(payload, mode: :custom, use_to_json: true)
13
+ end
14
+
15
+ it "generates json" do
16
+ expect(described_class.generate(key: "value")).to eq('{"key":"value"}')
17
+ end
18
+ end
19
+
20
+ describe ".parse" do
21
+ it "delegates to Oj" do
22
+ allow(Oj).to receive(:load)
23
+
24
+ payload = '{"key":"value"}'
25
+
26
+ described_class.parse(payload)
27
+
28
+ expect(Oj).to have_received(:load).with(payload)
29
+ end
30
+ end
31
+ 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
 
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.1.2
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: 2020-10-02 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
@@ -213,9 +199,9 @@ executables: []
213
199
  extensions: []
214
200
  extra_rdoc_files: []
215
201
  files:
202
+ - ".github/workflows/test.yml"
216
203
  - ".gitignore"
217
204
  - ".rubocop.yml"
218
- - ".travis.yml"
219
205
  - CHANGELOG.md
220
206
  - Gemfile
221
207
  - LICENSE.txt
@@ -259,6 +245,7 @@ files:
259
245
  - spec/search_flip/criteria_spec.rb
260
246
  - spec/search_flip/http_client_spec.rb
261
247
  - spec/search_flip/index_spec.rb
248
+ - spec/search_flip/json_spec.rb
262
249
  - spec/search_flip/model_spec.rb
263
250
  - spec/search_flip/null_instrumenter_spec.rb
264
251
  - spec/search_flip/response_spec.rb
@@ -283,9 +270,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
283
270
  version: '0'
284
271
  required_rubygems_version: !ruby/object:Gem::Requirement
285
272
  requirements:
286
- - - ">="
273
+ - - ">"
287
274
  - !ruby/object:Gem::Version
288
- version: '0'
275
+ version: 1.3.1
289
276
  requirements: []
290
277
  rubygems_version: 3.0.3
291
278
  signing_key:
@@ -300,6 +287,7 @@ test_files:
300
287
  - spec/search_flip/criteria_spec.rb
301
288
  - spec/search_flip/http_client_spec.rb
302
289
  - spec/search_flip/index_spec.rb
290
+ - spec/search_flip/json_spec.rb
303
291
  - spec/search_flip/model_spec.rb
304
292
  - spec/search_flip/null_instrumenter_spec.rb
305
293
  - spec/search_flip/response_spec.rb
@@ -1,20 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- env:
4
- - ES_IMAGE=plainpicture/elasticsearch:2.4.1_delete-by-query
5
- - ES_IMAGE=elasticsearch:5.4
6
- - ES_IMAGE=docker.elastic.co/elasticsearch/elasticsearch:6.7.0
7
- - ES_IMAGE=docker.elastic.co/elasticsearch/elasticsearch:7.0.0
8
- - ES_IMAGE=docker.elastic.co/elasticsearch/elasticsearch:7.9.0
9
- rvm:
10
- - ruby-2.5.3
11
- - ruby-2.6.2
12
- - ruby-2.7.1
13
- before_install:
14
- - docker-compose up -d
15
- - sleep 10
16
- install:
17
- - travis_retry bundle install
18
- script:
19
- - bundle exec rspec
20
- - bundle exec rubocop