chewy 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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