searchkick 3.1.3 → 4.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8fb08ed2716d410bb1d609e873e10387a97e437a6bb63530687998a5b9539e13
4
- data.tar.gz: f0b43190746e1d841643b1fc45ef8cd86621b42970369cb2c5fb5f02396ca432
3
+ metadata.gz: 7e1a7c30f19f80bab77d1c44dc8778877881d8178ab52c2c3e48cb0fe1f31ac4
4
+ data.tar.gz: 3091f32cea77c628e629e28dc865d700203f2265393ff44526e86b8ce899ae46
5
5
  SHA512:
6
- metadata.gz: a15444ee63e976df8b85dfb5c5462f48525cd7eb102dc4d0f156e92937223d2cae116c66019821009291bbaeaad56449bf145861c47fa2b729c13e6cf9cf13ac
7
- data.tar.gz: cff5bee77c65345926199f94ba975db417bbbdcca5cfa7647e004b99c5f7aba3965da700a039f7bd1906d91734de98edcc178dcebfe303a4fa8b7b67bdd3e1dd
6
+ metadata.gz: 8d25cc6e9ac21a3f62199255aa5ab9911f2ab3fd970d79417a29063eeb944497da84e1db5ba840cc75eba549bee524c2a9b5b68d624dcadf0d4aa9bfcbc6f4fd
7
+ data.tar.gz: 9fff1372bb24c8c8d2a59a1821d5ad299c9fcc1e2a73e53bbda2f3fec6b8aeddff0e00692451ec3ece0708762b9ccafe370b0ca7fc2d1e623a5bf12688a78ecd
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## 4.0.0
2
+
3
+ - Added support for Elasticsearch 7
4
+ - Added `models` option
5
+
6
+ Breaking changes
7
+
8
+ - Removed support for Elasticsearch 5
9
+ - Removed support for multi-word synonyms (they no longer work with shingles)
10
+
1
11
  ## 3.1.3
2
12
 
3
13
  - Added support for endless ranges
data/README.md CHANGED
@@ -53,7 +53,7 @@ Add this line to your application’s Gemfile:
53
53
  gem 'searchkick'
54
54
  ```
55
55
 
56
- The latest version works with Elasticsearch 5 and 6. For Elasticsearch 2, use version 2.5.0 and [this readme](https://github.com/ankane/searchkick/blob/v2.5.0/README.md).
56
+ The latest version works with Elasticsearch 6 and 7. For Elasticsearch 5, use version 3.1.3 and [this readme](https://github.com/ankane/searchkick/blob/v3.1.3/README.md).
57
57
 
58
58
  Add searchkick to models you want to search.
59
59
 
@@ -312,13 +312,13 @@ A few languages require plugins:
312
312
 
313
313
  ```ruby
314
314
  class Product < ApplicationRecord
315
- searchkick synonyms: [["scallion", "green onion"], ["qtip", "cotton swab"]]
315
+ searchkick synonyms: [["burger", "hamburger"], ["sneakers", "shoes"]]
316
316
  end
317
317
  ```
318
318
 
319
319
  Call `Product.reindex` after changing synonyms.
320
320
 
321
- Synonyms cannot be more than two words at the moment.
321
+ Synonyms cannot be multiple words at the moment.
322
322
 
323
323
  To read synonyms from a file, use:
324
324
 
@@ -355,27 +355,6 @@ Search with:
355
355
  Product.search query, fields: [:name_tagged]
356
356
  ```
357
357
 
358
- ### WordNet
359
-
360
- Prepopulate English synonyms with the [WordNet database](https://en.wikipedia.org/wiki/WordNet).
361
-
362
- Download [WordNet 3.0](http://wordnetcode.princeton.edu/3.0/WNprolog-3.0.tar.gz) to each Elasticsearch server and move `wn_s.pl` to the `/var/lib` directory.
363
-
364
- ```sh
365
- cd /tmp
366
- curl -o wordnet.tar.gz http://wordnetcode.princeton.edu/3.0/WNprolog-3.0.tar.gz
367
- tar -zxvf wordnet.tar.gz
368
- mv prolog/wn_s.pl /var/lib
369
- ```
370
-
371
- Tell each model to use it:
372
-
373
- ```ruby
374
- class Product < ApplicationRecord
375
- searchkick wordnet: true
376
- end
377
- ```
378
-
379
358
  ### Misspellings
380
359
 
381
360
  By default, Searchkick handles misspelled queries by returning results with an [edit distance](https://en.wikipedia.org/wiki/Levenshtein_distance) of one.
@@ -796,8 +775,6 @@ Script support
796
775
  Product.search "*", aggs: {color: {script: {source: "'Color: ' + _value"}}}
797
776
  ```
798
777
 
799
- **Note:** Use `inline` instead of `source` before Elasticsearch 5.6
800
-
801
778
  Date histogram
802
779
 
803
780
  ```ruby
@@ -924,9 +901,7 @@ You can also index and search geo shapes.
924
901
 
925
902
  ```ruby
926
903
  class Restaurant < ApplicationRecord
927
- searchkick geo_shape: {
928
- bounds: {tree: "geohash", precision: "1km"}
929
- }
904
+ searchkick geo_shape: [:bounds]
930
905
 
931
906
  def search_data
932
907
  attributes.merge(
@@ -959,12 +934,6 @@ Not touching the query shape
959
934
  Restaurant.search "burger", where: {bounds: {geo_shape: {type: "envelope", relation: "disjoint", coordinates: [{lat: 38, lon: -123}, {lat: 37, lon: -122}]}}}
960
935
  ```
961
936
 
962
- Containing the query shape
963
-
964
- ```ruby
965
- Restaurant.search "fries", where: {bounds: {geo_shape: {type: "envelope", relation: "contains", coordinates: [{lat: 38, lon: -123}, {lat: 37, lon: -122}]}}}
966
- ```
967
-
968
937
  ## Inheritance
969
938
 
970
939
  Searchkick supports single table inheritance.
@@ -1496,21 +1465,15 @@ Then use `products` and `coupons` as typical results.
1496
1465
 
1497
1466
  **Note:** Errors are not raised as with single requests. Use the `error` method on each query to check for errors.
1498
1467
 
1499
- ## Multiple Indices
1468
+ ## Multiple Models
1500
1469
 
1501
- Search across multiple models/indices with:
1470
+ Search across multiple models with:
1502
1471
 
1503
1472
  ```ruby
1504
- Searchkick.search "milk", index_name: [Product, Category]
1473
+ Searchkick.search "milk", models: [Product, Category]
1505
1474
  ```
1506
1475
 
1507
- Specify conditions for different indices
1508
-
1509
- ```ruby
1510
- where: {_or: [{_type: "product", in_stock: true}, {_type: "category", active: true}]}
1511
- ```
1512
-
1513
- Boost specific indices with:
1476
+ Boost specific models with:
1514
1477
 
1515
1478
  ```ruby
1516
1479
  indices_boost: {Category => 2, Product => 1}
@@ -1657,7 +1620,7 @@ Product.search "milk", includes: [:brand, :stores]
1657
1620
  Eager load different associations by model
1658
1621
 
1659
1622
  ```ruby
1660
- Searchkick.search("*", index_name: [Product, Store], model_includes: {Product => [:store], Store => [:product]})
1623
+ Searchkick.search("*", models: [Product, Store], model_includes: {Product => [:store], Store => [:product]})
1661
1624
  ```
1662
1625
 
1663
1626
  Run additional scopes on results
@@ -1900,6 +1863,11 @@ Check out [this great post](https://www.tiagoamaro.com.br/2014/12/11/multi-tenan
1900
1863
 
1901
1864
  See [how to upgrade to Searchkick 3](docs/Searchkick-3-Upgrade.md)
1902
1865
 
1866
+ ## Elasticsearch 6 to 7 Upgrade
1867
+
1868
+ 1. Install Searchkick 4
1869
+ 2. Upgrade your Elasticsearch cluster
1870
+
1903
1871
  ## Elasticsearch 5 to 6 Upgrade
1904
1872
 
1905
1873
  Elasticsearch 6 removes the ability to reindex with the `_all` field. Before you upgrade, we recommend disabling this field manually and specifying default fields on your models.
data/lib/searchkick.rb CHANGED
@@ -78,16 +78,36 @@ module Searchkick
78
78
  Gem::Version.new(server_version.split("-")[0]) < Gem::Version.new(version.split("-")[0])
79
79
  end
80
80
 
81
+ # memoize for performance
82
+ def self.server_below7?
83
+ unless defined?(@server_below7)
84
+ @server_below7 = server_below?("7.0.0")
85
+ end
86
+ @server_below7
87
+ end
88
+
81
89
  def self.search(term = "*", model: nil, **options, &block)
82
90
  options = options.dup
83
91
  klass = model
84
92
 
85
- # make Searchkick.search(index_name: [Product]) and Product.search equivalent
93
+ # convert index_name into models if possible
94
+ # this should allow for easier upgrade
95
+ if options[:index_name] && !options[:models] && Array(options[:index_name]).all? { |v| v.respond_to?(:searchkick_index) }
96
+ options[:models] = options.delete(:index_name)
97
+ end
98
+
99
+ # make Searchkick.search(models: [Product]) and Product.search equivalent
86
100
  unless klass
87
- index_name = Array(options[:index_name])
88
- if index_name.size == 1 && index_name.first.respond_to?(:searchkick_index)
89
- klass = index_name.first
90
- options.delete(:index_name)
101
+ models = Array(options[:models])
102
+ if models.size == 1
103
+ klass = models.first
104
+ options.delete(:models)
105
+ end
106
+ end
107
+
108
+ if klass
109
+ if (options[:models] && Array(options[:models]) != [klass]) || Array(options[:index_name]).any? { |v| v.respond_to?(:searchkick_index) && v != klass }
110
+ raise ArgumentError, "Use Searchkick.search to search multiple models"
91
111
  end
92
112
  end
93
113
 
@@ -17,7 +17,7 @@ module Searchkick
17
17
  end
18
18
 
19
19
  def delete
20
- if !Searchkick.server_below?("6.0.0") && alias_exists?
20
+ if alias_exists?
21
21
  # can't call delete directly on aliases in ES 6
22
22
  indices = client.indices.get_alias(name: name).keys
23
23
  client.indices.delete index: indices
@@ -68,7 +68,7 @@ module Searchkick
68
68
  }
69
69
  )
70
70
 
71
- response["hits"]["total"]
71
+ Searchkick::Results.new(nil, response).total_count
72
72
  end
73
73
 
74
74
  def promote(new_name, update_refresh_interval: false)
@@ -4,15 +4,13 @@ module Searchkick
4
4
  options = @options
5
5
  language = options[:language]
6
6
  language = language.call if language.respond_to?(:call)
7
- index_type = options[:_type]
8
- index_type = index_type.call if index_type.respond_to?(:call)
9
7
 
10
8
  if options[:mappings] && !options[:merge_mappings]
11
9
  settings = options[:settings] || {}
12
10
  mappings = options[:mappings]
13
11
  else
14
- below60 = Searchkick.server_below?("6.0.0")
15
12
  below62 = Searchkick.server_below?("6.2.0")
13
+ below70 = Searchkick.server_below?("7.0.0")
16
14
 
17
15
  default_type = "text"
18
16
  default_analyzer = :searchkick_index
@@ -144,15 +142,6 @@ module Searchkick
144
142
  }
145
143
  }
146
144
 
147
- if below60
148
- # ES docs say standard token filter does nothing in ES 5
149
- # (and therefore isn't needed at at), but tests say otherwise
150
- # https://www.elastic.co/guide/en/elasticsearch/reference/5.0/analysis-standard-tokenfilter.html
151
- [default_analyzer, :searchkick_search, :searchkick_search2].each do |analyzer|
152
- settings[:analysis][:analyzer][analyzer][:filter].unshift("standard")
153
- end
154
- end
155
-
156
145
  stem = options[:stem]
157
146
 
158
147
  case language
@@ -279,8 +268,7 @@ module Searchkick
279
268
  # - Only apply the synonym expansion at index time
280
269
  # - Don't have the synonym filter applied search
281
270
  # - Use directional synonyms where appropriate. You want to make sure that you're not injecting terms that are too general.
282
- settings[:analysis][:analyzer][default_analyzer][:filter].insert(4, "searchkick_synonym") if below60
283
- settings[:analysis][:analyzer][default_analyzer][:filter] << "searchkick_synonym"
271
+ settings[:analysis][:analyzer][default_analyzer][:filter].insert(2, "searchkick_synonym")
284
272
 
285
273
  %w(word_start word_middle word_end).each do |type|
286
274
  settings[:analysis][:analyzer]["searchkick_#{type}_index".to_sym][:filter].insert(2, "searchkick_synonym")
@@ -391,10 +379,6 @@ module Searchkick
391
379
  "{name}" => keyword_mapping
392
380
  }
393
381
 
394
- if below60 && all
395
- dynamic_fields["{name}"][:include_in_all] = !options[:searchable]
396
- end
397
-
398
382
  if options.key?(:filterable)
399
383
  dynamic_fields["{name}"] = {type: default_type, index: index_false_value}
400
384
  end
@@ -413,25 +397,24 @@ module Searchkick
413
397
  multi_field = dynamic_fields["{name}"].merge(fields: dynamic_fields.except("{name}"))
414
398
 
415
399
  mappings = {
416
- index_type => {
417
- properties: mapping,
418
- _routing: routing,
419
- # https://gist.github.com/kimchy/2898285
420
- dynamic_templates: [
421
- {
422
- string_template: {
423
- match: "*",
424
- match_mapping_type: "string",
425
- mapping: multi_field
426
- }
400
+ properties: mapping,
401
+ _routing: routing,
402
+ # https://gist.github.com/kimchy/2898285
403
+ dynamic_templates: [
404
+ {
405
+ string_template: {
406
+ match: "*",
407
+ match_mapping_type: "string",
408
+ mapping: multi_field
427
409
  }
428
- ]
429
- }
410
+ }
411
+ ]
430
412
  }
431
413
 
432
- if below60
433
- all_enabled = all && (!options[:searchable] || options[:searchable].to_a.map(&:to_s).include?("_all"))
434
- mappings[index_type][:_all] = all_enabled ? analyzed_field_options : {enabled: false}
414
+ if below70
415
+ index_type = options[:_type]
416
+ index_type = index_type.call if index_type.respond_to?(:call)
417
+ mappings = {index_type => mappings}
435
418
  end
436
419
 
437
420
  mappings = mappings.symbolize_keys.deep_merge((options[:mappings] || {}).symbolize_keys)
@@ -18,7 +18,7 @@ module Searchkick
18
18
  unknown_keywords = options.keys - [:aggs, :block, :body, :body_options, :boost,
19
19
  :boost_by, :boost_by_distance, :boost_by_recency, :boost_where, :conversions, :conversions_term, :debug, :emoji, :exclude, :execute, :explain,
20
20
  :fields, :highlight, :includes, :index_name, :indices_boost, :limit, :load,
21
- :match, :misspellings, :model_includes, :offset, :operator, :order, :padding, :page, :per_page, :profile,
21
+ :match, :misspellings, :models, :model_includes, :offset, :operator, :order, :padding, :page, :per_page, :profile,
22
22
  :request_params, :routing, :scope_results, :select, :similar, :smart_aggs, :suggest, :total_entries, :track, :type, :where]
23
23
  raise ArgumentError, "unknown keywords: #{unknown_keywords.join(", ")}" if unknown_keywords.any?
24
24
 
@@ -39,6 +39,7 @@ module Searchkick
39
39
  @misspellings = false
40
40
  @misspellings_below = nil
41
41
  @highlighted_fields = nil
42
+ @index_mapping = nil
42
43
 
43
44
  prepare
44
45
  end
@@ -56,9 +57,18 @@ module Searchkick
56
57
  end
57
58
 
58
59
  def params
60
+ if options[:models]
61
+ @index_mapping = {}
62
+ Array(options[:models]).each do |model|
63
+ @index_mapping[model.searchkick_index.name] = model
64
+ end
65
+ end
66
+
59
67
  index =
60
68
  if options[:index_name]
61
69
  Array(options[:index_name]).map { |v| v.respond_to?(:searchkick_index) ? v.searchkick_index.name : v }.join(",")
70
+ elsif options[:models]
71
+ @index_mapping.keys.join(",")
62
72
  elsif searchkick_index
63
73
  searchkick_index.name
64
74
  else
@@ -116,8 +126,8 @@ module Searchkick
116
126
  misspellings: @misspellings,
117
127
  term: term,
118
128
  scope_results: options[:scope_results],
119
- index_name: options[:index_name],
120
- total_entries: options[:total_entries]
129
+ total_entries: options[:total_entries],
130
+ index_mapping: @index_mapping
121
131
  }
122
132
 
123
133
  if options[:debug]
@@ -166,7 +176,7 @@ module Searchkick
166
176
  end
167
177
 
168
178
  def retry_misspellings?(response)
169
- @misspellings_below && response["hits"]["total"] < @misspellings_below
179
+ @misspellings_below && Searchkick::Results.new(searchkick_klass, response).total_count < @misspellings_below
170
180
  end
171
181
 
172
182
  private
@@ -377,7 +387,7 @@ module Searchkick
377
387
  queries_to_add.concat(q2)
378
388
  end
379
389
 
380
- queries.concat(queries_to_add)
390
+ queries << queries_to_add
381
391
 
382
392
  if options[:exclude]
383
393
  must_not.concat(set_exclude(exclude_field, exclude_analyzer))
@@ -392,9 +402,10 @@ module Searchkick
392
402
 
393
403
  should = []
394
404
  else
405
+ # higher score for matching more fields
395
406
  payload = {
396
- dis_max: {
397
- queries: queries
407
+ bool: {
408
+ should: queries.map { |qs| {dis_max: {queries: qs}} }
398
409
  }
399
410
  }
400
411
 
@@ -663,20 +674,9 @@ module Searchkick
663
674
  def set_boost_by_indices(payload)
664
675
  return unless options[:indices_boost]
665
676
 
666
- if below52?
667
- indices_boost = options[:indices_boost].each_with_object({}) do |(key, boost), memo|
668
- index = key.respond_to?(:searchkick_index) ? key.searchkick_index.name : key
669
- # try to use index explicitly instead of alias: https://github.com/elasticsearch/elasticsearch/issues/4756
670
- index_by_alias = Searchkick.client.indices.get_alias(index: index).keys.first
671
- memo[index_by_alias || index] = boost
672
- end
673
- else
674
- # array format supports alias resolution
675
- # https://github.com/elastic/elasticsearch/pull/21393
676
- indices_boost = options[:indices_boost].map do |key, boost|
677
- index = key.respond_to?(:searchkick_index) ? key.searchkick_index.name : key
678
- {index => boost}
679
- end
677
+ indices_boost = options[:indices_boost].map do |key, boost|
678
+ index = key.respond_to?(:searchkick_index) ? key.searchkick_index.name : key
679
+ {index => boost}
680
680
  end
681
681
 
682
682
  payload[:indices_boost] = indices_boost
@@ -713,7 +713,7 @@ module Searchkick
713
713
  def set_highlights(payload, fields)
714
714
  payload[:highlight] = {
715
715
  fields: Hash[fields.map { |f| [f, {}] }],
716
- fragment_size: below60? ? 30000 : 0
716
+ fragment_size: 0
717
717
  }
718
718
 
719
719
  if options[:highlight].is_a?(Hash)
@@ -824,7 +824,7 @@ module Searchkick
824
824
  # TODO id transformation for arrays
825
825
  def set_order(payload)
826
826
  order = options[:order].is_a?(Enumerable) ? options[:order] : {options[:order] => :asc}
827
- id_field = below60? ? :_uid : :_id
827
+ id_field = :_id
828
828
  payload[:sort] = order.is_a?(Array) ? order : Hash[order.map { |k, v| [k.to_s == "id" ? id_field : k, v] }]
829
829
  end
830
830
 
@@ -1021,16 +1021,12 @@ module Searchkick
1021
1021
  k.sub(/\.(analyzed|word_start|word_middle|word_end|text_start|text_middle|text_end|exact)\z/, "")
1022
1022
  end
1023
1023
 
1024
- def below52?
1025
- Searchkick.server_below?("5.2.0")
1026
- end
1027
-
1028
- def below60?
1029
- Searchkick.server_below?("6.0.0")
1030
- end
1031
-
1032
1024
  def below61?
1033
1025
  Searchkick.server_below?("6.1.0")
1034
1026
  end
1027
+
1028
+ def below70?
1029
+ Searchkick.server_below?("7.0.0")
1030
+ end
1035
1031
  end
1036
1032
  end
@@ -34,18 +34,13 @@ module Searchkick
34
34
  index.klass_document_type(record.class, ignore_type)
35
35
  end
36
36
 
37
- # memoize
38
- def self.routing_key
39
- @routing_key ||= Searchkick.server_below?("6.0.0") ? :_routing : :routing
40
- end
41
-
42
37
  def record_data
43
38
  data = {
44
39
  _index: index.name,
45
- _id: search_id,
46
- _type: document_type
40
+ _id: search_id
47
41
  }
48
- data[self.class.routing_key] = record.search_routing if record.respond_to?(:search_routing)
42
+ data[:_type] = document_type if Searchkick.server_below7?
43
+ data[:routing] = record.search_routing if record.respond_to?(:search_routing)
49
44
  data
50
45
  end
51
46
 
@@ -25,9 +25,16 @@ module Searchkick
25
25
  # results can have different types
26
26
  results = {}
27
27
 
28
- hits.group_by { |hit, _| hit["_type"] }.each do |type, grouped_hits|
29
- klass = (!options[:index_name] && @klass) || type.camelize.constantize
30
- results[type] = results_query(klass, grouped_hits).to_a.index_by { |r| r.id.to_s }
28
+ hits.group_by { |hit, _| hit["_index"] }.each do |index, grouped_hits|
29
+ klass =
30
+ if @klass
31
+ @klass
32
+ else
33
+ index_alias = index.split("_")[0..-2].join("_")
34
+ (options[:index_mapping] || {})[index_alias]
35
+ end
36
+ raise Searchkick::Error, "Unknown model for index: #{index}" unless klass
37
+ results[index] = results_query(klass, grouped_hits).to_a.index_by { |r| r.id.to_s }
31
38
  end
32
39
 
33
40
  missing_ids = []
@@ -35,7 +42,7 @@ module Searchkick
35
42
  # sort
36
43
  results =
37
44
  hits.map do |hit|
38
- result = results[hit["_type"]][hit["_id"].to_s]
45
+ result = results[hit["_index"]][hit["_id"].to_s]
39
46
  if result && !(options[:load].is_a?(Hash) && options[:load][:dumpable])
40
47
  if (hit["highlight"] || options[:highlight]) && !result.respond_to?(:search_highlights)
41
48
  highlights = hit_highlights(hit)
@@ -132,7 +139,13 @@ module Searchkick
132
139
  end
133
140
 
134
141
  def total_count
135
- options[:total_entries] || response["hits"]["total"]
142
+ if options[:total_entries]
143
+ options[:total_entries]
144
+ elsif response["hits"]["total"].is_a?(Hash)
145
+ response["hits"]["total"]["value"]
146
+ else
147
+ response["hits"]["total"]
148
+ end
136
149
  end
137
150
  alias_method :total_entries, :total_count
138
151
 
@@ -1,3 +1,3 @@
1
1
  module Searchkick
2
- VERSION = "3.1.3"
2
+ VERSION = "4.0.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: searchkick
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.3
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '4.2'
19
+ version: '5'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '4.2'
26
+ version: '5'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: elasticsearch
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '5'
33
+ version: '6'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '5'
40
+ version: '6'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: hashie
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -138,7 +138,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
138
138
  requirements:
139
139
  - - ">="
140
140
  - !ruby/object:Gem::Version
141
- version: '2.2'
141
+ version: '2.4'
142
142
  required_rubygems_version: !ruby/object:Gem::Requirement
143
143
  requirements:
144
144
  - - ">="