shoulda-matchers 4.1.0 → 4.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1856891b0a96aaa5ed99a48490288b2bbd3547c7779ab1d8477a33b61cbb0c7d
4
- data.tar.gz: b3768f6532318b37de78e6959a1c7be2e28e19b4618d966a7ca0dab0cfa96ceb
3
+ metadata.gz: f55ad44dc8280d7bb9598c809562c5d4b4bd174e78bdc8323898bdb7a3e8665a
4
+ data.tar.gz: 80ddb4b8e6c0ab63c4b9225a1a75789d058d1e664c1b2248680469868072e724
5
5
  SHA512:
6
- metadata.gz: dc99bd232c8f9a3eeff2ea7b82b36821339b20090b40c750c282b48d413b99028fcb69ec775ecb37a43d7e6d59a0c090213c35ede384ed95303d010a5e00ed90
7
- data.tar.gz: 56dbd1bd6978b59743e6936118a535e276b7672f12a0b46b69b3baf164b6dcac0688ee26ec66ccb11b2d0af8d1374567d401ef1f46d3f54bd6d3ccee8cf55085
6
+ metadata.gz: b912596ee8e4a25b1cbd98bca2878ac52cc19b54ab6014bbff0952b7449294e26a6d82b21a6d871b897eb23b26fb82bbc7b328d4de28bb73191fccf53e4e9c1b
7
+ data.tar.gz: 168c002e0ed67d1a2dfde0465e2f48c2fcd4177810479f9c4d5970949f4fbec7db7cb5c71c33b7a341174d5c97fbbfb0782b18ada9f30695048bf25c64777875
data/README.md CHANGED
@@ -19,7 +19,7 @@ complex, and error-prone.
19
19
 
20
20
  ## Quick links
21
21
 
22
- 📖 **[Read the documentation for the latest version (4.1.0)][rubydocs].**
22
+ 📖 **[Read the documentation for the latest version (4.1.1)][rubydocs].**
23
23
  📢 **[See what's changed in a recent version][news].**
24
24
 
25
25
  [rubydocs]: http://matchers.shoulda.io/docs
@@ -170,7 +170,7 @@ module Shoulda
170
170
  allows_and_double_checks_value_of!(value)
171
171
  end
172
172
  else
173
- (expects_to_allow_nil? && !allows_value_of(nil)) ||
173
+ (expects_to_allow_nil? && disallows_value_of(nil)) ||
174
174
  disallowed_values.any? do |value|
175
175
  allows_original_or_typecast_value?(value)
176
176
  end
@@ -234,12 +234,14 @@ validation for you? Instead of using `validate_presence_of`, try
234
234
  end
235
235
 
236
236
  def disallowed_values
237
- if collection?
237
+ if collection_association?
238
238
  [Array.new]
239
+ elsif attachment?
240
+ [nil]
239
241
  else
240
242
  values = []
241
243
 
242
- if !association_being_validated?
244
+ if attribute_accepts_string_values?
243
245
  values << ''
244
246
  end
245
247
 
@@ -251,16 +253,6 @@ validation for you? Instead of using `validate_presence_of`, try
251
253
  end
252
254
  end
253
255
 
254
- def collection?
255
- if association_reflection
256
- [:has_many, :has_and_belongs_to_many].include?(
257
- association_reflection.macro,
258
- )
259
- else
260
- false
261
- end
262
- end
263
-
264
256
  def should_add_footnote_about_belongs_to?
265
257
  belongs_to_association_being_validated? &&
266
258
  presence_validation_exists_on_attribute?
@@ -316,12 +308,33 @@ validation for you? Instead of using `validate_presence_of`, try
316
308
  end
317
309
 
318
310
  def belongs_to_association_being_validated?
319
- association_being_validated? &&
320
- association_reflection.macro == :belongs_to
311
+ association? && association_reflection.macro == :belongs_to
312
+ end
313
+
314
+ def attribute_accepts_string_values?
315
+ if association?
316
+ false
317
+ elsif attribute_serializer
318
+ attribute_serializer.object_class == String
319
+ else
320
+ attribute_type.try(:type) == :string
321
+ end
322
+ end
323
+
324
+ def association?
325
+ association_reflection.present?
321
326
  end
322
327
 
323
- def association_being_validated?
324
- !!association_reflection
328
+ def collection_association?
329
+ association? && association_reflection.macro.in?(
330
+ [:has_many, :has_and_belongs_to_many],
331
+ )
332
+ end
333
+
334
+ def attachment?
335
+ model_has_associations?(
336
+ ["#{@attribute}_attachment", "#{@attribute}_attachments"],
337
+ )
325
338
  end
326
339
 
327
340
  def association_name
@@ -333,8 +346,25 @@ validation for you? Instead of using `validate_presence_of`, try
333
346
  end
334
347
 
335
348
  def association_reflection
336
- model.respond_to?(:reflect_on_association) &&
337
- model.reflect_on_association(@attribute)
349
+ model.try(:reflect_on_association, @attribute)
350
+ end
351
+
352
+ def model_has_associations?(associations)
353
+ associations.any? do |association|
354
+ !!model.try(:reflect_on_association, association)
355
+ end
356
+ end
357
+
358
+ def attribute_serializer
359
+ if attribute_type.respond_to?(:coder)
360
+ attribute_type.coder
361
+ else
362
+ nil
363
+ end
364
+ end
365
+
366
+ def attribute_type
367
+ RailsShim.attribute_type_for(model, @attribute)
338
368
  end
339
369
 
340
370
  def presence_validation_exists_on_attribute?
@@ -2,7 +2,7 @@ module Shoulda
2
2
  module Matchers
3
3
  module ActiveRecord
4
4
  # The `define_enum_for` matcher is used to test that the `enum` macro has
5
- # been used to decorate an attribute with enum methods.
5
+ # been used to decorate an attribute with enum capabilities.
6
6
  #
7
7
  # class Process < ActiveRecord::Base
8
8
  # enum status: [:running, :stopped, :suspended]
@@ -22,8 +22,8 @@ module Shoulda
22
22
  #
23
23
  # ##### with_values
24
24
  #
25
- # Use `with_values` to test that the attribute has been defined with a
26
- # certain set of possible values.
25
+ # Use `with_values` to test that the attribute can only receive a certain
26
+ # set of possible values.
27
27
  #
28
28
  # class Process < ActiveRecord::Base
29
29
  # enum status: [:running, :stopped, :suspended]
@@ -43,10 +43,37 @@ module Shoulda
43
43
  # with_values([:running, :stopped, :suspended])
44
44
  # end
45
45
  #
46
+ # If the values backing your enum attribute are arbitrary instead of a
47
+ # series of integers starting from 0, pass a hash to `with_values` instead
48
+ # of an array:
49
+ #
50
+ # class Process < ActiveRecord::Base
51
+ # enum status: {
52
+ # running: 0,
53
+ # stopped: 1,
54
+ # suspended: 3,
55
+ # other: 99
56
+ # }
57
+ # end
58
+ #
59
+ # # RSpec
60
+ # RSpec.describe Process, type: :model do
61
+ # it do
62
+ # should define_enum_for(:status).
63
+ # with_values(running: 0, stopped: 1, suspended: 3, other: 99)
64
+ # end
65
+ # end
66
+ #
67
+ # # Minitest (Shoulda)
68
+ # class ProcessTest < ActiveSupport::TestCase
69
+ # should define_enum_for(:status).
70
+ # with_values(running: 0, stopped: 1, suspended: 3, other: 99)
71
+ # end
72
+ #
46
73
  # ##### backed_by_column_of_type
47
74
  #
48
- # Use `backed_by_column_of_type` to test that the attribute is of a
49
- # certain column type. (The default is `:integer`.)
75
+ # Use `backed_by_column_of_type` when the column backing your column type
76
+ # is a string instead of an integer:
50
77
  #
51
78
  # class LoanApplication < ActiveRecord::Base
52
79
  # enum status: {
@@ -156,6 +156,14 @@ module Shoulda
156
156
  nil
157
157
  end
158
158
 
159
+ def attribute_type_for(model, attribute_name)
160
+ if supports_full_attributes_api?(model)
161
+ model.attribute_types[attribute_name.to_s]
162
+ else
163
+ LegacyAttributeType.new(model, attribute_name)
164
+ end
165
+ end
166
+
159
167
  private
160
168
 
161
169
  def simply_generate_validation_message(
@@ -179,6 +187,30 @@ module Shoulda
179
187
  { default: default_translation_keys }.merge(options)
180
188
  I18n.translate(primary_translation_key, translate_options)
181
189
  end
190
+
191
+ def supports_full_attributes_api?(model)
192
+ defined?(::ActiveModel::Attributes) &&
193
+ model.respond_to?(:attribute_types)
194
+ end
195
+
196
+ class LegacyAttributeType
197
+ def initialize(model, attribute_name)
198
+ @model = model
199
+ @attribute_name = attribute_name
200
+ end
201
+
202
+ def coder
203
+ if model.respond_to?(:serialized_attributes)
204
+ ActiveSupport::Deprecation.silence do
205
+ model.serialized_attributes[attribute_name.to_s]
206
+ end
207
+ end
208
+ end
209
+
210
+ private
211
+
212
+ attr_reader :model, :attribute_name
213
+ end
182
214
  end
183
215
  end
184
216
  end
@@ -1,6 +1,6 @@
1
1
  module Shoulda
2
2
  module Matchers
3
3
  # @private
4
- VERSION = '4.1.0'.freeze
4
+ VERSION = '4.1.1'.freeze
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shoulda-matchers
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.0
4
+ version: 4.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tammer Saleh
@@ -14,7 +14,7 @@ authors:
14
14
  autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
- date: 2019-06-09 00:00:00.000000000 Z
17
+ date: 2019-07-15 00:00:00.000000000 Z
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
20
20
  name: activesupport