search_flip 3.5.0 → 4.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.5.0"
2
+ VERSION = "4.0.0.beta"
3
3
  end
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
 
@@ -33,15 +31,10 @@ require "search_flip/index"
33
31
  require "search_flip/model"
34
32
 
35
33
  module SearchFlip
36
- class Error < StandardError; end
34
+ class NotSupportedError < StandardError; end
35
+ class ConnectionError < StandardError; end
37
36
 
38
- class NotSupportedError < Error; end
39
-
40
- class HttpError < Error; end
41
- class ConnectionError < HttpError; end
42
- class TimeoutError < HttpError; end
43
-
44
- class ResponseError < Error
37
+ class ResponseError < StandardError
45
38
  attr_reader :code, :body
46
39
 
47
40
  def initialize(code:, body:)
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
 
@@ -97,8 +97,7 @@ RSpec.describe SearchFlip::Criteria do
97
97
  methods = [
98
98
  :profile_value, :failsafe_value, :terminate_after_value, :timeout_value,
99
99
  :offset_value, :limit_value, :scroll_args, :source_value, :preference_value,
100
- :search_type_value, :routing_value, :track_total_hits_value, :explain_value,
101
- :http_timeout_value
100
+ :search_type_value, :routing_value, :track_total_hits_value, :explain_value
102
101
  ]
103
102
 
104
103
  methods.each do |method|
@@ -192,22 +191,6 @@ RSpec.describe SearchFlip::Criteria do
192
191
  end
193
192
  end
194
193
 
195
- describe "#http_timeout" do
196
- it "sets the query timeout" do
197
- http_client = double("client").as_null_object
198
- allow(http_client).to receive(:timeout).and_return(http_client)
199
- allow(http_client).to receive(:post).and_raise(SearchFlip::TimeoutError)
200
- allow(ProductIndex.connection).to receive(:http_client).and_return(http_client)
201
-
202
- expect { ProductIndex.http_timeout(1).execute }.to raise_error(SearchFlip::TimeoutError)
203
- expect(http_client).to have_received(:timeout).with(1)
204
- end
205
-
206
- it "executes without errors" do
207
- expect { ProductIndex.http_timeout(1).execute }.not_to raise_error
208
- end
209
- end
210
-
211
194
  describe "#terminate_after" do
212
195
  it "sets the terminate after value" do
213
196
  query = ProductIndex.terminate_after(1)
@@ -433,18 +416,6 @@ RSpec.describe SearchFlip::Criteria do
433
416
  end
434
417
  end
435
418
 
436
- describe "#match_none" do
437
- it "does not match any documents" do
438
- if ProductIndex.connection.version.to_i >= 5
439
- ProductIndex.import create(:product)
440
-
441
- query = ProductIndex.match_none
442
-
443
- expect(query.records).to eq([])
444
- end
445
- end
446
- end
447
-
448
419
  describe "#exists" do
449
420
  it "sets up the constraints correctly and is chainable" do
450
421
  product1 = create(:product, title: "title1", description: "description1")
@@ -1221,19 +1192,13 @@ RSpec.describe SearchFlip::Criteria do
1221
1192
  end
1222
1193
 
1223
1194
  describe "#failsafe" do
1224
- [SearchFlip::ConnectionError, SearchFlip::TimeoutError, SearchFlip::ResponseError.new(code: "code", body: "body")].each do |error|
1225
- it "prevents #{error}" do
1226
- http_client = double("client").as_null_object
1227
- allow(http_client).to receive(:post).and_raise(error)
1228
- allow(ProductIndex.connection).to receive(:http_client).and_return(http_client)
1229
-
1230
- expect { ProductIndex.all.execute }.to raise_error(error)
1195
+ it "prevents query syntax exceptions" do
1196
+ expect { ProductIndex.search("syntax/error").records }.to raise_error(SearchFlip::ResponseError)
1231
1197
 
1232
- query = ProductIndex.failsafe(true)
1198
+ query = ProductIndex.failsafe(true).search("syntax/error")
1233
1199
 
1234
- expect(query.records).to eq([])
1235
- expect(query.total_entries).to eq(0)
1236
- end
1200
+ expect(query.records).to eq([])
1201
+ expect(query.total_entries).to eq(0)
1237
1202
  end
1238
1203
  end
1239
1204
 
@@ -1336,7 +1301,7 @@ RSpec.describe SearchFlip::Criteria do
1336
1301
  ProductIndex.import create(:product)
1337
1302
 
1338
1303
  query = ProductIndex.match_all.explain(true)
1339
- expect(query.results.first._hit.key?(:_explanation)).to eq(true)
1304
+ expect(query.results.first._hit.key?("_explanation")).to eq(true)
1340
1305
  end
1341
1306
  end
1342
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,
@@ -14,7 +14,7 @@ RSpec.describe SearchFlip::Index do
14
14
  :total_entries, :total_count, :terminate_after, :timeout, :records, :results,
15
15
  :must, :must_not, :should, :find_each_result,
16
16
  :find_results_in_batches, :preference, :search_type, :routing,
17
- :track_total_hits, :explain, :http_timeout
17
+ :track_total_hits, :explain
18
18
  ]
19
19
 
20
20
  methods.each do |method|
@@ -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