chewy 0.5.2 → 0.6.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.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +26 -4
  3. data/CHANGELOG.md +16 -0
  4. data/Gemfile +3 -1
  5. data/README.md +2 -10
  6. data/chewy.gemspec +0 -1
  7. data/gemfiles/Gemfile.rails-3.2.active_record +6 -0
  8. data/gemfiles/Gemfile.rails-3.2.active_record.kaminari +7 -0
  9. data/gemfiles/Gemfile.rails-3.2.active_record.will_paginate +7 -0
  10. data/gemfiles/Gemfile.rails-4.0.active_record +6 -0
  11. data/gemfiles/Gemfile.rails-4.0.active_record.kaminari +7 -0
  12. data/gemfiles/Gemfile.rails-4.0.active_record.will_paginate +7 -0
  13. data/gemfiles/Gemfile.rails-4.0.mongoid +6 -0
  14. data/gemfiles/Gemfile.rails-4.0.mongoid.kaminari +7 -0
  15. data/gemfiles/Gemfile.rails-4.0.mongoid.will_paginate +7 -0
  16. data/gemfiles/Gemfile.rails-4.1.active_record +6 -0
  17. data/gemfiles/Gemfile.rails-4.1.active_record.kaminari +7 -0
  18. data/gemfiles/Gemfile.rails-4.1.active_record.will_paginate +7 -0
  19. data/gemfiles/Gemfile.rails-4.1.mongoid +6 -0
  20. data/gemfiles/Gemfile.rails-4.1.mongoid.kaminari +7 -0
  21. data/gemfiles/Gemfile.rails-4.1.mongoid.will_paginate +7 -0
  22. data/gemfiles/Gemfile.rails-4.2.active_record +6 -0
  23. data/gemfiles/Gemfile.rails-4.2.active_record.kaminari +7 -0
  24. data/gemfiles/Gemfile.rails-4.2.active_record.will_paginate +7 -0
  25. data/gemfiles/Gemfile.rails-4.2.mongoid +6 -0
  26. data/gemfiles/Gemfile.rails-4.2.mongoid.kaminari +7 -0
  27. data/gemfiles/Gemfile.rails-4.2.mongoid.will_paginate +7 -0
  28. data/lib/chewy.rb +33 -5
  29. data/lib/chewy/config.rb +1 -0
  30. data/lib/chewy/index/search.rb +6 -3
  31. data/lib/chewy/query.rb +74 -1
  32. data/lib/chewy/query/compose.rb +4 -4
  33. data/lib/chewy/query/pagination.rb +5 -4
  34. data/lib/chewy/query/pagination/kaminari.rb +1 -1
  35. data/lib/chewy/query/pagination/will_paginate.rb +27 -0
  36. data/lib/chewy/type.rb +1 -0
  37. data/lib/chewy/type/adapter/active_record.rb +2 -2
  38. data/lib/chewy/type/adapter/mongoid.rb +147 -0
  39. data/lib/chewy/type/adapter/object.rb +1 -1
  40. data/lib/chewy/type/import.rb +1 -0
  41. data/lib/chewy/type/observe.rb +34 -6
  42. data/lib/chewy/version.rb +1 -1
  43. data/spec/chewy/config_spec.rb +17 -17
  44. data/spec/chewy/fields/base_spec.rb +62 -62
  45. data/spec/chewy/fields/root_spec.rb +5 -5
  46. data/spec/chewy/index/actions_spec.rb +127 -127
  47. data/spec/chewy/index/aliases_spec.rb +9 -9
  48. data/spec/chewy/index/search_spec.rb +4 -4
  49. data/spec/chewy/index/settings_spec.rb +33 -33
  50. data/spec/chewy/index_spec.rb +49 -49
  51. data/spec/chewy/query/criteria_spec.rb +173 -161
  52. data/spec/chewy/query/filters_spec.rb +76 -76
  53. data/spec/chewy/query/loading_spec.rb +54 -23
  54. data/spec/chewy/query/nodes/and_spec.rb +4 -4
  55. data/spec/chewy/query/nodes/bool_spec.rb +8 -8
  56. data/spec/chewy/query/nodes/equal_spec.rb +19 -19
  57. data/spec/chewy/query/nodes/exists_spec.rb +6 -6
  58. data/spec/chewy/query/nodes/has_child_spec.rb +25 -25
  59. data/spec/chewy/query/nodes/has_parent_spec.rb +25 -25
  60. data/spec/chewy/query/nodes/match_all_spec.rb +1 -1
  61. data/spec/chewy/query/nodes/missing_spec.rb +4 -4
  62. data/spec/chewy/query/nodes/not_spec.rb +4 -4
  63. data/spec/chewy/query/nodes/or_spec.rb +4 -4
  64. data/spec/chewy/query/nodes/prefix_spec.rb +5 -5
  65. data/spec/chewy/query/nodes/query_spec.rb +2 -2
  66. data/spec/chewy/query/nodes/range_spec.rb +18 -18
  67. data/spec/chewy/query/nodes/raw_spec.rb +1 -1
  68. data/spec/chewy/query/nodes/regexp_spec.rb +18 -18
  69. data/spec/chewy/query/nodes/script_spec.rb +4 -4
  70. data/spec/chewy/query/pagination/kaminari_spec.rb +41 -39
  71. data/spec/chewy/query/pagination/will_paginage_spec.rb +60 -0
  72. data/spec/chewy/query/pagination_spec.rb +8 -7
  73. data/spec/chewy/query_spec.rb +166 -167
  74. data/spec/chewy/rspec/update_index_spec.rb +1 -1
  75. data/spec/chewy/runtime/version_spec.rb +30 -30
  76. data/spec/chewy/runtime_spec.rb +3 -3
  77. data/spec/chewy/type/actions_spec.rb +3 -3
  78. data/spec/chewy/type/adapter/active_record_spec.rb +143 -143
  79. data/spec/chewy/type/adapter/mongoid_spec.rb +219 -0
  80. data/spec/chewy/type/adapter/object_spec.rb +39 -39
  81. data/spec/chewy/type/import_spec.rb +67 -37
  82. data/spec/chewy/type/mapping_spec.rb +12 -12
  83. data/spec/chewy/type/observe_spec.rb +5 -6
  84. data/spec/chewy/type/wrapper_spec.rb +12 -12
  85. data/spec/chewy_spec.rb +26 -28
  86. data/spec/spec_helper.rb +19 -31
  87. data/spec/support/active_record.rb +52 -0
  88. data/spec/support/class_helpers.rb +0 -4
  89. data/spec/support/mongoid.rb +87 -0
  90. metadata +33 -18
  91. data/gemfiles/Gemfile.rails-3.2 +0 -15
  92. data/gemfiles/Gemfile.rails-4.0 +0 -15
@@ -30,11 +30,11 @@ module Chewy
30
30
  def _queries_join queries, logic
31
31
  queries = queries.compact
32
32
 
33
- if queries.many?
33
+ if queries.many? || (queries.any? && logic == :must_not)
34
34
  case logic
35
35
  when :dis_max
36
36
  { dis_max: { queries: queries } }
37
- when :must, :should
37
+ when :must, :should, :must_not
38
38
  { bool: { logic => queries } }
39
39
  else
40
40
  if logic.is_a?(Float)
@@ -51,11 +51,11 @@ module Chewy
51
51
  def _filters_join filters, logic
52
52
  filters = filters.compact
53
53
 
54
- if filters.many?
54
+ if filters.many? || (filters.any? && logic == :must_not)
55
55
  case logic
56
56
  when :and, :or
57
57
  { logic => filters }
58
- when :must, :should
58
+ when :must, :should, :must_not
59
59
  { bool: { logic => filters } }
60
60
  else
61
61
  { bool: { should: filters, minimum_should_match: logic } }
@@ -3,13 +3,14 @@ module Chewy
3
3
  module Pagination
4
4
  # Returns request total found documents count
5
5
  #
6
- # PlacesIndex.query(...).filter(...).total_count
6
+ # PlacesIndex.query(...).filter(...).total
7
7
  #
8
- def total_count
8
+ def total
9
9
  _response['hits'].try(:[], 'total') || 0
10
10
  end
11
+
12
+ alias_method :total_count, :total
13
+ alias_method :total_entries, :total
11
14
  end
12
15
  end
13
16
  end
14
-
15
- require 'chewy/query/pagination/kaminari' if defined?(::Kaminari)
@@ -34,4 +34,4 @@ module Chewy
34
34
  end
35
35
  end
36
36
 
37
- Chewy::Query::Pagination.send :include, Chewy::Query::Pagination::Kaminari
37
+ Chewy::Query.send :include, Chewy::Query::Pagination::Kaminari
@@ -0,0 +1,27 @@
1
+ module Chewy
2
+ class Query
3
+ module Pagination
4
+ module WillPaginate
5
+ extend ActiveSupport::Concern
6
+ include ::WillPaginate::CollectionMethods
7
+
8
+ attr_reader :current_page, :per_page
9
+
10
+ def paginate(options={})
11
+ @current_page = ::WillPaginate::PageNumber(options[:page] || @current_page || 1)
12
+ @page_multiplier = @current_page - 1
13
+ @per_page = (options[:per_page] || @per_page || ::WillPaginate.per_page).to_i
14
+
15
+ #call Chewy::Query methods to limit results
16
+ limit(@per_page).offset(@page_multiplier * @per_page)
17
+ end
18
+
19
+ def page(page)
20
+ paginate(page: page)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ Chewy::Query.send :include, Chewy::Query::Pagination::WillPaginate
@@ -6,6 +6,7 @@ require 'chewy/type/actions'
6
6
  require 'chewy/type/import'
7
7
  require 'chewy/type/adapter/object'
8
8
  require 'chewy/type/adapter/active_record'
9
+ require 'chewy/type/adapter/mongoid'
9
10
 
10
11
  module Chewy
11
12
  class Type
@@ -72,7 +72,7 @@ module Chewy
72
72
  result
73
73
  else
74
74
  if collection.all? { |object| object.respond_to?(:id) }
75
- collection.in_groups_of(import_options[:batch_size], false).map do |group|
75
+ collection.each_slice(import_options[:batch_size]).map do |group|
76
76
  block.call grouped_objects(group)
77
77
  end.all?
78
78
  else
@@ -112,7 +112,7 @@ module Chewy
112
112
  indexed &= block.call(grouped_objects(objects))
113
113
  end
114
114
 
115
- deleted = ids.in_groups_of(import_options[:batch_size], false).map do |group|
115
+ deleted = ids.each_slice(import_options[:batch_size]).map do |group|
116
116
  block.call(delete: group)
117
117
  end.all?
118
118
 
@@ -0,0 +1,147 @@
1
+ require 'chewy/type/adapter/base'
2
+
3
+ module Chewy
4
+ class Type
5
+ module Adapter
6
+ class Mongoid < Base
7
+ def initialize *args
8
+ @options = args.extract_options!
9
+ subject = args.first
10
+ if subject.is_a?(::Mongoid::Criteria)
11
+ @model = subject.klass
12
+ @scope = subject
13
+ else
14
+ @model = subject
15
+ end
16
+ end
17
+
18
+ def name
19
+ @name ||= (options[:name].present? ? options[:name].to_s.camelize : model.model_name.to_s).demodulize
20
+ end
21
+
22
+ # Import method for Mongoid takes import data and import options
23
+ #
24
+ # Import data types:
25
+ #
26
+ # * Nothing passed - imports all the model data
27
+ # * ActiveRecord scope
28
+ # * Objects collection
29
+ # * Ids collection
30
+ #
31
+ # Import options:
32
+ #
33
+ # <tt>:batch_size</tt> - import batch size, 1000 objects by default
34
+ #
35
+ # Method handles destroyed objects as well. In case of objects AcriveRecord::Relation
36
+ # or array passed, objects, responding with true to `destroyed?` method will be deleted
37
+ # from index. In case of ids array passed - documents with missing records ids will be
38
+ # deleted from index:
39
+ #
40
+ # users = User.all
41
+ # users.each { |user| user.destroy if user.incative? }
42
+ # UsersIndex::User.import users # inactive users will be deleted from index
43
+ # # or
44
+ # UsersIndex::User.import users.map(&:id) # deleted user ids will be deleted from index
45
+ #
46
+ # Also there is custom API method `delete_from_index?`. It it returns `true`
47
+ # object will be deleted from index. Note that if this method is defined and
48
+ # return `false` Chewy will still check `destroyed?` method. This is useful
49
+ # for paranoid objects sdeleting implementation.
50
+ #
51
+ # class User
52
+ # alias_method :delete_from_index?, :deleted_at?
53
+ # end
54
+ #
55
+ # users = User.all
56
+ # users.each { |user| user.deleted_at = Time.now }
57
+ # UsersIndex::User.import users # paranoid deleted users will be deleted from index
58
+ # # or
59
+ # UsersIndex::User.import users.map(&:id) # user ids will be deleted from index
60
+ #
61
+ def import *args, &block
62
+ import_options = args.extract_options!
63
+ import_options[:batch_size] ||= BATCH_SIZE
64
+ batch_size = import_options[:batch_size]
65
+
66
+ collection = args.none? ? model_all :
67
+ (args.one? && args.first.is_a?(::Mongoid::Criteria) ? args.first : args.flatten.compact)
68
+
69
+ if collection.is_a?(::Mongoid::Criteria)
70
+ result = true
71
+ merged_scope(collection).batch_size(batch_size).no_timeout.each_slice(batch_size) do |batch|
72
+ result &= block.call grouped_objects(batch)
73
+ end
74
+ result
75
+ else
76
+ if collection.all? { |object| object.respond_to?(:id) }
77
+ collection.each_slice(batch_size).map do |group|
78
+ block.call grouped_objects(group)
79
+ end.all?
80
+ else
81
+ import_ids(collection, import_options, &block)
82
+ end
83
+ end
84
+ end
85
+
86
+ def load *args
87
+ load_options = args.extract_options!
88
+ objects = args.flatten
89
+
90
+ additional_scope = load_options[load_options[:_type].type_name.to_sym].try(:[], :scope) || load_options[:scope]
91
+
92
+ scope = scoped_model(objects.map(&:id))
93
+ loaded_objects = if additional_scope.is_a?(Proc)
94
+ scope.instance_exec(&additional_scope)
95
+ elsif additional_scope.is_a?(::Mongoid::Criteria)
96
+ scope.merge(additional_scope)
97
+ else
98
+ scope
99
+ end.index_by { |object| object.id.to_s }
100
+
101
+ objects.map { |object| loaded_objects[object.id.to_s] }
102
+ end
103
+
104
+ private
105
+
106
+ attr_reader :model, :scope, :options
107
+
108
+ def import_ids(ids, import_options = {}, &block)
109
+ ids.uniq!
110
+ batch_size = import_options[:batch_size] || BATCH_SIZE
111
+
112
+ indexed = true
113
+ merged_scope(scoped_model(ids)).batch_size(batch_size).no_timeout.each_slice(batch_size) do |batch|
114
+ ids -= batch.map(&:id)
115
+ indexed &= block.call(grouped_objects(batch))
116
+ end
117
+
118
+ deleted = ids.each_slice(batch_size).map do |group|
119
+ block.call(delete: group)
120
+ end.all?
121
+
122
+ indexed && deleted
123
+ end
124
+
125
+ def grouped_objects(objects)
126
+ objects.group_by do |object|
127
+ delete = object.delete_from_index? if object.respond_to?(:delete_from_index?)
128
+ delete ||= object.destroyed?
129
+ delete ? :delete : :index
130
+ end
131
+ end
132
+
133
+ def merged_scope(target)
134
+ scope ? scope.clone.merge(target) : target
135
+ end
136
+
137
+ def scoped_model(ids)
138
+ model.where(:_id.in => ids)
139
+ end
140
+
141
+ def model_all
142
+ model.all
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
@@ -33,7 +33,7 @@ module Chewy
33
33
  batch_size = import_options.delete(:batch_size) || BATCH_SIZE
34
34
  objects = args.flatten.compact
35
35
 
36
- objects.in_groups_of(batch_size, false).map do |group|
36
+ objects.each_slice(batch_size).map do |group|
37
37
  action_groups = group.group_by do |object|
38
38
  raise "Object is not a `#{target}`" if class_target? && !object.is_a?(target)
39
39
  delete = object.delete_from_index? if object.respond_to?(:delete_from_index?)
@@ -84,6 +84,7 @@ module Chewy
84
84
  entry = {}
85
85
 
86
86
  entry[:_id] = object.respond_to?(:id) ? object.id : object
87
+ entry[:_id] = entry[:_id].to_s if defined?(BSON) && entry[:_id].is_a?(BSON::ObjectId)
87
88
  entry[:data] = object_data(object) unless action == :delete
88
89
 
89
90
  if self.root_object.parent_id
@@ -3,14 +3,35 @@ module Chewy
3
3
  module Observe
4
4
  extend ActiveSupport::Concern
5
5
 
6
+ module MongoidMethods
7
+ def update_index(type_name, *args, &block)
8
+ options = args.extract_options!
9
+ method = args.first
10
+
11
+ update = Proc.new do
12
+ backreference = if method && method.to_s == 'self'
13
+ self
14
+ elsif method
15
+ send(method)
16
+ else
17
+ instance_eval(&block)
18
+ end
19
+
20
+ Chewy.derive_type(type_name).update_index(backreference, options)
21
+ end
22
+
23
+ after_save &update
24
+ after_destroy &update
25
+ end
26
+ end
27
+
6
28
  module ActiveRecordMethods
7
29
  def update_index(type_name, *args, &block)
8
30
  options = args.extract_options!
9
31
  method = args.first
10
32
 
11
33
  update = Proc.new do
12
- update_options = options.reverse_merge(urgent: Chewy.urgent_update)
13
- clear_association_cache if update_options[:urgent]
34
+ clear_association_cache if Chewy.urgent_update
14
35
 
15
36
  backreference = if method && method.to_s == 'self'
16
37
  self
@@ -20,7 +41,7 @@ module Chewy
20
41
  instance_eval(&block)
21
42
  end
22
43
 
23
- Chewy.derive_type(type_name).update_index(backreference, update_options)
44
+ Chewy.derive_type(type_name).update_index(backreference, options)
24
45
  end
25
46
 
26
47
  after_save &update
@@ -31,14 +52,21 @@ module Chewy
31
52
  module ClassMethods
32
53
  def update_index(objects, options = {})
33
54
  if Chewy.atomic?
34
- ids = if objects.is_a?(::ActiveRecord::Relation)
55
+ relation = (defined?(::ActiveRecord) && objects.is_a?(::ActiveRecord::Relation)) ||
56
+ (defined?(::Mongoid) && objects.is_a?(::Mongoid::Criteria))
57
+
58
+ ids = if relation
35
59
  objects.pluck(:id)
36
60
  else
37
61
  Array.wrap(objects).map { |object| object.respond_to?(:id) ? object.id : object.to_i }
38
62
  end
63
+
39
64
  Chewy.stash self, ids
40
- else
41
- import(objects) if options[:urgent]
65
+ elsif options[:urgent]
66
+ ActiveSupport::Deprecation.warn("`urgent: true` option is deprecated and will be removed soon, use `Chewy.atomic` block instead")
67
+ import(objects)
68
+ elsif Chewy.urgent_update
69
+ import(objects)
42
70
  end if objects
43
71
 
44
72
  true
@@ -1,3 +1,3 @@
1
1
  module Chewy
2
- VERSION = '0.5.2'
2
+ VERSION = '0.6.0'
3
3
  end
@@ -14,42 +14,42 @@ describe Chewy::Config do
14
14
  its(:char_filters) { should == {} }
15
15
 
16
16
  describe '#analyzer' do
17
- specify { subject.analyzer(:name).should be_nil }
17
+ specify { expect(subject.analyzer(:name)).to be_nil }
18
18
 
19
19
  context do
20
20
  before { subject.analyzer(:name, option: :foo) }
21
- specify { subject.analyzer(:name).should == {option: :foo} }
22
- specify { subject.analyzers.should == {name: {option: :foo}} }
21
+ specify { expect(subject.analyzer(:name)).to eq({option: :foo}) }
22
+ specify { expect(subject.analyzers).to eq({name: {option: :foo}}) }
23
23
  end
24
24
  end
25
25
 
26
26
  describe '#tokenizer' do
27
- specify { subject.tokenizer(:name).should be_nil }
27
+ specify { expect(subject.tokenizer(:name)).to be_nil }
28
28
 
29
29
  context do
30
30
  before { subject.tokenizer(:name, option: :foo) }
31
- specify { subject.tokenizer(:name).should == {option: :foo} }
32
- specify { subject.tokenizers.should == {name: {option: :foo}} }
31
+ specify { expect(subject.tokenizer(:name)).to eq({option: :foo}) }
32
+ specify { expect(subject.tokenizers).to eq({name: {option: :foo}}) }
33
33
  end
34
34
  end
35
35
 
36
36
  describe '#filter' do
37
- specify { subject.filter(:name).should be_nil }
37
+ specify { expect(subject.filter(:name)).to be_nil }
38
38
 
39
39
  context do
40
40
  before { subject.filter(:name, option: :foo) }
41
- specify { subject.filter(:name).should == {option: :foo} }
42
- specify { subject.filters.should == {name: {option: :foo}} }
41
+ specify { expect(subject.filter(:name)).to eq({option: :foo}) }
42
+ specify { expect(subject.filters).to eq({name: {option: :foo}}) }
43
43
  end
44
44
  end
45
45
 
46
46
  describe '#char_filter' do
47
- specify { subject.char_filter(:name).should be_nil }
47
+ specify { expect(subject.char_filter(:name)).to be_nil }
48
48
 
49
49
  context do
50
50
  before { subject.char_filter(:name, option: :foo) }
51
- specify { subject.char_filter(:name).should == {option: :foo} }
52
- specify { subject.char_filters.should == {name: {option: :foo}} }
51
+ specify { expect(subject.char_filter(:name)).to eq({option: :foo}) }
52
+ specify { expect(subject.char_filters).to eq({name: {option: :foo}}) }
53
53
  end
54
54
  end
55
55
 
@@ -62,8 +62,8 @@ describe Chewy::Config do
62
62
 
63
63
  describe '#atomic?' do
64
64
  its(:atomic?) { should eq(false) }
65
- specify { subject.atomic { subject.atomic?.should eq(true) } }
66
- specify { subject.atomic { }; subject.atomic?.should eq(false) }
65
+ specify { subject.atomic { expect(subject.atomic?).to eq(true) } }
66
+ specify { subject.atomic { }; expect(subject.atomic?).to eq(false) }
67
67
  end
68
68
 
69
69
  describe '#atomic' do
@@ -74,9 +74,9 @@ describe Chewy::Config do
74
74
  end
75
75
  let(:dummy_type) { DummiesIndex::Dummy }
76
76
 
77
- specify { subject.atomic { 42 }.should == 42 }
77
+ specify { expect(subject.atomic { 42 }).to eq(42) }
78
78
  specify { expect { subject.atomic { subject.stash Class.new, 42 } }.to raise_error ArgumentError }
79
- specify { subject.atomic { subject.atomic { subject.stash.should == [{}, {}] } } }
79
+ specify { subject.atomic { subject.atomic { expect(subject.stash).to eq([{}, {}]) } } }
80
80
 
81
81
  specify do
82
82
  expect(dummy_type).to receive(:import).with([1, 2, 3]).once
@@ -107,6 +107,6 @@ describe Chewy::Config do
107
107
  end
108
108
 
109
109
  describe '#stash' do
110
- specify { subject.atomic { subject.stash.should == [{}] } }
110
+ specify { subject.atomic { expect(subject.stash).to eq([{}]) } }
111
111
  end
112
112
  end
@@ -1,16 +1,16 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Chewy::Fields::Base do
4
- specify { described_class.new('name').name.should == :name }
5
- specify { described_class.new('name', type: 'integer').options[:type].should == 'integer' }
4
+ specify { expect(described_class.new('name').name).to eq(:name) }
5
+ specify { expect(described_class.new('name', type: 'integer').options[:type]).to eq('integer') }
6
6
 
7
7
  describe '#compose' do
8
8
  let(:field) { described_class.new(:name, value: ->(o){ o.value }) }
9
9
 
10
- specify { field.compose(double(value: 'hello')).should == {name: 'hello'} }
11
- specify { field.compose(double(value: ['hello', 'world'])).should == {name: ['hello', 'world']} }
10
+ specify { expect(field.compose(double(value: 'hello'))).to eq({name: 'hello'}) }
11
+ specify { expect(field.compose(double(value: ['hello', 'world']))).to eq({name: ['hello', 'world']}) }
12
12
 
13
- specify { described_class.new(:name).compose(double(name: 'hello')).should == {name: 'hello'} }
13
+ specify { expect(described_class.new(:name).compose(double(name: 'hello'))).to eq({name: 'hello'}) }
14
14
 
15
15
  context do
16
16
  before do
@@ -19,15 +19,15 @@ describe Chewy::Fields::Base do
19
19
  field.nested(described_class.new(:subname3))
20
20
  end
21
21
 
22
- specify { field.compose(double(value: double(subvalue1: 'hello', subvalue2: 'value', subname3: 'world')))
23
- .should == {name: {'subname1' => 'hello', 'subname2' => 'value', 'subname3' => 'world'}} }
24
- specify { field.compose(double(value: [
22
+ specify { expect(field.compose(double(value: double(subvalue1: 'hello', subvalue2: 'value', subname3: 'world'))))
23
+ .to eq({name: {'subname1' => 'hello', 'subname2' => 'value', 'subname3' => 'world'}}) }
24
+ specify { expect(field.compose(double(value: [
25
25
  double(subvalue1: 'hello1', subvalue2: 'value1', subname3: 'world1'),
26
26
  double(subvalue1: 'hello2', subvalue2: 'value2', subname3: 'world2')
27
- ])).should == {name: [
27
+ ]))).to eq({name: [
28
28
  {'subname1' => 'hello1', 'subname2' => 'value1', 'subname3' => 'world1'},
29
29
  {'subname1' => 'hello2', 'subname2' => 'value2', 'subname3' => 'world2'}
30
- ]} }
30
+ ]}) }
31
31
  end
32
32
 
33
33
  context do
@@ -37,7 +37,7 @@ describe Chewy::Fields::Base do
37
37
  field.nested(described_class.new(:untouched))
38
38
  end
39
39
 
40
- specify { field.compose(double(name: 'Alex')).should == {name: 'Alex'} }
40
+ specify { expect(field.compose(double(name: 'Alex'))).to eq({name: 'Alex'}) }
41
41
  end
42
42
 
43
43
  context do
@@ -49,7 +49,7 @@ describe Chewy::Fields::Base do
49
49
  field.nested(described_class.new(:key2, value: ->(h){ h[:key2] }))
50
50
  end
51
51
 
52
- specify{ field.compose(object).should == { name: { 'key1' => 'value1', 'key2' => 'value2' } } }
52
+ specify{ expect(field.compose(object)).to eq({ name: { 'key1' => 'value1', 'key2' => 'value2' } }) }
53
53
  end
54
54
  end
55
55
 
@@ -69,21 +69,21 @@ describe Chewy::Fields::Base do
69
69
  fields2.each { |m| fields1[0].nested(m) }
70
70
  end
71
71
 
72
- specify { field.mappings_hash.should == {name: {type: :object, properties: {
72
+ specify { expect(field.mappings_hash).to eq({name: {type: :object, properties: {
73
73
  name1: {type: 'string1', fields: {
74
74
  name3: {type: 'string3'}, name4: {type: 'string4'}
75
75
  }}, name2: {type: 'string2'}
76
- }}} }
76
+ }}}) }
77
77
 
78
78
  context do
79
79
  let(:field) { described_class.new(:name, type: :string) }
80
80
  let(:fields1) { 2.times.map { |i| described_class.new("name#{i+1}") } }
81
81
 
82
- specify { field.mappings_hash.should == {name: {type: :string, fields: {
82
+ specify { expect(field.mappings_hash).to eq({name: {type: :string, fields: {
83
83
  name1: {type: 'object', properties: {
84
84
  name3: {type: 'string3'}, name4: {type: 'string4'}
85
85
  }}, name2: {type: 'string'}
86
- }}} }
86
+ }}}) }
87
87
  end
88
88
  end
89
89
 
@@ -105,7 +105,7 @@ describe Chewy::Fields::Base do
105
105
  end
106
106
 
107
107
  specify do
108
- EventsIndex::Event.mappings_hash.should == { event: {
108
+ expect(EventsIndex::Event.mappings_hash).to eq({ event: {
109
109
  properties: {
110
110
  id: { type: 'string' },
111
111
  category: {
@@ -116,99 +116,99 @@ describe Chewy::Fields::Base do
116
116
  type: 'object',
117
117
  properties: {
118
118
  id: { type: 'string' },
119
- name: { type: 'string' } } } } } } } }
119
+ name: { type: 'string' } } } } } } } })
120
120
  end
121
121
 
122
122
  specify do
123
- EventsIndex::Event.root_object.compose(
123
+ expect(EventsIndex::Event.root_object.compose(
124
124
  id: 1, category: { id: 2, licenses: { id: 3, name: 'Name' } }
125
- ).should == {
125
+ )).to eq({
126
126
  event: { 'id' => 1, 'category' => { 'id' => 2, 'licenses' => {'id' => 3, 'name' => 'Name'}}}
127
- }
127
+ })
128
128
  end
129
129
 
130
130
  specify do
131
- EventsIndex::Event.root_object.compose(id: 1, category: [
131
+ expect(EventsIndex::Event.root_object.compose(id: 1, category: [
132
132
  { id: 2, 'licenses' => { id: 3, name: 'Name1' } },
133
133
  { id: 4, licenses: nil}
134
- ]).should == {
134
+ ])).to eq({
135
135
  event: { 'id' => 1, 'category' => [
136
136
  { 'id' => 2, 'licenses' => { 'id' => 3, 'name' => 'Name1' } },
137
137
  {'id' => 4, 'licenses' => nil }
138
138
  ] }
139
- }
139
+ })
140
140
  end
141
141
 
142
142
  specify do
143
- EventsIndex::Event.root_object.compose('id' => 1, category: { id: 2, licenses: [
143
+ expect(EventsIndex::Event.root_object.compose('id' => 1, category: { id: 2, licenses: [
144
144
  { id: 3, name: 'Name1' }, { id: 4, name: 'Name2' }
145
- ] }).should == {
145
+ ] })).to eq({
146
146
  event: { 'id' => 1, 'category' => { 'id' => 2, 'licenses' => [
147
147
  {'id' => 3, 'name' => 'Name1'}, {'id' => 4, 'name' => 'Name2'}
148
148
  ] } }
149
- }
149
+ })
150
150
  end
151
151
 
152
152
  specify do
153
- EventsIndex::Event.root_object.compose(id: 1, category: [
153
+ expect(EventsIndex::Event.root_object.compose(id: 1, category: [
154
154
  { id: 2, licenses: [
155
155
  { id: 3, 'name' => 'Name1' }, { id: 4, name: 'Name2' }
156
156
  ] },
157
157
  { id: 5, licenses: [] }
158
- ]).should == {
158
+ ])).to eq({
159
159
  event: { 'id' => 1, 'category' => [
160
160
  { 'id' => 2, 'licenses' => [
161
161
  { 'id' => 3, 'name' => 'Name1' }, { 'id' => 4, 'name' => 'Name2' }
162
162
  ] },
163
163
  {'id' => 5, 'licenses' => [] }
164
164
  ] }
165
- }
165
+ })
166
166
  end
167
167
 
168
168
  specify do
169
- EventsIndex::Event.root_object.compose(
169
+ expect(EventsIndex::Event.root_object.compose(
170
170
  double(id: 1, category: double(id: 2, licenses: double(id: 3, name: 'Name')))
171
- ).should == {
171
+ )).to eq({
172
172
  event: { 'id' => 1, 'category' => { 'id' => 2, 'licenses' => {'id' => 3, 'name' => 'Name'}}}
173
- }
173
+ })
174
174
  end
175
175
 
176
176
  specify do
177
- EventsIndex::Event.root_object.compose(double(id: 1, category: [
177
+ expect(EventsIndex::Event.root_object.compose(double(id: 1, category: [
178
178
  double(id: 2, licenses: double(id: 3, name: 'Name1')),
179
179
  double(id: 4, licenses: nil)
180
- ])).should == {
180
+ ]))).to eq({
181
181
  event: { 'id' => 1, 'category' => [
182
182
  { 'id' => 2, 'licenses' => { 'id' => 3, 'name' => 'Name1' } },
183
183
  {'id' => 4, 'licenses' => nil }
184
184
  ] }
185
- }
185
+ })
186
186
  end
187
187
 
188
188
  specify do
189
- EventsIndex::Event.root_object.compose(double(id: 1, category: double(id: 2, licenses: [
189
+ expect(EventsIndex::Event.root_object.compose(double(id: 1, category: double(id: 2, licenses: [
190
190
  double(id: 3, name: 'Name1'), double(id: 4, name: 'Name2')
191
- ]))).should == {
191
+ ])))).to eq({
192
192
  event: { 'id' => 1, 'category' => { 'id' => 2, 'licenses' => [
193
193
  {'id' => 3, 'name' => 'Name1'}, {'id' => 4, 'name' => 'Name2'}
194
194
  ] } }
195
- }
195
+ })
196
196
  end
197
197
 
198
198
  specify do
199
- EventsIndex::Event.root_object.compose(double(id: 1, category: [
199
+ expect(EventsIndex::Event.root_object.compose(double(id: 1, category: [
200
200
  double(id: 2, licenses: [
201
201
  double(id: 3, name: 'Name1'), double(id: 4, name: 'Name2')
202
202
  ]),
203
203
  double(id: 5, licenses: [])
204
- ])).should == {
204
+ ]))).to eq({
205
205
  event: { 'id' => 1, 'category' => [
206
206
  { 'id' => 2, 'licenses' => [
207
207
  { 'id' => 3, 'name' => 'Name1' }, { 'id' => 4, 'name' => 'Name2' }
208
208
  ] },
209
209
  {'id' => 5, 'licenses' => [] }
210
210
  ] }
211
- }
211
+ })
212
212
  end
213
213
  end
214
214
 
@@ -229,11 +229,11 @@ describe Chewy::Fields::Base do
229
229
  end
230
230
 
231
231
  specify do
232
- EventsIndex::Event.root_object.compose(
232
+ expect(EventsIndex::Event.root_object.compose(
233
233
  double(id: 1, categories: double(id: 2, license: double(id: 3, name: 'Name')))
234
- ).should == {
234
+ )).to eq({
235
235
  event: { 'id' => 1, 'category' => { 'id' => 2, 'licenses' => {'id' => 3, 'name' => 'Name'}}}
236
- }
236
+ })
237
237
  end
238
238
  end
239
239
 
@@ -251,7 +251,7 @@ describe Chewy::Fields::Base do
251
251
  end
252
252
 
253
253
  specify do
254
- EventsIndex::Event.mappings_hash.should == { event: {
254
+ expect(EventsIndex::Event.mappings_hash).to eq({ event: {
255
255
  properties: {
256
256
  id: { type: 'string' },
257
257
  name: {
@@ -262,28 +262,28 @@ describe Chewy::Fields::Base do
262
262
  },
263
263
  category: { type: 'object' }
264
264
  }
265
- } }
265
+ } })
266
266
  end
267
267
 
268
268
  specify do
269
- EventsIndex::Event.root_object.compose(
269
+ expect(EventsIndex::Event.root_object.compose(
270
270
  double(id: 1, name: 'Jonny', category: double(id: 2, as_json: {name: 'Borogoves'}))
271
- ).should == {
271
+ )).to eq({
272
272
  event: {
273
273
  'id' => 1,
274
274
  'name' => 'Jonny',
275
275
  'category' => { 'name' => 'Borogoves' }
276
276
  }
277
- }
277
+ })
278
278
  end
279
279
 
280
280
  specify do
281
- EventsIndex::Event.root_object.compose(
281
+ expect(EventsIndex::Event.root_object.compose(
282
282
  double(id: 1, name: 'Jonny', category: [
283
283
  double(id: 2, as_json: { name: 'Borogoves1' }),
284
284
  double(id: 3, as_json: { name: 'Borogoves2' })
285
285
  ])
286
- ).should == {
286
+ )).to eq({
287
287
  event: {
288
288
  'id' => 1,
289
289
  'name' => 'Jonny',
@@ -292,11 +292,11 @@ describe Chewy::Fields::Base do
292
292
  { 'name' => 'Borogoves2' }
293
293
  ]
294
294
  }
295
- }
295
+ })
296
296
  end
297
297
  end
298
298
 
299
- context 'objects and scopes' do
299
+ context 'objects and scopes', :orm do
300
300
  before do
301
301
  stub_model(:city) do
302
302
  belongs_to :country
@@ -318,13 +318,13 @@ describe Chewy::Fields::Base do
318
318
  end
319
319
 
320
320
  specify do
321
- CountriesIndex::Country.root_object.compose(
322
- Country.create!(cities: [City.create!(name: 'City1'), City.create!(name: 'City2')])
323
- ).should == {
321
+ expect(CountriesIndex::Country.root_object.compose(
322
+ Country.create!(id: 1, cities: [City.create!(id: 1, name: 'City1'), City.create!(id: 2, name: 'City2')])
323
+ )).to eq({
324
324
  country: { 'id' => 1, 'cities' => [
325
325
  { 'id' => 1, 'name' => 'City1' }, { 'id' => 2, 'name' => 'City2' }
326
326
  ] }
327
- }
327
+ })
328
328
  end
329
329
 
330
330
  context 'nested object' do
@@ -341,11 +341,11 @@ describe Chewy::Fields::Base do
341
341
  end
342
342
 
343
343
  specify do
344
- CitiesIndex::City.root_object.compose(
345
- City.create!(country: Country.create!(name: 'Country'))
346
- ).should == {
344
+ expect(CitiesIndex::City.root_object.compose(
345
+ City.create!(id: 1, country: Country.create!(id: 1, name: 'Country'))
346
+ )).to eq({
347
347
  city: { 'id' => 1, 'country' => { 'id' => 1, 'name' => 'Country' } }
348
- }
348
+ })
349
349
  end
350
350
  end
351
351
  end