chewy 0.8.3 → 0.8.4

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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +43 -11
  3. data/Appraisals +39 -12
  4. data/CHANGELOG.md +42 -0
  5. data/Gemfile +1 -1
  6. data/README.md +60 -7
  7. data/chewy.gemspec +12 -5
  8. data/gemfiles/{rails.4.0.mongoid.gemfile → rails.4.0.mongoid.4.0.0.gemfile} +1 -1
  9. data/gemfiles/{rails.4.0.mongoid.kaminari.gemfile → rails.4.0.mongoid.4.0.0.kaminari.gemfile} +1 -1
  10. data/gemfiles/{rails.4.0.mongoid.will_paginate.gemfile → rails.4.0.mongoid.4.0.0.will_paginate.gemfile} +1 -1
  11. data/gemfiles/rails.4.0.mongoid.5.1.0.gemfile +15 -0
  12. data/gemfiles/rails.4.0.mongoid.5.1.0.kaminari.gemfile +14 -0
  13. data/gemfiles/rails.4.0.mongoid.5.1.0.will_paginate.gemfile +14 -0
  14. data/gemfiles/{rails.4.1.mongoid.gemfile → rails.4.1.mongoid.4.0.0.gemfile} +1 -1
  15. data/gemfiles/{rails.4.1.mongoid.kaminari.gemfile → rails.4.1.mongoid.4.0.0.kaminari.gemfile} +1 -1
  16. data/gemfiles/{rails.4.1.mongoid.will_paginate.gemfile → rails.4.1.mongoid.4.0.0.will_paginate.gemfile} +1 -1
  17. data/gemfiles/rails.4.1.mongoid.5.1.0.gemfile +15 -0
  18. data/gemfiles/rails.4.1.mongoid.5.1.0.kaminari.gemfile +14 -0
  19. data/gemfiles/rails.4.1.mongoid.5.1.0.will_paginate.gemfile +14 -0
  20. data/gemfiles/{rails.4.2.mongoid.gemfile → rails.4.2.mongoid.4.0.0.gemfile} +1 -1
  21. data/gemfiles/{rails.4.2.mongoid.kaminari.gemfile → rails.4.2.mongoid.4.0.0.kaminari.gemfile} +1 -1
  22. data/gemfiles/{rails.4.2.mongoid.will_paginate.gemfile → rails.4.2.mongoid.4.0.0.will_paginate.gemfile} +1 -1
  23. data/gemfiles/rails.4.2.mongoid.5.1.0.gemfile +15 -0
  24. data/gemfiles/rails.4.2.mongoid.5.1.0.kaminari.gemfile +14 -0
  25. data/gemfiles/rails.4.2.mongoid.5.1.0.will_paginate.gemfile +14 -0
  26. data/gemfiles/rails.5.0.0.beta3.activerecord.gemfile +16 -0
  27. data/gemfiles/rails.5.0.0.beta3.activerecord.kaminari.gemfile +16 -0
  28. data/gemfiles/rails.5.0.0.beta3.activerecord.will_paginate.gemfile +15 -0
  29. data/gemfiles/{sequel.4.28.gemfile → sequel.4.31.gemfile} +1 -1
  30. data/lib/chewy.rb +7 -1
  31. data/lib/chewy/errors.rb +6 -0
  32. data/lib/chewy/fields/base.rb +12 -8
  33. data/lib/chewy/fields/root.rb +1 -1
  34. data/lib/chewy/index.rb +17 -8
  35. data/lib/chewy/index/actions.rb +4 -4
  36. data/lib/chewy/query.rb +8 -13
  37. data/lib/chewy/query/compose.rb +2 -2
  38. data/lib/chewy/query/criteria.rb +2 -2
  39. data/lib/chewy/query/loading.rb +1 -1
  40. data/lib/chewy/query/nodes/bool.rb +1 -1
  41. data/lib/chewy/query/nodes/regexp.rb +2 -2
  42. data/lib/chewy/railtie.rb +15 -3
  43. data/lib/chewy/rake_helper.rb +5 -2
  44. data/lib/chewy/rspec/update_index.rb +17 -6
  45. data/lib/chewy/strategy.rb +7 -3
  46. data/lib/chewy/strategy/active_job.rb +2 -2
  47. data/lib/chewy/strategy/resque.rb +2 -2
  48. data/lib/chewy/strategy/sidekiq.rb +2 -2
  49. data/lib/chewy/type.rb +14 -0
  50. data/lib/chewy/type/adapter/active_record.rb +11 -1
  51. data/lib/chewy/type/adapter/orm.rb +13 -11
  52. data/lib/chewy/type/adapter/sequel.rb +10 -12
  53. data/lib/chewy/type/import.rb +53 -22
  54. data/lib/chewy/type/witchcraft.rb +208 -0
  55. data/lib/chewy/type/wrapper.rb +25 -7
  56. data/lib/chewy/version.rb +1 -1
  57. data/lib/tasks/chewy.rake +22 -14
  58. data/spec/chewy/fields/base_spec.rb +6 -2
  59. data/spec/chewy/fields/time_fields_spec.rb +4 -4
  60. data/spec/chewy/index/actions_spec.rb +32 -18
  61. data/spec/chewy/index_spec.rb +19 -0
  62. data/spec/chewy/query/pagination_spec.rb +1 -1
  63. data/spec/chewy/query_spec.rb +77 -21
  64. data/spec/chewy/rspec/update_index_spec.rb +75 -62
  65. data/spec/chewy/runtime_spec.rb +1 -1
  66. data/spec/chewy/strategy/active_job_spec.rb +6 -1
  67. data/spec/chewy/strategy/atomic_spec.rb +5 -5
  68. data/spec/chewy/strategy/resque_spec.rb +7 -2
  69. data/spec/chewy/strategy/sidekiq_spec.rb +6 -1
  70. data/spec/chewy/strategy_spec.rb +13 -1
  71. data/spec/chewy/type/actions_spec.rb +4 -1
  72. data/spec/chewy/type/import_spec.rb +71 -2
  73. data/spec/chewy/type/observe_spec.rb +9 -9
  74. data/spec/chewy/type/witchcraft_spec.rb +154 -0
  75. data/spec/chewy/type/wrapper_spec.rb +30 -5
  76. data/spec/chewy/type_spec.rb +10 -0
  77. data/spec/chewy_spec.rb +29 -5
  78. data/spec/spec_helper.rb +2 -0
  79. data/spec/support/class_helpers.rb +15 -0
  80. data/spec/support/mongoid.rb +5 -0
  81. metadata +64 -21
@@ -2,7 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "mongoid", "~> 4.0.0"
5
+ gem "mongoid", "> 4.0.0"
6
6
  gem "activesupport", "~> 4.1.0"
7
7
  gem "resque", :require => false
8
8
  gem "sidekiq", :require => false
@@ -2,7 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "mongoid", "~> 4.0.0"
5
+ gem "mongoid", "> 4.0.0"
6
6
  gem "activesupport", "~> 4.1.0"
7
7
  gem "kaminari", "0.16.3", :require => false
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "mongoid", "~> 4.0.0"
5
+ gem "mongoid", "> 4.0.0"
6
6
  gem "activesupport", "~> 4.1.0"
7
7
  gem "will_paginate", :require => false
8
8
 
@@ -0,0 +1,15 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "mongoid", "> 5.1.0"
6
+ gem "activesupport", "~> 4.1.0"
7
+ gem "resque", :require => false
8
+ gem "sidekiq", :require => false
9
+
10
+ group :test do
11
+ gem "guard"
12
+ gem "guard-rspec"
13
+ end
14
+
15
+ gemspec :path => "../"
@@ -0,0 +1,14 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "mongoid", "> 5.1.0"
6
+ gem "activesupport", "~> 4.1.0"
7
+ gem "kaminari", "0.16.3", :require => false
8
+
9
+ group :test do
10
+ gem "guard"
11
+ gem "guard-rspec"
12
+ end
13
+
14
+ gemspec :path => "../"
@@ -0,0 +1,14 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "mongoid", "> 5.1.0"
6
+ gem "activesupport", "~> 4.1.0"
7
+ gem "will_paginate", :require => false
8
+
9
+ group :test do
10
+ gem "guard"
11
+ gem "guard-rspec"
12
+ end
13
+
14
+ gemspec :path => "../"
@@ -2,7 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "mongoid", "~> 4.0.0"
5
+ gem "mongoid", "> 4.0.0"
6
6
  gem "activesupport", "~> 4.2.0"
7
7
  gem "resque", :require => false
8
8
  gem "sidekiq", :require => false
@@ -2,7 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "mongoid", "~> 4.0.0"
5
+ gem "mongoid", "> 4.0.0"
6
6
  gem "activesupport", "~> 4.2.0"
7
7
  gem "kaminari", "0.16.3", :require => false
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "mongoid", "~> 4.0.0"
5
+ gem "mongoid", "> 4.0.0"
6
6
  gem "activesupport", "~> 4.2.0"
7
7
  gem "will_paginate", :require => false
8
8
 
@@ -0,0 +1,15 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "mongoid", "> 5.1.0"
6
+ gem "activesupport", "~> 4.2.0"
7
+ gem "resque", :require => false
8
+ gem "sidekiq", :require => false
9
+
10
+ group :test do
11
+ gem "guard"
12
+ gem "guard-rspec"
13
+ end
14
+
15
+ gemspec :path => "../"
@@ -0,0 +1,14 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "mongoid", "> 5.1.0"
6
+ gem "activesupport", "~> 4.2.0"
7
+ gem "kaminari", "0.16.3", :require => false
8
+
9
+ group :test do
10
+ gem "guard"
11
+ gem "guard-rspec"
12
+ end
13
+
14
+ gemspec :path => "../"
@@ -0,0 +1,14 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "mongoid", "> 5.1.0"
6
+ gem "activesupport", "~> 4.2.0"
7
+ gem "will_paginate", :require => false
8
+
9
+ group :test do
10
+ gem "guard"
11
+ gem "guard-rspec"
12
+ end
13
+
14
+ gemspec :path => "../"
@@ -0,0 +1,16 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 5.0.0.beta3"
6
+ gem "activesupport", "~> 5.0.0.beta3"
7
+ gem "activejob", "~> 5.0.0.beta3"
8
+ gem "resque", :require => false
9
+ gem "sidekiq", :require => false
10
+
11
+ group :test do
12
+ gem "guard"
13
+ gem "guard-rspec"
14
+ end
15
+
16
+ gemspec :path => "../"
@@ -0,0 +1,16 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 5.0.0.beta3"
6
+ gem "activesupport", "~> 5.0.0.beta3"
7
+ gem "activejob", "~> 5.0.0.beta3"
8
+ gem "actionpack", "~> 5.0.0.beta3"
9
+ gem "kaminari", "0.16.3", :require => false
10
+
11
+ group :test do
12
+ gem "guard"
13
+ gem "guard-rspec"
14
+ end
15
+
16
+ gemspec :path => "../"
@@ -0,0 +1,15 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 5.0.0.beta3"
6
+ gem "activesupport", "~> 5.0.0.beta3"
7
+ gem "activejob", "~> 5.0.0.beta3"
8
+ gem "will_paginate", :require => false
9
+
10
+ group :test do
11
+ gem "guard"
12
+ gem "guard-rspec"
13
+ end
14
+
15
+ gemspec :path => "../"
@@ -2,7 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "sequel", "~> 4.28.0"
5
+ gem "sequel", "~> 4.31.0"
6
6
  gem "activesupport", "~> 4.2.0"
7
7
 
8
8
  group :test do
@@ -8,6 +8,7 @@ require 'active_support/core_ext/array/wrap'
8
8
  require 'active_support/core_ext/enumerable'
9
9
  require 'active_support/core_ext/hash/reverse_merge'
10
10
  require 'active_support/core_ext/numeric/time'
11
+ require 'active_support/core_ext/numeric/bytes'
11
12
  require 'active_support/core_ext/object/blank'
12
13
  require 'active_support/core_ext/object/inclusion'
13
14
  require 'active_support/core_ext/string/inflections'
@@ -122,7 +123,12 @@ module Chewy
122
123
  # Main elasticsearch-ruby client instance
123
124
  #
124
125
  def client
125
- Thread.current[:chewy_client] ||= ::Elasticsearch::Client.new configuration
126
+ Thread.current[:chewy_client] ||= begin
127
+ client_configuration = configuration.deep_dup
128
+ client_configuration.delete(:prefix) # used by Chewy, not relevant to Elasticsearch::Client
129
+ block = client_configuration[:transport_options].try(:delete, :proc)
130
+ ::Elasticsearch::Client.new(client_configuration, &block)
131
+ end
126
132
  end
127
133
 
128
134
  # Sends wait_for_status request to ElasticSearch with status
@@ -36,4 +36,10 @@ Please wrap your code with `Chewy.strategy(:strategy_name) block.`
36
36
  super message
37
37
  end
38
38
  end
39
+
40
+ class RemovedFeature < Error
41
+ end
42
+
43
+ class PluginMissing < Error
44
+ end
39
45
  end
@@ -11,19 +11,19 @@ module Chewy
11
11
  end
12
12
 
13
13
  def multi_field?
14
- children.any? && !object_field?
14
+ children.present? && !object_field?
15
15
  end
16
16
 
17
17
  def object_field?
18
- (children.any? && options[:type].blank?) || ['object', 'nested'].include?(options[:type].to_s)
18
+ (children.present? && options[:type].blank?) || ['object', 'nested'].include?(options[:type].to_s)
19
19
  end
20
20
 
21
21
  def mappings_hash
22
- mapping = children.any? ? {
22
+ mapping = children.present? ? {
23
23
  (multi_field? ? :fields : :properties) => children.map(&:mappings_hash).inject(:merge)
24
24
  } : {}
25
25
  mapping.reverse_merge!(options)
26
- mapping.reverse_merge!(type: (children.any? ? 'object' : 'string'))
26
+ mapping.reverse_merge!(type: (children.present? ? 'object' : 'string'))
27
27
  {name => mapping}
28
28
  end
29
29
 
@@ -39,16 +39,20 @@ module Chewy
39
39
  value.call(*objects.first(value.arity))
40
40
  end
41
41
  elsif object.is_a?(Hash)
42
- object[name] || object[name.to_s]
42
+ if object.has_key?(name)
43
+ object[name]
44
+ else
45
+ object[name.to_s]
46
+ end
43
47
  else
44
48
  object.send(name)
45
49
  end
46
50
 
47
51
  result = if result.respond_to?(:to_ary)
48
- result.to_ary.map { |result| compose_children(result, *objects) }
52
+ result.to_ary.map { |item| compose_children(item, *objects) }
49
53
  else
50
54
  compose_children(result, *objects)
51
- end if children.any? && !multi_field?
55
+ end if children.present? && !multi_field?
52
56
 
53
57
  {name => result.as_json(root: false)}
54
58
  end
@@ -56,7 +60,7 @@ module Chewy
56
60
  private
57
61
 
58
62
  def compose_children(value, *parent_objects)
59
- children.map { |field| field.compose(value, *parent_objects) if value }.compact.inject(:merge)
63
+ children.map { |field| field.compose(value, *parent_objects) }.compact.inject(:merge) if value
60
64
  end
61
65
  end
62
66
  end
@@ -21,7 +21,7 @@ module Chewy
21
21
  mappings = super
22
22
  mappings[name].delete(:type)
23
23
 
24
- if dynamic_templates.any?
24
+ if dynamic_templates.present?
25
25
  mappings[name][:dynamic_templates] ||= []
26
26
  mappings[name][:dynamic_templates].concat dynamic_templates
27
27
  end
@@ -30,18 +30,24 @@ module Chewy
30
30
  #
31
31
  def self.index_name(suggest = nil)
32
32
  if suggest
33
- @index_name = build_index_name(suggest, prefix: Chewy.configuration[:prefix])
33
+ @index_name = build_index_name(suggest, prefix: default_prefix)
34
34
  else
35
35
  @index_name ||= begin
36
36
  build_index_name(
37
37
  name.sub(/Index\Z/, '').demodulize.underscore,
38
- prefix: Chewy.configuration[:prefix]
38
+ prefix: default_prefix
39
39
  ) if name
40
40
  end
41
41
  end
42
42
  @index_name or raise UndefinedIndex
43
43
  end
44
44
 
45
+ # Prefix to use
46
+ #
47
+ def self.default_prefix
48
+ Chewy.configuration[:prefix]
49
+ end
50
+
45
51
  # Defines type for the index. Arguments depends on adapter used. For
46
52
  # ActiveRecord you can pass model or scope and options
47
53
  #
@@ -80,11 +86,14 @@ module Chewy
80
86
  type_class = Chewy.create_type(self, target, options, &block)
81
87
  self.type_hash = type_hash.merge(type_class.type_name => type_class)
82
88
 
83
- class_eval <<-METHOD, __FILE__, __LINE__ + 1
84
- def self.#{type_class.type_name}
85
- type_hash['#{type_class.type_name}']
86
- end
87
- METHOD
89
+ unless respond_to?(type_class.type_name)
90
+ class_eval <<-METHOD, __FILE__, __LINE__ + 1
91
+ def self.#{type_class.type_name}
92
+ ActiveSupport::Deprecation.warn("`#{self}.#{type_class.type_name}` accessor is deprecated and will be removed soon. Use `#{type_class}` directly instead.")
93
+ type_hash['#{type_class.type_name}']
94
+ end
95
+ METHOD
96
+ end
88
97
  end
89
98
 
90
99
  # Types method has double usage.
@@ -99,7 +108,7 @@ module Chewy
99
108
  # UsersIndex.types(:admin, :manager).filters { name =~ 'ro' } # the same as the first example
100
109
  #
101
110
  def self.types *args
102
- if args.any?
111
+ if args.present?
103
112
  all.types *args
104
113
  else
105
114
  type_hash.values
@@ -24,8 +24,8 @@ module Chewy
24
24
  # method creates index with suffix and makes unsuffixed alias
25
25
  # for it.
26
26
  #
27
- # UsersIndex.create '01-2013' # creates index `uses_01-2013` and alias `users` for it
28
- # UsersIndex.create '01-2013', alias: false # creates index `uses_01-2013` only and no alias
27
+ # UsersIndex.create '01-2013' # creates index `users_01-2013` and alias `users` for it
28
+ # UsersIndex.create '01-2013', alias: false # creates index `users_01-2013` only and no alias
29
29
  #
30
30
  # Suffixed index names might be used for zero-downtime mapping change, for example.
31
31
  # Description: (http://www.elasticsearch.org/blog/changing-mapping-with-zero-downtime/).
@@ -161,7 +161,7 @@ module Chewy
161
161
  # UsersIndex.reset! Time.now.to_i
162
162
  #
163
163
  def reset! suffix = nil
164
- if suffix.present? && (indexes = self.indexes).any?
164
+ if suffix.present? && (indexes = self.indexes).present?
165
165
  create! suffix, alias: false
166
166
  result = import suffix: suffix
167
167
  client.indices.update_aliases body: {actions: [
@@ -170,7 +170,7 @@ module Chewy
170
170
  end,
171
171
  {add: {index: build_index_name(suffix: suffix), alias: index_name}}
172
172
  ]}
173
- client.indices.delete index: indexes if indexes.any?
173
+ client.indices.delete index: indexes if indexes.present?
174
174
  result
175
175
  else
176
176
  purge! suffix
@@ -18,16 +18,6 @@ module Chewy
18
18
  include Loading
19
19
  include Pagination
20
20
 
21
- RESULT_MERGER = lambda do |key, old_value, new_value|
22
- if old_value.is_a?(Hash) && new_value.is_a?(Hash)
23
- old_value.merge(new_value, &RESULT_MERGER)
24
- elsif new_value.is_a?(Array) && new_value.count > 1
25
- new_value
26
- else
27
- old_value.is_a?(Array) ? new_value : new_value.first
28
- end
29
- end
30
-
31
21
  delegate :each, :count, :size, to: :_collection
32
22
  alias_method :to_ary, :to_a
33
23
 
@@ -353,6 +343,7 @@ module Chewy
353
343
  # Returns empty hash if no facets was requested or resulted.
354
344
  #
355
345
  def facets params = nil
346
+ raise RemovedFeature, 'removed in elasticsearch 2.0' if Runtime.version >= '2.0'
356
347
  if params
357
348
  chain { criteria.update_facets params }
358
349
  else
@@ -906,6 +897,10 @@ module Chewy
906
897
  # UsersIndex::User.filter{ age <= 42 }.delete_all
907
898
  #
908
899
  def delete_all
900
+ if Runtime.version > '2.0'
901
+ plugins = Chewy.client.nodes.info(plugins: true)["nodes"].values.map { |item| item["plugins"] }.flatten
902
+ raise PluginMissing, "install delete-by-query plugin" unless plugins.find { |item| item["name"] == 'delete-by-query' }
903
+ end
909
904
  request = chain { criteria.update_options simple: true }.send(:_request)
910
905
  ActiveSupport::Notifications.instrument 'delete_query.chewy',
911
906
  request: request, indexes: _indexes, types: _types,
@@ -992,7 +987,7 @@ module Chewy
992
987
  begin
993
988
  Chewy.client.search(_request)
994
989
  rescue Elasticsearch::Transport::Transport::Errors::NotFound => e
995
- raise e if e.message !~ /IndexMissingException/
990
+ raise e if e.message !~ /IndexMissingException/ && e.message !~ /index_not_found_exception/
996
991
  {}
997
992
  end
998
993
  end
@@ -1000,8 +995,8 @@ module Chewy
1000
995
 
1001
996
  def _results
1002
997
  @_results ||= (criteria.none? || _response == {} ? [] : _response['hits']['hits']).map do |hit|
1003
- attributes = (hit['_source'] || {}).merge(hit['highlight'] || {}, &RESULT_MERGER)
1004
- attributes.reverse_merge!(id: hit['_id'])
998
+ attributes = (hit['_source'] || {})
999
+ .reverse_merge(id: hit['_id'])
1005
1000
  .merge!(_score: hit['_score'])
1006
1001
  .merge!(_explanation: hit['_explanation'])
1007
1002