search_flip 3.1.1 → 3.4.0
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 +4 -4
- data/.github/workflows/test.yml +35 -0
- data/.rubocop.yml +5 -1
- data/CHANGELOG.md +23 -0
- data/README.md +40 -35
- data/lib/search_flip.rb +1 -0
- data/lib/search_flip/bulk.rb +1 -1
- data/lib/search_flip/config.rb +7 -1
- data/lib/search_flip/connection.rb +28 -15
- data/lib/search_flip/criteria.rb +20 -30
- data/lib/search_flip/filterable.rb +16 -0
- data/lib/search_flip/http_client.rb +26 -5
- data/lib/search_flip/index.rb +12 -6
- data/lib/search_flip/json.rb +4 -9
- data/lib/search_flip/to_json.rb +1 -29
- data/lib/search_flip/version.rb +1 -1
- data/search_flip.gemspec +1 -0
- data/spec/search_flip/criteria_spec.rb +22 -0
- data/spec/search_flip/http_client_spec.rb +7 -3
- data/spec/search_flip/index_spec.rb +17 -4
- data/spec/search_flip/json_spec.rb +45 -0
- data/spec/search_flip/null_instrumenter_spec.rb +2 -2
- metadata +20 -6
- data/.travis.yml +0 -20
- data/spec/search_flip/to_json_spec.rb +0 -28
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6722b210d8b3d0baa98e3370f26e2f293a21ea7db15dd08ba47deb2a1dba4e1c
|
|
4
|
+
data.tar.gz: a66d9f5482e06ae11cffeece148a8eb290523ee6ec4c91f510c1258b1c780225
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4e60dbae8d1bf0c4be3964bd0daf0740c4dd89827d61481d21960af17f34b237b512dde09f08111949d9b728bc3290c59a535930e168aaa562c30c9f74faa841
|
|
7
|
+
data.tar.gz: 3b7d941dee59924dc47b486e5cd3d88af8a3a9a42e8f6952e14934087e2a0acbe0014ee09caabec373640c35c5ae1d72a433e2100fcd2257e8d920c09f39e3b6
|
|
@@ -0,0 +1,35 @@
|
|
|
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.11.2
|
|
15
|
+
ruby:
|
|
16
|
+
- 2.6
|
|
17
|
+
- 2.7
|
|
18
|
+
- 3.0
|
|
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: gem install bundler
|
|
32
|
+
- run: bundle
|
|
33
|
+
- run: sleep 10
|
|
34
|
+
- run: bundle exec rspec
|
|
35
|
+
- run: bundle exec rubocop
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
|
|
2
2
|
# CHANGELOG
|
|
3
3
|
|
|
4
|
+
## v3.4.0
|
|
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`
|
|
22
|
+
|
|
23
|
+
## v3.1.2
|
|
24
|
+
|
|
25
|
+
* Fix ignored false value for source when merging criterias
|
|
26
|
+
|
|
4
27
|
## v3.1.1
|
|
5
28
|
|
|
6
29
|
* Make `SearchFlip::Result.from_hit` work with the `_source` being disabled
|
data/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
**Full-Featured Elasticsearch Ruby Client with a Chainable DSL**
|
|
5
5
|
|
|
6
|
-
[](https://github.com/mrkamel/search_flip/actions?query=workflow%3Atest+branch%3Amaster)
|
|
7
7
|
[](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
|
|
55
|
-
and oj only).
|
|
54
|
+
Finally, SearchFlip comes with a minimal set of dependencies.
|
|
56
55
|
|
|
57
56
|
## Reference Docs
|
|
58
57
|
|
|
@@ -419,6 +418,14 @@ Simply matches all documents:
|
|
|
419
418
|
CommentIndex.match_all
|
|
420
419
|
```
|
|
421
420
|
|
|
421
|
+
* `match_none`
|
|
422
|
+
|
|
423
|
+
Simply matches none documents at all:
|
|
424
|
+
|
|
425
|
+
```ruby
|
|
426
|
+
CommentIndex.match_none
|
|
427
|
+
```
|
|
428
|
+
|
|
422
429
|
* `all`
|
|
423
430
|
|
|
424
431
|
Simply returns the criteria as is or an empty criteria when called on the index
|
|
@@ -749,7 +756,7 @@ end
|
|
|
749
756
|
This allows to use different clusters per index e.g. when migrating indices to
|
|
750
757
|
new versions of Elasticsearch.
|
|
751
758
|
|
|
752
|
-
You can specify basic auth, additional headers, etc via:
|
|
759
|
+
You can specify basic auth, additional headers, request timeouts, etc via:
|
|
753
760
|
|
|
754
761
|
```ruby
|
|
755
762
|
http_client = SearchFlip::HTTPClient.new
|
|
@@ -766,6 +773,9 @@ http_client = http_client.via("proxy.host", 8080)
|
|
|
766
773
|
# Custom headers
|
|
767
774
|
http_client = http_client.headers(key: "value")
|
|
768
775
|
|
|
776
|
+
# Timeouts
|
|
777
|
+
http_client = http_client.timeout(20)
|
|
778
|
+
|
|
769
779
|
SearchFlip::Connection.new(base_url: "...", http_client: http_client)
|
|
770
780
|
```
|
|
771
781
|
|
|
@@ -875,57 +885,52 @@ Thus, if your ORM supports `.find_each`, `#id` and `#where` you are already
|
|
|
875
885
|
good to go. Otherwise, simply add your custom implementation of those methods
|
|
876
886
|
that work with whatever ORM you use.
|
|
877
887
|
|
|
878
|
-
##
|
|
888
|
+
## JSON
|
|
879
889
|
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
However, `JSON.generate` in ruby by default outputs something like:
|
|
890
|
+
SearchFlip is using the [Oj gem](https://github.com/ohler55/oj) to generate
|
|
891
|
+
JSON. More concretely, SearchFlip is using:
|
|
884
892
|
|
|
885
893
|
```ruby
|
|
886
|
-
|
|
887
|
-
# => "{\"time\":\"2018-02-22 18:19:33 UTC\"}"
|
|
894
|
+
Oj.dump({ key: "value" }, mode: :custom, use_to_json: true, time_format: :xmlschema, bigdecimal_as_decimal: false)
|
|
888
895
|
```
|
|
889
896
|
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
However,
|
|
893
|
-
|
|
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:
|
|
894
901
|
|
|
895
902
|
```ruby
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
903
|
+
SearchFlip::Config[:json_options] = {
|
|
904
|
+
mode: :custom,
|
|
905
|
+
use_to_json: false,
|
|
906
|
+
time_format: :xmlschema,
|
|
907
|
+
bigdecimal_as_decimal: false
|
|
908
|
+
}
|
|
901
909
|
```
|
|
902
910
|
|
|
903
|
-
|
|
904
|
-
JSON. More concretely, SearchFlip is using:
|
|
911
|
+
However, you then have to convert timestamps manually for indexation via e.g.:
|
|
905
912
|
|
|
906
913
|
```ruby
|
|
907
|
-
|
|
908
|
-
|
|
914
|
+
class MyIndex
|
|
915
|
+
# ...
|
|
909
916
|
|
|
910
|
-
|
|
917
|
+
def self.serialize(model)
|
|
918
|
+
{
|
|
919
|
+
# ...
|
|
911
920
|
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
921
|
+
created_at: model.created_at.to_time
|
|
922
|
+
}
|
|
923
|
+
end
|
|
924
|
+
end
|
|
915
925
|
```
|
|
916
926
|
|
|
917
|
-
|
|
918
|
-
`Date` and `DateTime` to get proper serialization. You can either add them on
|
|
919
|
-
your own, via other libraries or by simply using:
|
|
920
|
-
|
|
921
|
-
```ruby
|
|
922
|
-
require "search_flip/to_json"
|
|
923
|
-
```
|
|
927
|
+
Please check out the oj docs for more details.
|
|
924
928
|
|
|
925
929
|
## Feature Support
|
|
926
930
|
|
|
927
931
|
* for Elasticsearch 2.x, the delete-by-query plugin is required to delete
|
|
928
932
|
records via queries
|
|
933
|
+
* `#match_none` is only available with Elasticsearch >= 5
|
|
929
934
|
* `#track_total_hits` is only available with Elasticsearch >= 7
|
|
930
935
|
|
|
931
936
|
## Keeping your Models and Indices in Sync
|
data/lib/search_flip.rb
CHANGED
data/lib/search_flip/bulk.rb
CHANGED
data/lib/search_flip/config.rb
CHANGED
|
@@ -5,6 +5,12 @@ module SearchFlip
|
|
|
5
5
|
bulk_limit: 1_000,
|
|
6
6
|
bulk_max_mb: 100,
|
|
7
7
|
auto_refresh: false,
|
|
8
|
-
instrumenter: NullInstrumenter.new
|
|
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
|
+
}
|
|
9
15
|
}
|
|
10
16
|
end
|
|
@@ -28,7 +28,11 @@ module SearchFlip
|
|
|
28
28
|
|
|
29
29
|
def version
|
|
30
30
|
@version_mutex.synchronize do
|
|
31
|
-
@version ||=
|
|
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
|
|
32
36
|
end
|
|
33
37
|
end
|
|
34
38
|
|
|
@@ -40,7 +44,9 @@ module SearchFlip
|
|
|
40
44
|
# @return [Hash] The raw response
|
|
41
45
|
|
|
42
46
|
def cluster_health
|
|
43
|
-
http_client.headers(accept: "application/json").get("#{base_url}/_cluster/health")
|
|
47
|
+
response = http_client.headers(accept: "application/json").get("#{base_url}/_cluster/health")
|
|
48
|
+
|
|
49
|
+
SearchFlip::JSON.parse(response.to_s)
|
|
44
50
|
end
|
|
45
51
|
|
|
46
52
|
# Uses the Elasticsearch Multi Search API to execute multiple search requests
|
|
@@ -71,7 +77,7 @@ module SearchFlip
|
|
|
71
77
|
.headers(accept: "application/json", content_type: "application/x-ndjson")
|
|
72
78
|
.post("#{base_url}/_msearch", body: payload)
|
|
73
79
|
|
|
74
|
-
raw_response.
|
|
80
|
+
SearchFlip::JSON.parse(raw_response.to_s)["responses"].map.with_index do |response, index|
|
|
75
81
|
SearchFlip::Response.new(criterias[index], response)
|
|
76
82
|
end
|
|
77
83
|
end
|
|
@@ -90,10 +96,11 @@ module SearchFlip
|
|
|
90
96
|
# @return [Hash] The raw response
|
|
91
97
|
|
|
92
98
|
def update_aliases(payload)
|
|
93
|
-
http_client
|
|
99
|
+
response = http_client
|
|
94
100
|
.headers(accept: "application/json", content_type: "application/json")
|
|
95
101
|
.post("#{base_url}/_aliases", body: SearchFlip::JSON.generate(payload))
|
|
96
|
-
|
|
102
|
+
|
|
103
|
+
SearchFlip::JSON.parse(response.to_s)
|
|
97
104
|
end
|
|
98
105
|
|
|
99
106
|
# Sends an analyze request to Elasticsearch. Raises
|
|
@@ -105,10 +112,11 @@ module SearchFlip
|
|
|
105
112
|
# @return [Hash] The raw response
|
|
106
113
|
|
|
107
114
|
def analyze(request, params = {})
|
|
108
|
-
http_client
|
|
115
|
+
response = http_client
|
|
109
116
|
.headers(accept: "application/json")
|
|
110
117
|
.post("#{base_url}/_analyze", json: request, params: params)
|
|
111
|
-
|
|
118
|
+
|
|
119
|
+
SearchFlip::JSON.parse(response.to_s)
|
|
112
120
|
end
|
|
113
121
|
|
|
114
122
|
# Fetches information about the specified index aliases. Raises
|
|
@@ -124,10 +132,11 @@ module SearchFlip
|
|
|
124
132
|
# @return [Hash] The raw response
|
|
125
133
|
|
|
126
134
|
def get_aliases(index_name: "*", alias_name: "*")
|
|
127
|
-
http_client
|
|
135
|
+
response = http_client
|
|
128
136
|
.headers(accept: "application/json", content_type: "application/json")
|
|
129
137
|
.get("#{base_url}/#{index_name}/_alias/#{alias_name}")
|
|
130
|
-
|
|
138
|
+
|
|
139
|
+
SearchFlip::JSON.parse(response.to_s)
|
|
131
140
|
end
|
|
132
141
|
|
|
133
142
|
# Returns whether or not the associated Elasticsearch alias already
|
|
@@ -159,10 +168,11 @@ module SearchFlip
|
|
|
159
168
|
# @return [Array] The raw response
|
|
160
169
|
|
|
161
170
|
def get_indices(name = "*", params: {})
|
|
162
|
-
http_client
|
|
171
|
+
response = http_client
|
|
163
172
|
.headers(accept: "application/json", content_type: "application/json")
|
|
164
173
|
.get("#{base_url}/_cat/indices/#{name}", params: params)
|
|
165
|
-
|
|
174
|
+
|
|
175
|
+
SearchFlip::JSON.parse(response.to_s)
|
|
166
176
|
end
|
|
167
177
|
|
|
168
178
|
alias_method :cat_indices, :get_indices
|
|
@@ -259,10 +269,11 @@ module SearchFlip
|
|
|
259
269
|
# @return [Hash] The index settings
|
|
260
270
|
|
|
261
271
|
def get_index_settings(index_name)
|
|
262
|
-
http_client
|
|
272
|
+
response = http_client
|
|
263
273
|
.headers(accept: "application/json")
|
|
264
274
|
.get("#{index_url(index_name)}/_settings")
|
|
265
|
-
|
|
275
|
+
|
|
276
|
+
SearchFlip::JSON.parse(response.to_s)
|
|
266
277
|
end
|
|
267
278
|
|
|
268
279
|
# Sends a refresh request to Elasticsearch. Raises
|
|
@@ -272,7 +283,7 @@ module SearchFlip
|
|
|
272
283
|
# @return [Boolean] Returns true or raises SearchFlip::ResponseError
|
|
273
284
|
|
|
274
285
|
def refresh(index_names = nil)
|
|
275
|
-
http_client.post("#{index_names ? index_url(Array(index_names).join(",")) : base_url}/_refresh"
|
|
286
|
+
http_client.post("#{index_names ? index_url(Array(index_names).join(",")) : base_url}/_refresh")
|
|
276
287
|
|
|
277
288
|
true
|
|
278
289
|
end
|
|
@@ -310,7 +321,9 @@ module SearchFlip
|
|
|
310
321
|
url = type_name ? type_url(index_name, type_name) : index_url(index_name)
|
|
311
322
|
params = type_name && version.to_f >= 6.7 ? { include_type_name: true } : {}
|
|
312
323
|
|
|
313
|
-
http_client.headers(accept: "application/json").get("#{url}/_mapping", params: params)
|
|
324
|
+
response = http_client.headers(accept: "application/json").get("#{url}/_mapping", params: params)
|
|
325
|
+
|
|
326
|
+
SearchFlip::JSON.parse(response.to_s)
|
|
314
327
|
end
|
|
315
328
|
|
|
316
329
|
# Deletes the specified index from Elasticsearch. Raises
|
data/lib/search_flip/criteria.rb
CHANGED
|
@@ -44,35 +44,25 @@ module SearchFlip
|
|
|
44
44
|
other = other.criteria
|
|
45
45
|
|
|
46
46
|
fresh.tap do |criteria|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
criteria.must_not_values = (criteria.must_not_values || []) + other.must_not_values if other.must_not_values
|
|
67
|
-
criteria.filter_values = (criteria.filter_values || []) + other.filter_values if other.filter_values
|
|
68
|
-
criteria.post_must_values = (criteria.post_must_values || []) + other.post_must_values if other.post_must_values
|
|
69
|
-
criteria.post_must_not_values = (criteria.post_must_not_values || []) + other.post_must_not_values if other.post_must_not_values
|
|
70
|
-
criteria.post_filter_values = (criteria.post_filter_values || []) + other.post_filter_values if other.post_filter_values
|
|
71
|
-
|
|
72
|
-
criteria.highlight_values = (criteria.highlight_values || {}).merge(other.highlight_values) if other.highlight_values
|
|
73
|
-
criteria.suggest_values = (criteria.suggest_values || {}).merge(other.suggest_values) if other.suggest_values
|
|
74
|
-
criteria.custom_value = (criteria.custom_value || {}).merge(other.custom_value) if other.custom_value
|
|
75
|
-
criteria.aggregation_values = (criteria.aggregation_values || {}).merge(other.aggregation_values) if other.aggregation_values
|
|
47
|
+
[
|
|
48
|
+
:profile_value, :failsafe_value, :terminate_after_value, :timeout_value, :offset_value,
|
|
49
|
+
:limit_value, :scroll_args, :source_value, :preference_value, :search_type_value,
|
|
50
|
+
:routing_value, :track_total_hits_value, :explain_value
|
|
51
|
+
].each do |name|
|
|
52
|
+
criteria.send(:"#{name}=", other.send(name)) unless other.send(name).nil?
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
[
|
|
56
|
+
:sort_values, :includes_values, :preload_values, :eager_load_values, :must_values,
|
|
57
|
+
:must_not_values, :filter_values, :post_must_values, :post_must_not_values,
|
|
58
|
+
:post_filter_values
|
|
59
|
+
].each do |name|
|
|
60
|
+
criteria.send(:"#{name}=", (criteria.send(name) || []) + other.send(name)) if other.send(name)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
[:highlight_values, :suggest_values, :custom_value, :aggregation_values].each do |name|
|
|
64
|
+
criteria.send(:"#{name}=", (criteria.send(name) || {}).merge(other.send(name))) if other.send(name)
|
|
65
|
+
end
|
|
76
66
|
end
|
|
77
67
|
end
|
|
78
68
|
|
|
@@ -618,7 +608,7 @@ module SearchFlip
|
|
|
618
608
|
http_request.post("#{target.type_url}/_search", params: request_params, json: request)
|
|
619
609
|
end
|
|
620
610
|
|
|
621
|
-
SearchFlip::Response.new(self, http_response.
|
|
611
|
+
SearchFlip::Response.new(self, SearchFlip::JSON.parse(http_response.to_s))
|
|
622
612
|
rescue SearchFlip::ConnectionError, SearchFlip::ResponseError => e
|
|
623
613
|
raise e unless failsafe_value
|
|
624
614
|
|
|
@@ -235,6 +235,22 @@ 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
|
+
|
|
238
254
|
# Adds an exists filter to the criteria, which selects all documents for
|
|
239
255
|
# which the specified field has a non-null value.
|
|
240
256
|
#
|
|
@@ -1,7 +1,28 @@
|
|
|
1
1
|
module SearchFlip
|
|
2
|
-
# The SearchFlip::HTTPClient class wraps the http gem
|
|
3
|
-
#
|
|
4
|
-
# with
|
|
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)
|
|
5
26
|
|
|
6
27
|
class HTTPClient
|
|
7
28
|
attr_accessor :request, :plugins
|
|
@@ -14,11 +35,11 @@ module SearchFlip
|
|
|
14
35
|
class << self
|
|
15
36
|
extend Forwardable
|
|
16
37
|
|
|
17
|
-
def_delegators :new, :headers, :via, :basic_auth, :auth
|
|
38
|
+
def_delegators :new, :headers, :via, :basic_auth, :auth, :timeout
|
|
18
39
|
def_delegators :new, :get, :post, :put, :delete, :head
|
|
19
40
|
end
|
|
20
41
|
|
|
21
|
-
[:headers, :via, :basic_auth, :auth].each do |method|
|
|
42
|
+
[:headers, :via, :basic_auth, :auth, :timeout].each do |method|
|
|
22
43
|
define_method method do |*args|
|
|
23
44
|
dup.tap do |client|
|
|
24
45
|
client.request = request.send(method, *args)
|
data/lib/search_flip/index.rb
CHANGED
|
@@ -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) unless block_given?
|
|
156
|
+
return enum_for(:each_record, scope, index_scope: index_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, :
|
|
251
|
-
: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, :match_none,
|
|
251
|
+
:exists, :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,
|
|
@@ -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)
|
|
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)
|
|
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
|
|
@@ -483,7 +487,9 @@ module SearchFlip
|
|
|
483
487
|
# @return [Hash] The raw response
|
|
484
488
|
|
|
485
489
|
def analyze(request, params = {})
|
|
486
|
-
connection.http_client.headers(accept: "application/json").post("#{index_url}/_analyze", json: request, params: 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)
|
|
487
493
|
end
|
|
488
494
|
|
|
489
495
|
# Sends a index refresh request to Elasticsearch. Raises
|
data/lib/search_flip/json.rb
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
module SearchFlip
|
|
2
2
|
class JSON
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
use_to_json: true
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
def self.default_options
|
|
9
|
-
@default_options
|
|
3
|
+
def self.generate(obj)
|
|
4
|
+
Oj.dump(obj, SearchFlip::Config[:json_options])
|
|
10
5
|
end
|
|
11
6
|
|
|
12
|
-
def self.
|
|
13
|
-
|
|
7
|
+
def self.parse(json)
|
|
8
|
+
::JSON.parse(json)
|
|
14
9
|
end
|
|
15
10
|
end
|
|
16
11
|
end
|
data/lib/search_flip/to_json.rb
CHANGED
|
@@ -1,29 +1 @@
|
|
|
1
|
-
|
|
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
|
+
warn "[DEPRECATION] Using search_flip/to_json is not neccessary anymore"
|
data/lib/search_flip/version.rb
CHANGED
data/search_flip.gemspec
CHANGED
|
@@ -110,6 +110,16 @@ RSpec.describe SearchFlip::Criteria do
|
|
|
110
110
|
|
|
111
111
|
expect(criteria1.merge(criteria2).send(method)).to eq("value2")
|
|
112
112
|
end
|
|
113
|
+
|
|
114
|
+
it "handles false values correctly" do
|
|
115
|
+
criteria1 = SearchFlip::Criteria.new(target: TestIndex)
|
|
116
|
+
criteria1.send("#{method}=", true)
|
|
117
|
+
|
|
118
|
+
criteria2 = SearchFlip::Criteria.new(target: TestIndex)
|
|
119
|
+
criteria2.send("#{method}=", false)
|
|
120
|
+
|
|
121
|
+
expect(criteria1.merge(criteria2).send(method)).to eq(false)
|
|
122
|
+
end
|
|
113
123
|
end
|
|
114
124
|
end
|
|
115
125
|
|
|
@@ -406,6 +416,18 @@ RSpec.describe SearchFlip::Criteria do
|
|
|
406
416
|
end
|
|
407
417
|
end
|
|
408
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
|
+
|
|
409
431
|
describe "#exists" do
|
|
410
432
|
it "sets up the constraints correctly and is chainable" do
|
|
411
433
|
product1 = create(:product, title: "title1", description: "description1")
|
|
@@ -7,7 +7,7 @@ class HttpTestRequest
|
|
|
7
7
|
self.calls = []
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
[:via, :basic_auth, :auth].each do |method|
|
|
10
|
+
[:headers, :via, :basic_auth, :auth, :timeout].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].each do |method|
|
|
23
|
+
[:headers, :via, :basic_auth, :auth, :timeout].each do |method|
|
|
24
24
|
it { should delegate(method).to(:new) }
|
|
25
25
|
end
|
|
26
26
|
|
|
@@ -56,8 +56,12 @@ RSpec.describe SearchFlip::HTTPClient do
|
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
58
|
|
|
59
|
-
[:via, :basic_auth, :auth].each do |method|
|
|
59
|
+
[:headers, :via, :basic_auth, :auth, :timeout].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
|
+
|
|
61
65
|
it "creates a dupped instance" do
|
|
62
66
|
client = SearchFlip::HTTPClient.new
|
|
63
67
|
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, :
|
|
9
|
-
:exists_not, :post_where, :post_where_not, :post_filter, :post_must,
|
|
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,
|
|
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,12 +211,18 @@ 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)
|
|
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
|
|
220
226
|
end
|
|
221
227
|
end
|
|
222
228
|
|
|
@@ -258,12 +264,19 @@ RSpec.describe SearchFlip::Index do
|
|
|
258
264
|
TestIndex.create_index
|
|
259
265
|
TestIndex.update_mapping
|
|
260
266
|
|
|
261
|
-
allow(TestIndex.connection).to receive(:get_mapping)
|
|
267
|
+
allow(TestIndex.connection).to receive(:get_mapping)
|
|
262
268
|
|
|
263
269
|
TestIndex.get_mapping
|
|
264
270
|
|
|
265
271
|
expect(TestIndex.connection).to have_received(:get_mapping).with("test", type_name: "test")
|
|
266
272
|
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
|
|
267
280
|
end
|
|
268
281
|
end
|
|
269
282
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require File.expand_path("../spec_helper", __dir__)
|
|
2
|
+
|
|
3
|
+
RSpec.describe SearchFlip::JSON do
|
|
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
|
+
it "delegates to Oj" do
|
|
16
|
+
allow(Oj).to receive(:dump)
|
|
17
|
+
|
|
18
|
+
payload = { key: "value" }
|
|
19
|
+
|
|
20
|
+
described_class.generate(payload)
|
|
21
|
+
|
|
22
|
+
expect(Oj).to have_received(:dump).with(payload, mode: :custom, use_to_json: true, time_format: :xmlschema, bigdecimal_as_decimal: false)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "generates json" do
|
|
26
|
+
expect(described_class.generate(key: "value")).to eq('{"key":"value"}')
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
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)
|
|
37
|
+
|
|
38
|
+
payload = '{"key":"value"}'
|
|
39
|
+
|
|
40
|
+
described_class.parse(payload)
|
|
41
|
+
|
|
42
|
+
expect(JSON).to have_received(:parse).with(payload)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
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" }) {}
|
|
10
|
+
subject.instrument("name", { key: "value" }) { true }
|
|
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" }) {}
|
|
18
|
+
subject.instrument("name", { key: "value" }) { true }
|
|
19
19
|
|
|
20
20
|
expect(subject).to have_received(:finish)
|
|
21
21
|
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
|
+
version: 3.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Benjamin Vetter
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-06-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|
|
@@ -178,6 +178,20 @@ dependencies:
|
|
|
178
178
|
- - ">="
|
|
179
179
|
- !ruby/object:Gem::Version
|
|
180
180
|
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'
|
|
181
195
|
- !ruby/object:Gem::Dependency
|
|
182
196
|
name: oj
|
|
183
197
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -213,9 +227,9 @@ executables: []
|
|
|
213
227
|
extensions: []
|
|
214
228
|
extra_rdoc_files: []
|
|
215
229
|
files:
|
|
230
|
+
- ".github/workflows/test.yml"
|
|
216
231
|
- ".gitignore"
|
|
217
232
|
- ".rubocop.yml"
|
|
218
|
-
- ".travis.yml"
|
|
219
233
|
- CHANGELOG.md
|
|
220
234
|
- Gemfile
|
|
221
235
|
- LICENSE.txt
|
|
@@ -259,11 +273,11 @@ files:
|
|
|
259
273
|
- spec/search_flip/criteria_spec.rb
|
|
260
274
|
- spec/search_flip/http_client_spec.rb
|
|
261
275
|
- spec/search_flip/index_spec.rb
|
|
276
|
+
- spec/search_flip/json_spec.rb
|
|
262
277
|
- spec/search_flip/model_spec.rb
|
|
263
278
|
- spec/search_flip/null_instrumenter_spec.rb
|
|
264
279
|
- spec/search_flip/response_spec.rb
|
|
265
280
|
- spec/search_flip/result_spec.rb
|
|
266
|
-
- spec/search_flip/to_json_spec.rb
|
|
267
281
|
- spec/spec_helper.rb
|
|
268
282
|
homepage: https://github.com/mrkamel/search_flip
|
|
269
283
|
licenses:
|
|
@@ -287,7 +301,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
287
301
|
- !ruby/object:Gem::Version
|
|
288
302
|
version: '0'
|
|
289
303
|
requirements: []
|
|
290
|
-
rubygems_version: 3.
|
|
304
|
+
rubygems_version: 3.2.3
|
|
291
305
|
signing_key:
|
|
292
306
|
specification_version: 4
|
|
293
307
|
summary: Full-Featured Elasticsearch Ruby Client with a Chainable DSL
|
|
@@ -300,9 +314,9 @@ test_files:
|
|
|
300
314
|
- spec/search_flip/criteria_spec.rb
|
|
301
315
|
- spec/search_flip/http_client_spec.rb
|
|
302
316
|
- spec/search_flip/index_spec.rb
|
|
317
|
+
- spec/search_flip/json_spec.rb
|
|
303
318
|
- spec/search_flip/model_spec.rb
|
|
304
319
|
- spec/search_flip/null_instrumenter_spec.rb
|
|
305
320
|
- spec/search_flip/response_spec.rb
|
|
306
321
|
- spec/search_flip/result_spec.rb
|
|
307
|
-
- spec/search_flip/to_json_spec.rb
|
|
308
322
|
- spec/spec_helper.rb
|
data/.travis.yml
DELETED
|
@@ -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.8.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
|
|
@@ -1,28 +0,0 @@
|
|
|
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
|