mongoid 7.2.6 → 7.3.3

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 (154) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/Rakefile +16 -0
  4. data/lib/config/locales/en.yml +2 -2
  5. data/lib/mongoid/association/accessors.rb +13 -1
  6. data/lib/mongoid/association/constrainable.rb +1 -1
  7. data/lib/mongoid/association/depending.rb +4 -4
  8. data/lib/mongoid/association/embedded/batchable.rb +1 -1
  9. data/lib/mongoid/association/embedded/embedded_in.rb +1 -1
  10. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +10 -3
  11. data/lib/mongoid/association/nested/many.rb +1 -1
  12. data/lib/mongoid/association/nested/one.rb +4 -2
  13. data/lib/mongoid/association/proxy.rb +6 -1
  14. data/lib/mongoid/association/referenced/auto_save.rb +2 -2
  15. data/lib/mongoid/association/referenced/has_many/enumerable.rb +490 -496
  16. data/lib/mongoid/association/referenced/has_many/proxy.rb +2 -2
  17. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +2 -2
  18. data/lib/mongoid/atomic.rb +26 -2
  19. data/lib/mongoid/attributes/projector.rb +120 -0
  20. data/lib/mongoid/attributes.rb +24 -13
  21. data/lib/mongoid/cacheable.rb +2 -2
  22. data/lib/mongoid/clients/factory.rb +22 -8
  23. data/lib/mongoid/clients.rb +1 -1
  24. data/lib/mongoid/config.rb +19 -2
  25. data/lib/mongoid/contextual/aggregable/mongo.rb +10 -8
  26. data/lib/mongoid/copyable.rb +1 -1
  27. data/lib/mongoid/criteria/findable.rb +1 -1
  28. data/lib/mongoid/criteria/queryable/expandable.rb +0 -24
  29. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +1 -1
  30. data/lib/mongoid/criteria/queryable/extensions.rb +0 -4
  31. data/lib/mongoid/criteria/queryable/mergeable.rb +46 -20
  32. data/lib/mongoid/criteria/queryable/selectable.rb +8 -8
  33. data/lib/mongoid/criteria.rb +4 -5
  34. data/lib/mongoid/document.rb +1 -15
  35. data/lib/mongoid/errors/delete_restriction.rb +8 -9
  36. data/lib/mongoid/evolvable.rb +1 -1
  37. data/lib/mongoid/extensions/boolean.rb +1 -2
  38. data/lib/mongoid/extensions/false_class.rb +1 -1
  39. data/lib/mongoid/extensions/hash.rb +2 -2
  40. data/lib/mongoid/extensions/true_class.rb +1 -1
  41. data/lib/mongoid/fields.rb +43 -5
  42. data/lib/mongoid/inspectable.rb +1 -1
  43. data/lib/mongoid/matcher/bits.rb +41 -0
  44. data/lib/mongoid/matcher/bits_all_clear.rb +20 -0
  45. data/lib/mongoid/matcher/bits_all_set.rb +20 -0
  46. data/lib/mongoid/matcher/bits_any_clear.rb +20 -0
  47. data/lib/mongoid/matcher/bits_any_set.rb +20 -0
  48. data/lib/mongoid/matcher/expression.rb +4 -0
  49. data/lib/mongoid/matcher/field_operator.rb +6 -0
  50. data/lib/mongoid/matcher/mod.rb +17 -0
  51. data/lib/mongoid/matcher/type.rb +99 -0
  52. data/lib/mongoid/matcher.rb +7 -0
  53. data/lib/mongoid/persistable/deletable.rb +1 -2
  54. data/lib/mongoid/persistable/destroyable.rb +8 -2
  55. data/lib/mongoid/persistable/updatable.rb +27 -2
  56. data/lib/mongoid/query_cache.rb +35 -29
  57. data/lib/mongoid/selectable.rb +5 -7
  58. data/lib/mongoid/shardable.rb +21 -5
  59. data/lib/mongoid/touchable.rb +33 -4
  60. data/lib/mongoid/version.rb +1 -1
  61. data/spec/integration/associations/embeds_many_spec.rb +44 -0
  62. data/spec/integration/associations/has_one_spec.rb +48 -0
  63. data/spec/integration/criteria/date_field_spec.rb +1 -1
  64. data/spec/integration/document_spec.rb +9 -0
  65. data/spec/integration/matcher_operator_data/bits_all_clear.yml +159 -0
  66. data/spec/integration/matcher_operator_data/bits_all_set.yml +159 -0
  67. data/spec/integration/matcher_operator_data/bits_any_clear.yml +159 -0
  68. data/spec/integration/matcher_operator_data/bits_any_set.yml +159 -0
  69. data/spec/integration/matcher_operator_data/comment.yml +22 -0
  70. data/spec/integration/matcher_operator_data/in.yml +16 -0
  71. data/spec/integration/matcher_operator_data/mod.yml +55 -0
  72. data/spec/integration/matcher_operator_data/type.yml +70 -0
  73. data/spec/integration/matcher_operator_data/type_array.yml +16 -0
  74. data/spec/integration/matcher_operator_data/type_binary.yml +18 -0
  75. data/spec/integration/matcher_operator_data/type_boolean.yml +39 -0
  76. data/spec/integration/matcher_operator_data/type_code.yml +26 -0
  77. data/spec/integration/matcher_operator_data/type_code_with_scope.yml +26 -0
  78. data/spec/integration/matcher_operator_data/type_date.yml +39 -0
  79. data/spec/integration/matcher_operator_data/type_db_pointer.yml +19 -0
  80. data/spec/integration/matcher_operator_data/type_decimal.yml +40 -0
  81. data/spec/integration/matcher_operator_data/type_double.yml +15 -0
  82. data/spec/integration/matcher_operator_data/type_int32.yml +33 -0
  83. data/spec/integration/matcher_operator_data/type_int64.yml +33 -0
  84. data/spec/integration/matcher_operator_data/type_max_key.yml +17 -0
  85. data/spec/integration/matcher_operator_data/type_min_key.yml +17 -0
  86. data/spec/integration/matcher_operator_data/type_null.yml +23 -0
  87. data/spec/integration/matcher_operator_data/type_object.yml +23 -0
  88. data/spec/integration/matcher_operator_data/type_object_id.yml +25 -0
  89. data/spec/integration/matcher_operator_data/type_regex.yml +44 -0
  90. data/spec/integration/matcher_operator_data/type_string.yml +15 -0
  91. data/spec/integration/matcher_operator_data/type_symbol.yml +32 -0
  92. data/spec/integration/matcher_operator_data/type_timestamp.yml +25 -0
  93. data/spec/integration/matcher_operator_data/type_undefined.yml +17 -0
  94. data/spec/lite_spec_helper.rb +2 -0
  95. data/spec/mongoid/association/depending_spec.rb +391 -352
  96. data/spec/mongoid/association/nested/one_spec.rb +18 -14
  97. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +25 -8
  98. data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +1 -1
  99. data/spec/mongoid/association/referenced/has_many/binding_spec.rb +1 -1
  100. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +245 -93
  101. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +6 -6
  102. data/spec/mongoid/association/referenced/has_one_models.rb +8 -0
  103. data/spec/mongoid/atomic/paths_spec.rb +64 -12
  104. data/spec/mongoid/attributes/projector_data/embedded.yml +105 -0
  105. data/spec/mongoid/attributes/projector_data/fields.yml +93 -0
  106. data/spec/mongoid/attributes/projector_spec.rb +41 -0
  107. data/spec/mongoid/attributes_spec.rb +98 -6
  108. data/spec/mongoid/clients/factory_spec.rb +48 -0
  109. data/spec/mongoid/config_spec.rb +106 -1
  110. data/spec/mongoid/contextual/mongo_spec.rb +2 -2
  111. data/spec/mongoid/criteria/modifiable_spec.rb +1 -1
  112. data/spec/mongoid/criteria/queryable/expandable_spec.rb +0 -73
  113. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +1 -1
  114. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +105 -7
  115. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +229 -24
  116. data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +39 -0
  117. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -565
  118. data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +590 -0
  119. data/spec/mongoid/criteria_projection_spec.rb +411 -0
  120. data/spec/mongoid/criteria_spec.rb +0 -275
  121. data/spec/mongoid/document_spec.rb +13 -13
  122. data/spec/mongoid/errors/delete_restriction_spec.rb +1 -1
  123. data/spec/mongoid/extensions/false_class_spec.rb +1 -1
  124. data/spec/mongoid/extensions/string_spec.rb +5 -5
  125. data/spec/mongoid/extensions/true_class_spec.rb +1 -1
  126. data/spec/mongoid/fields/localized_spec.rb +4 -4
  127. data/spec/mongoid/fields_spec.rb +4 -4
  128. data/spec/mongoid/inspectable_spec.rb +12 -4
  129. data/spec/mongoid/persistable/deletable_spec.rb +175 -1
  130. data/spec/mongoid/persistable/destroyable_spec.rb +191 -3
  131. data/spec/mongoid/persistable/savable_spec.rb +3 -5
  132. data/spec/mongoid/persistable/upsertable_spec.rb +1 -1
  133. data/spec/mongoid/query_cache_middleware_spec.rb +8 -0
  134. data/spec/mongoid/reloadable_spec.rb +18 -1
  135. data/spec/mongoid/shardable_spec.rb +44 -0
  136. data/spec/mongoid/touchable_spec.rb +122 -16
  137. data/spec/mongoid/touchable_spec_models.rb +54 -0
  138. data/spec/mongoid/validatable_spec.rb +1 -1
  139. data/spec/spec_helper.rb +6 -2
  140. data/spec/support/client_registry.rb +9 -0
  141. data/spec/support/models/bolt.rb +8 -0
  142. data/spec/support/models/hole.rb +13 -0
  143. data/spec/support/models/mop.rb +0 -1
  144. data/spec/support/models/nut.rb +8 -0
  145. data/spec/support/models/person.rb +6 -0
  146. data/spec/support/models/sealer.rb +8 -0
  147. data/spec/support/models/shirt.rb +12 -0
  148. data/spec/support/models/spacer.rb +8 -0
  149. data/spec/support/models/threadlocker.rb +8 -0
  150. data/spec/support/models/washer.rb +8 -0
  151. data.tar.gz.sig +0 -0
  152. metadata +97 -3
  153. metadata.gz.sig +0 -0
  154. data/spec/support/cluster_config.rb +0 -158
@@ -1568,12 +1568,12 @@ describe Mongoid::Association::Referenced::HasMany::Proxy do
1568
1568
  end
1569
1569
 
1570
1570
  context 'when association is not loaded' do
1571
- it 'queries database on each call' do
1572
- expect_query(1) do
1573
- movie.ratings.any?.should be true
1574
- end
1571
+ before do
1572
+ movie.ratings._loaded?.should be false
1573
+ end
1575
1574
 
1576
- expect_query(1) do
1575
+ it 'does not query the database because it knows about the added models' do
1576
+ expect_no_queries do
1577
1577
  movie.ratings.any?.should be true
1578
1578
  end
1579
1579
  end
@@ -1581,7 +1581,7 @@ describe Mongoid::Association::Referenced::HasMany::Proxy do
1581
1581
 
1582
1582
  context 'when association is loaded' do
1583
1583
  it 'does not query database' do
1584
- expect_query(1) do
1584
+ expect_no_queries do
1585
1585
  movie.ratings.any?.should be true
1586
1586
  end
1587
1587
 
@@ -19,6 +19,14 @@ class HomAccreditation
19
19
 
20
20
  field :degree, type: String
21
21
  field :year, type: Integer, default: 2012
22
+
23
+ def format
24
+ 'fmt'
25
+ end
26
+
27
+ def price
28
+ 42
29
+ end
22
30
  end
23
31
 
24
32
  class HomAccreditation::Child
@@ -113,10 +113,33 @@ describe Mongoid::Atomic::Paths do
113
113
  person.addresses << address
114
114
  end
115
115
 
116
- it "returns the association with id.atomic_selector" do
117
- expect(address.atomic_selector).to eq(
118
- { "_id" => person.id, "addresses._id" => address.id }
119
- )
116
+ context 'when the parent is persisted' do
117
+
118
+ let(:person) do
119
+ Person.create!
120
+ end
121
+
122
+ before do
123
+ person.should be_persisted
124
+ end
125
+
126
+ it "returns the association with id.atomic_selector" do
127
+ expect(address.atomic_selector).to eq(
128
+ { "_id" => person.id, "addresses._id" => address.id }
129
+ )
130
+ end
131
+ end
132
+
133
+ context 'when the parent is not persisted' do
134
+ before do
135
+ person.should be_new_record
136
+ end
137
+
138
+ it "returns the association with id.atomic_selector" do
139
+ expect(address.atomic_selector).to eq(
140
+ { "_id" => person.id, "addresses._id" => address.id }
141
+ )
142
+ end
120
143
  end
121
144
  end
122
145
 
@@ -127,14 +150,43 @@ describe Mongoid::Atomic::Paths do
127
150
  person.addresses << address
128
151
  end
129
152
 
130
- it "returns the JSON notation to the document with ids" do
131
- expect(location.atomic_selector).to eq(
132
- {
133
- "_id" => person.id,
134
- "addresses._id" => address.id,
135
- "addresses.locations._id" => location.id
136
- }
137
- )
153
+ context 'when the parent is persisted' do
154
+
155
+ let(:person) do
156
+ Person.create!
157
+ end
158
+
159
+ before do
160
+ person.should be_persisted
161
+ end
162
+
163
+ it "returns the JSON notation to the document with ids" do
164
+ expect(location.atomic_selector).to eq(
165
+ {
166
+ "_id" => person.id,
167
+ "addresses._id" => address.id,
168
+ "addresses.0.locations._id" => location.id
169
+ }
170
+ )
171
+ end
172
+ end
173
+
174
+ context 'when the parent is not persisted' do
175
+ before do
176
+ person.should be_new_record
177
+ end
178
+
179
+ it "returns the JSON notation to the document with ids" do
180
+ expect(location.atomic_selector).to eq(
181
+ {
182
+ "_id" => person.id,
183
+ "addresses._id" => address.id,
184
+ # This condition is technically acceptable for finds
185
+ # but probably won't work for modifications of 'locations'.
186
+ "addresses.locations._id" => location.id
187
+ }
188
+ )
189
+ end
138
190
  end
139
191
  end
140
192
  end
@@ -0,0 +1,105 @@
1
+ - name: embedded field - inclusion
2
+ projection:
3
+ foo.bar: 1
4
+
5
+ queries: &embedded-field-inclusion-expectations
6
+ # Top-level field is allowed as a container
7
+ - query: foo
8
+ allowed: true
9
+
10
+ # Unmentioned field is not allowed
11
+ - query: bar
12
+ allowed: false
13
+
14
+ # A peer to the field isn't allowed
15
+ - query: foo.buck
16
+ allowed: false
17
+
18
+ # A more nested field is allowed
19
+ - query: foo.bar.baz
20
+ allowed: true
21
+
22
+ - name: embedded field - exclusion
23
+ projection:
24
+ foo.bar: 0
25
+
26
+ queries: &embedded-field-exclusion-expectations
27
+ # Top-level field is allowed
28
+ - query: foo
29
+ allowed: true
30
+
31
+ # Unmentioned field is allowed
32
+ - query: bar
33
+ allowed: true
34
+
35
+ # A peer to the excluded field is allowed
36
+ - query: foo.buck
37
+ allowed: true
38
+
39
+ # A more nested field is not allowed
40
+ - query: foo.bar.baz
41
+ allowed: false
42
+
43
+ - name: parent and child fields - inclusion
44
+ projection:
45
+ foo.bar: 1
46
+ foo.bar.baz: 1
47
+
48
+ queries:
49
+ # Top-level field is allowed
50
+ - query: foo
51
+ allowed: true
52
+
53
+ # Second-level field is allowed
54
+ - query: foo.bar
55
+ allowed: true
56
+
57
+ # Third-level field is also allowed
58
+ - query: foo.bar.baz
59
+ allowed: true
60
+
61
+ # Fourth-level field is still allowed
62
+ - query: foo.bar.baz.zzz
63
+ allowed: true
64
+
65
+ # Unmentioned siblings are not allowed
66
+ - query: buck
67
+ allowed: false
68
+ - query: foo.buck
69
+ allowed: false
70
+
71
+ # This sibling is under the second-level include and is allowed
72
+ - query: foo.bar.buck
73
+ allowed: true
74
+
75
+ - name: parent and child fields - exclusion
76
+ projection:
77
+ foo.bar: 0
78
+ foo.bar.baz: 0
79
+
80
+ queries:
81
+ # Top-level field is allowed
82
+ - query: foo
83
+ allowed: true
84
+
85
+ # Second-level field is not allowed
86
+ - query: foo.bar
87
+ allowed: false
88
+
89
+ # Third-level field is also not allowed
90
+ - query: foo.bar.baz
91
+ allowed: false
92
+
93
+ # Fourth-level field is still not allowed
94
+ - query: foo.bar.baz.zzz
95
+ allowed: false
96
+
97
+ # Unmentioned siblings are allowed
98
+ - query: buck
99
+ allowed: true
100
+ - query: foo.buck
101
+ allowed: true
102
+
103
+ # This sibling is under the second-level exclude and is disallowed
104
+ - query: foo.bar.buck
105
+ allowed: false
@@ -0,0 +1,93 @@
1
+ - name: simple inclusion - integer
2
+ projection:
3
+ foo: 1
4
+
5
+ queries: &field-inclusion-expectations
6
+ - query: foo
7
+ allowed: true
8
+ - query: bar
9
+ allowed: false
10
+
11
+ - name: simple inclusion - boolean
12
+ projection:
13
+ foo: true
14
+
15
+ queries: &field-inclusion-expectations
16
+ - query: foo
17
+ allowed: true
18
+ - query: bar
19
+ allowed: false
20
+
21
+ - name: positive integer - inclusion
22
+ projection:
23
+ foo: 2
24
+
25
+ queries: *field-inclusion-expectations
26
+
27
+ - name: simple exclusion - integer
28
+ projection:
29
+ foo: 0
30
+
31
+ queries: &field-exclusion-expectations
32
+ - query: foo
33
+ allowed: false
34
+ - query: bar
35
+ allowed: true
36
+
37
+ - name: simple exclusion - boolean
38
+ projection:
39
+ foo: false
40
+
41
+ queries: &field-exclusion-expectations
42
+ - query: foo
43
+ allowed: false
44
+ - query: bar
45
+ allowed: true
46
+
47
+ - name: negative integer - exclusion
48
+ projection:
49
+ foo: -2
50
+
51
+ queries: *field-exclusion-expectations
52
+
53
+ - name: field inclusion with _id exclusion
54
+ projection:
55
+ foo: 1
56
+ _id: 0
57
+
58
+ queries: &field-inclusion-with-id-exclusion-expectations
59
+ - query: foo
60
+ allowed: true
61
+
62
+ - query: bar
63
+ allowed: false
64
+
65
+ - query: _id
66
+ allowed: false
67
+
68
+ - name: _id exclusion with field inclusion
69
+ projection:
70
+ _id: 0
71
+ foo: 1
72
+
73
+ queries: *field-inclusion-with-id-exclusion-expectations
74
+
75
+ - name: id inclusion
76
+ projection:
77
+ _id: 1
78
+
79
+ queries:
80
+ - query: _id
81
+ allowed: true
82
+ - query: foo
83
+ allowed: false
84
+
85
+ - name: id exclusion
86
+ projection:
87
+ _id: false
88
+
89
+ queries:
90
+ - query: _id
91
+ allowed: false
92
+ - query: foo
93
+ allowed: true
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ require "spec_helper"
5
+
6
+ describe Mongoid::Attributes::Projector do
7
+ Dir[File.join(File.dirname(__FILE__), 'projector_data', '*.yml')].sort.each do |path|
8
+ context File.basename(path) do
9
+ specs = YAML.load(File.read(path))
10
+
11
+ specs.each do |spec|
12
+ context spec['name'] do
13
+
14
+ if spec['pending']
15
+ pending spec['pending'].to_s
16
+ end
17
+
18
+ let(:projection) do
19
+ spec['projection']
20
+ end
21
+
22
+ let(:projector) do
23
+ Mongoid::Attributes::Projector.new(projection)
24
+ end
25
+
26
+ spec.fetch('queries').each do |query_spec|
27
+ context query_spec.fetch('query').inspect do
28
+ let(:query) { query_spec['query'] }
29
+
30
+ context 'attribute_or_path_allowed?' do
31
+ it "is #{query_spec.fetch('allowed')}" do
32
+ projector.attribute_or_path_allowed?(query).should be query_spec['allowed']
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -96,6 +96,49 @@ describe Mongoid::Attributes do
96
96
  it "does not raise an error" do
97
97
  expect(from_db.map).to eq(map)
98
98
  end
99
+
100
+ context 'when only one of the hash fields is projected' do
101
+
102
+ let(:map) do
103
+ { 'dates' => { 'y' => { '2016' => 'Berlin', '2017' => 'Munich' } } }
104
+ end
105
+
106
+ let(:expected) do
107
+ { 'dates' => { 'y' => {
108
+ '2016' => 'Berlin',
109
+ } } }
110
+ end
111
+
112
+ it 'retrieves only the projected fields' do
113
+ expect(from_db.map).to eq(expected)
114
+ end
115
+ end
116
+
117
+ context 'when several of the hash fields is projected' do
118
+
119
+ let(:map) do
120
+ { 'dates' => { 'y' => {
121
+ '2016' => 'Berlin',
122
+ '2017' => 'Munich',
123
+ '2018' => 'Krakow',
124
+ } } }
125
+ end
126
+
127
+ let(:expected) do
128
+ { 'dates' => { 'y' => {
129
+ '2016' => 'Berlin',
130
+ '2018' => 'Krakow',
131
+ } } }
132
+ end
133
+
134
+ let(:from_db) do
135
+ Person.only('map.dates.y.2016', 'map.dates.y.2018').first
136
+ end
137
+
138
+ it 'retrieves only the projected fields' do
139
+ expect(from_db.map).to eq(expected)
140
+ end
141
+ end
99
142
  end
100
143
  end
101
144
 
@@ -298,16 +341,12 @@ describe Mongoid::Attributes do
298
341
  context 'when retrieving a field of the association using the dot notation' do
299
342
 
300
343
  it 'retrieves the field' do
301
- pending 'MONGOID-5032, fixed in 7.3'
302
-
303
344
  expect(from_db['name.first_name']).to eq 'Jose'
304
345
  end
305
346
  end
306
347
 
307
348
  context 'when retrieving a field of a nested association using the dot notation' do
308
349
  it 'retrieves the field' do
309
- pending 'MONGOID-5032, fixed in 7.3'
310
-
311
350
  expect(from_db['name.language.name']).to eq 'es'
312
351
  end
313
352
  end
@@ -320,8 +359,6 @@ describe Mongoid::Attributes do
320
359
 
321
360
  context 'when retrieving a field under the projected sub-association' do
322
361
  it 'retrieves the field' do
323
- pending 'MONGOID-5032, fixed in 7.3'
324
-
325
362
  expect(from_db['name.language.name']).to eq 'es'
326
363
  end
327
364
  end
@@ -1892,6 +1929,61 @@ describe Mongoid::Attributes do
1892
1929
  end
1893
1930
  end
1894
1931
 
1932
+ describe '#unalias_attribute' do
1933
+ let(:shirt) { Shirt.new }
1934
+ let(:id) { '1234' }
1935
+
1936
+ context 'when creating object' do
1937
+ let(:shirt) { Shirt.new(id: id) }
1938
+
1939
+ it 'id and _id are not the same' do
1940
+ expect(shirt.id).to eq(id)
1941
+ expect(shirt._id).not_to eq(id)
1942
+ end
1943
+ end
1944
+
1945
+ context 'update' do
1946
+ before do
1947
+ shirt.update(id: id)
1948
+ end
1949
+
1950
+ it 'updates id but not_id' do
1951
+ expect(shirt.id).to eq(id)
1952
+ expect(shirt._id).not_to eq(id)
1953
+ end
1954
+ end
1955
+
1956
+ context 'id=' do
1957
+ before do
1958
+ shirt.id = id
1959
+ end
1960
+
1961
+ it 'sets id and not _id' do
1962
+ expect(shirt.id).to eq(id)
1963
+ expect(shirt._id).not_to eq(id)
1964
+ end
1965
+ end
1966
+
1967
+ context 'id?' do
1968
+ context 'with null id' do
1969
+ it 'returns false' do
1970
+ expect(shirt.id?).to be false
1971
+ expect(shirt._id?).to be true
1972
+ end
1973
+ end
1974
+
1975
+ context 'with id' do
1976
+ before do
1977
+ shirt.id = id
1978
+ end
1979
+
1980
+ it 'returns true' do
1981
+ expect(shirt.id?).to be true
1982
+ end
1983
+ end
1984
+ end
1985
+ end
1986
+
1895
1987
  describe "#alias_attribute" do
1896
1988
 
1897
1989
  let(:product) do