shoulda-matchers 4.5.0 → 5.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0268da0cff119fb6c9128b70f1826451b582bdc2495acf382f4e512a6636d0c8'
4
- data.tar.gz: bf0698ed7605d8a8ef6b7e78bdc198bfa9502e1f2df134e3c5f524d1809b82da
3
+ metadata.gz: 188abbfbc6cac3e26997733b3d88b34ea74e9747e25f137738190bf15d033751
4
+ data.tar.gz: 73136b35573cffac784cadd7e3193e8e9a0934f0e69fa751f536ed589db01024
5
5
  SHA512:
6
- metadata.gz: 407cc79fc367dd4f02b346a199a8d9a9c4ecc5f2d814b98b25989489d96fd2d02308459e2d3a086aeacd67cbd5a9e91e7e237f3fe04efb64c196307dd53abe71
7
- data.tar.gz: a4eb04356408c22c7606ef403e1d4a042461e5323a9459875ad6a67f9f5cbc2944dee295d6086e6f1bea5b1d4fd7cace0fc5b701a4ba0199c75f7f002939f47a
6
+ metadata.gz: 55f3ccad9ce3d4affcb6ccc38020872bc000710f887765d7b78962bcdd339d79a2a1316e3a9d2cb33c62887e66bab9e54801d79c872f6cab7a2459a32ddce4bf
7
+ data.tar.gz: e5a862e62f25dfe284f0325f20600bbc4a3567ef78a0b7742685d1a9af9d03147ab650a259be287bd4566719444c7d998c0106874b7c3ac43efbd79996191838
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
- # Shoulda Matchers [![Gem Version][version-badge]][rubygems] [![Build Status][travis-badge]][travis] [![Total Downloads][downloads-total]][rubygems] [![Downloads][downloads-badge]][rubygems]
1
+ # Shoulda Matchers [![Gem Version][version-badge]][rubygems] [![Build Status][github-actions-badge]][github-actions] [![Total Downloads][downloads-total]][rubygems] [![Downloads][downloads-badge]][rubygems]
2
2
 
3
3
  [version-badge]: https://img.shields.io/gem/v/shoulda-matchers.svg
4
4
  [rubygems]: https://rubygems.org/gems/shoulda-matchers
5
- [travis-badge]: https://img.shields.io/travis/thoughtbot/shoulda-matchers/master.svg
6
- [travis]: https://travis-ci.org/thoughtbot/shoulda-matchers
5
+ [github-actions-badge]: https://img.shields.io/github/workflow/status/thoughtbot/shoulda-matchers/Test
6
+ [github-actions]: https://github.com/thoughtbot/shoulda-matchers/actions
7
7
  [downloads-total]: https://img.shields.io/gem/dt/shoulda-matchers.svg
8
8
  [downloads-badge]: https://img.shields.io/gem/dtv/shoulda-matchers.svg
9
9
  [downloads-badge]: https://img.shields.io/gem/dtv/shoulda-matchers.svg
@@ -55,7 +55,7 @@ Start by including `shoulda-matchers` in your Gemfile:
55
55
 
56
56
  ```ruby
57
57
  group :test do
58
- gem 'shoulda-matchers', '~> 4.0'
58
+ gem 'shoulda-matchers', '~> 5.0'
59
59
  end
60
60
  ```
61
61
 
@@ -430,11 +430,11 @@ about any of them, make sure to [consult the documentation][rubydocs]!
430
430
  makes assertions on the `session` hash.
431
431
  * **[set_flash](lib/shoulda/matchers/action_controller/set_flash_matcher.rb)**
432
432
  makes assertions on the `flash` hash.
433
- * **[use_after_action](lib/shoulda/matchers/action_controller/callback_matcher.rb#L79)**
433
+ * **[use_after_action](lib/shoulda/matchers/action_controller/callback_matcher.rb#L29)**
434
434
  tests that an `after_action` callback is defined in your controller.
435
- * **[use_around_action](lib/shoulda/matchers/action_controller/callback_matcher.rb#L129)**
435
+ * **[use_around_action](lib/shoulda/matchers/action_controller/callback_matcher.rb#L75)**
436
436
  tests that an `around_action` callback is defined in your controller.
437
- * **[use_before_action](lib/shoulda/matchers/action_controller/callback_matcher.rb#L54)**
437
+ * **[use_before_action](lib/shoulda/matchers/action_controller/callback_matcher.rb#L4)**
438
438
  tests that a `before_action` callback is defined in your controller.
439
439
 
440
440
  ### Routing matchers
@@ -468,12 +468,14 @@ machine, understanding the codebase, and creating a good pull request.
468
468
 
469
469
  ## Compatibility
470
470
 
471
- Shoulda Matchers is [tested][travis] and supported against Ruby 2.4+, Rails
472
- 4.2+, RSpec 3.x, and Minitest 5.x.
471
+ Shoulda Matchers is tested and supported against Ruby 2.6+, Rails
472
+ 5.2+, RSpec 3.x, and Minitest 5.x.
473
473
 
474
- For Ruby < 2.4 and Rails < 4.1 compatibility, please use [v3.1.3][v3.1.3].
474
+ - For Ruby < 2.4 and Rails < 4.1 compatibility, please use [v3.1.3][v3.1.3].
475
+ - For Ruby < 3.0 and Rails < 6.1 compatibility, please use [v4.5.1][v4.5.1].
475
476
 
476
477
  [v3.1.3]: https://github.com/thoughtbot/shoulda-matchers/tree/v3.1.3
478
+ [v4.5.1]: https://github.com/thoughtbot/shoulda-matchers/tree/v4.5.1
477
479
 
478
480
  ## Versioning
479
481
 
@@ -1,64 +1,6 @@
1
1
  module Shoulda
2
2
  module Matchers
3
3
  module ActionController
4
- # The `use_before_filter` matcher is used to test that a before_filter
5
- # callback is defined within your controller.
6
- #
7
- # class UsersController < ApplicationController
8
- # before_filter :authenticate_user!
9
- # end
10
- #
11
- # # RSpec
12
- # RSpec.describe UsersController, type: :controller do
13
- # it { should use_before_filter(:authenticate_user!) }
14
- # it { should_not use_before_filter(:prevent_ssl) }
15
- # end
16
- #
17
- # # Minitest (Shoulda)
18
- # class UsersControllerTest < ActionController::TestCase
19
- # should use_before_filter(:authenticate_user!)
20
- # should_not use_before_filter(:prevent_ssl)
21
- # end
22
- #
23
- # @note This method is only available when using shoulda-matchers under
24
- # Rails 4.x.
25
- # @return [CallbackMatcher]
26
- #
27
- if RailsShim.action_pack_lt_5?
28
- def use_before_filter(callback)
29
- CallbackMatcher.new(callback, :before, :filter)
30
- end
31
- end
32
-
33
- # The `use_after_filter` matcher is used to test that an after_filter
34
- # callback is defined within your controller.
35
- #
36
- # class IssuesController < ApplicationController
37
- # after_filter :log_activity
38
- # end
39
- #
40
- # # RSpec
41
- # RSpec.describe IssuesController, type: :controller do
42
- # it { should use_after_filter(:log_activity) }
43
- # it { should_not use_after_filter(:destroy_user) }
44
- # end
45
- #
46
- # # Minitest (Shoulda)
47
- # class IssuesControllerTest < ActionController::TestCase
48
- # should use_after_filter(:log_activity)
49
- # should_not use_after_filter(:destroy_user)
50
- # end
51
- #
52
- # @note This method is only available when using shoulda-matchers under
53
- # Rails 4.x.
54
- # @return [CallbackMatcher]
55
- #
56
- if RailsShim.action_pack_lt_5?
57
- def use_after_filter(callback)
58
- CallbackMatcher.new(callback, :after, :filter)
59
- end
60
- end
61
-
62
4
  # The `use_before_action` matcher is used to test that a before_action
63
5
  # callback is defined within your controller.
64
6
  #
@@ -109,35 +51,6 @@ module Shoulda
109
51
  CallbackMatcher.new(callback, :after, :action)
110
52
  end
111
53
 
112
- # The `use_around_filter` matcher is used to test that an around_filter
113
- # callback is defined within your controller.
114
- #
115
- # class ChangesController < ApplicationController
116
- # around_filter :wrap_in_transaction
117
- # end
118
- #
119
- # # RSpec
120
- # RSpec.describe ChangesController, type: :controller do
121
- # it { should use_around_filter(:wrap_in_transaction) }
122
- # it { should_not use_around_filter(:save_view_context) }
123
- # end
124
- #
125
- # # Minitest (Shoulda)
126
- # class ChangesControllerTest < ActionController::TestCase
127
- # should use_around_filter(:wrap_in_transaction)
128
- # should_not use_around_filter(:save_view_context)
129
- # end
130
- #
131
- # @note This method is only available when using shoulda-matchers under
132
- # Rails 4.x.
133
- # @return [CallbackMatcher]
134
- #
135
- if RailsShim.action_pack_lt_5?
136
- def use_around_filter(callback)
137
- CallbackMatcher.new(callback, :around, :filter)
138
- end
139
- end
140
-
141
54
  # The `use_around_action` matcher is used to test that an around_action
142
55
  # callback is defined within your controller.
143
56
  #
@@ -1,3 +1,4 @@
1
+ require 'active_support/core_ext/module/delegation'
1
2
  module Shoulda
2
3
  module Matchers
3
4
  module ActionController
@@ -34,10 +35,7 @@ module Shoulda
34
35
  expected_value === actual_value
35
36
  end
36
37
  end
37
-
38
- def empty?
39
- flash.empty?
40
- end
38
+ delegate :empty?, to: :flash
41
39
 
42
40
  def use_now!
43
41
  @use_now = true
@@ -251,12 +251,9 @@ module Shoulda
251
251
  parameters_double_registry.register
252
252
 
253
253
  Doublespeak.with_doubles_activated do
254
- Shoulda::Matchers::RailsShim.make_controller_request(
255
- context,
256
- verb,
257
- action,
258
- request_params,
259
- )
254
+ params = { params: request_params }
255
+
256
+ context.__send__(verb, action, **params)
260
257
  end
261
258
 
262
259
  unpermitted_parameter_names.empty?
@@ -8,7 +8,7 @@ module Shoulda
8
8
  end
9
9
 
10
10
  def format_validation_errors(errors)
11
- list_items = errors.keys.map do |attribute|
11
+ list_items = errors.to_hash.keys.map do |attribute|
12
12
  messages = errors[attribute]
13
13
  "* #{attribute}: #{messages}"
14
14
  end
@@ -109,11 +109,13 @@ module Shoulda
109
109
  end
110
110
  elsif array_column?
111
111
  ['an arbitary value']
112
+ elsif enum_column?
113
+ enum_values.first
112
114
  else
113
115
  case column_type
114
116
  when :integer, :float then 1
115
117
  when :decimal then BigDecimal(1, 0)
116
- when :datetime, :time, :timestamp then Time.now
118
+ when :datetime, :time, :timestamp then Time.current
117
119
  when :date then Date.new
118
120
  when :binary then '0'
119
121
  else 'an arbitrary value'
@@ -145,6 +147,15 @@ module Shoulda
145
147
  @subject.class.columns_hash[@attribute.to_s].respond_to?(:array) &&
146
148
  @subject.class.columns_hash[@attribute.to_s].array
147
149
  end
150
+
151
+ def enum_column?
152
+ @subject.class.respond_to?(:defined_enums) &&
153
+ @subject.class.defined_enums.key?(@attribute.to_s)
154
+ end
155
+
156
+ def enum_values
157
+ @subject.class.defined_enums[@attribute.to_s].values
158
+ end
148
159
  end
149
160
  end
150
161
  end
@@ -355,7 +355,7 @@ EOT
355
355
  description = "validate that :#{@attribute}"
356
356
 
357
357
  description <<
358
- if @array.many?
358
+ if @array.count > 1
359
359
  " is either #{inspected_array}"
360
360
  else
361
361
  " is #{inspected_array}"
@@ -643,7 +643,7 @@ module Shoulda
643
643
  if number_of_submatchers_for_failure_message > 1
644
644
  "In checking that #{model.name} #{submatcher_description}, " +
645
645
  failure_message[0].downcase +
646
- failure_message[1..-1]
646
+ failure_message[1..]
647
647
  else
648
648
  failure_message
649
649
  end
@@ -327,8 +327,8 @@ validation for you? Instead of using `validate_presence_of`, try
327
327
  end
328
328
 
329
329
  def collection_association?
330
- association? && association_reflection.macro.in?(
331
- [:has_many, :has_and_belongs_to_many],
330
+ association? && [:has_many, :has_and_belongs_to_many].include?(
331
+ association_reflection.macro,
332
332
  )
333
333
  end
334
334
 
@@ -98,12 +98,7 @@ module Shoulda
98
98
 
99
99
  all_validation_errors = record.errors.dup
100
100
 
101
- validation_error_messages =
102
- if record.errors.respond_to?(:[])
103
- record.errors[attribute]
104
- else
105
- record.errors.on(attribute)
106
- end
101
+ validation_error_messages = record.errors[attribute]
107
102
 
108
103
  {
109
104
  all_validation_errors: all_validation_errors,
@@ -26,7 +26,6 @@ require 'shoulda/matchers/active_model/numericality_matchers/comparison_matcher'
26
26
  require 'shoulda/matchers/active_model/numericality_matchers/odd_number_matcher'
27
27
  require 'shoulda/matchers/active_model/numericality_matchers/even_number_matcher'
28
28
  require 'shoulda/matchers/active_model/numericality_matchers/only_integer_matcher'
29
- require 'shoulda/matchers/active_model/allow_mass_assignment_of_matcher'
30
29
  require 'shoulda/matchers/active_model/errors'
31
30
  require 'shoulda/matchers/active_model/have_secure_password_matcher'
32
31
 
@@ -1004,7 +1004,7 @@ module Shoulda
1004
1004
  @submatchers = []
1005
1005
  @missing = ''
1006
1006
 
1007
- if macro == :belongs_to && RailsShim.active_record_gte_5?
1007
+ if macro == :belongs_to
1008
1008
  required(belongs_to_required_by_default?)
1009
1009
  end
1010
1010
  end
@@ -1394,14 +1394,25 @@ module Shoulda
1394
1394
  end
1395
1395
 
1396
1396
  def class_has_foreign_key?(klass)
1397
+ @missing = validate_foreign_key(klass)
1398
+
1399
+ @missing.nil?
1400
+ end
1401
+
1402
+ def validate_foreign_key(klass)
1397
1403
  if options.key?(:foreign_key) && !foreign_key_correct?
1398
- @missing = foreign_key_failure_message(klass, options[:foreign_key])
1399
- false
1400
- elsif !column_names_for(klass).include?(foreign_key)
1401
- @missing = foreign_key_failure_message(klass, foreign_key)
1402
- false
1404
+ foreign_key_failure_message(klass, options[:foreign_key])
1405
+ elsif !has_column?(klass, actual_foreign_key)
1406
+ foreign_key_failure_message(klass, actual_foreign_key)
1407
+ end
1408
+ end
1409
+
1410
+ def has_column?(klass, column)
1411
+ case column
1412
+ when Array
1413
+ column.all? { |c| has_column?(klass, c.to_s) }
1403
1414
  else
1404
- true
1415
+ column_names_for(klass).include?(column.to_s)
1405
1416
  end
1406
1417
  end
1407
1418
 
@@ -1433,13 +1444,15 @@ module Shoulda
1433
1444
  end
1434
1445
  end
1435
1446
 
1436
- def foreign_key
1437
- if foreign_key_reflection
1438
- if foreign_key_reflection.respond_to?(:foreign_key)
1439
- foreign_key_reflection.foreign_key.to_s
1440
- else
1441
- foreign_key_reflection.primary_key_name.to_s
1442
- end
1447
+ def actual_foreign_key
1448
+ return unless foreign_key_reflection
1449
+
1450
+ if foreign_key_reflection.options[:foreign_key]
1451
+ foreign_key_reflection.options[:foreign_key]
1452
+ elsif foreign_key_reflection.respond_to?(:foreign_key)
1453
+ foreign_key_reflection.foreign_key
1454
+ else
1455
+ foreign_key_reflection.primary_key_name
1443
1456
  end
1444
1457
  end
1445
1458
 
@@ -42,7 +42,7 @@ module Shoulda
42
42
  end
43
43
 
44
44
  def join_table_exists?
45
- if RailsShim.tables_and_views(connection).
45
+ if connection.data_sources.
46
46
  include?(join_table_name.to_s)
47
47
  true
48
48
  else
@@ -65,7 +65,7 @@ module Shoulda
65
65
  end
66
66
 
67
67
  def validation_message_key
68
- RailsShim.validation_message_key_for_association_required_option
68
+ :required
69
69
  end
70
70
  end
71
71
  end
@@ -6,16 +6,22 @@ module Shoulda
6
6
  #
7
7
  # class Process < ActiveRecord::Base
8
8
  # enum status: [:running, :stopped, :suspended]
9
+ #
10
+ # alias_attribute :kind, :SomeLegacyField
11
+ #
12
+ # enum kind: [:foo, :bar]
9
13
  # end
10
14
  #
11
15
  # # RSpec
12
16
  # RSpec.describe Process, type: :model do
13
17
  # it { should define_enum_for(:status) }
18
+ # it { should define_enum_for(:kind) }
14
19
  # end
15
20
  #
16
21
  # # Minitest (Shoulda)
17
22
  # class ProcessTest < ActiveSupport::TestCase
18
23
  # should define_enum_for(:status)
24
+ # should define_enum_for(:kind)
19
25
  # end
20
26
  #
21
27
  # #### Qualifiers
@@ -370,7 +376,10 @@ module Shoulda
370
376
  end
371
377
 
372
378
  def column
373
- model.columns_hash[attribute_name.to_s]
379
+ key = attribute_name.to_s
380
+ column_name = model.attribute_alias(key) || key
381
+
382
+ model.columns_hash[column_name]
374
383
  end
375
384
 
376
385
  def model
@@ -52,7 +52,7 @@ module Shoulda
52
52
  #
53
53
  # Use `with_options` to assert that a column has been defined with
54
54
  # certain options (`:precision`, `:limit`, `:default`, `:null`, `:scale`,
55
- # or `:primary`).
55
+ # `:primary` or `:array`).
56
56
  #
57
57
  # class CreatePhones < ActiveRecord::Migration
58
58
  # def change
@@ -84,7 +84,7 @@ module Shoulda
84
84
 
85
85
  # @private
86
86
  class HaveDbColumnMatcher
87
- OPTIONS = %i(precision limit default null scale primary).freeze
87
+ OPTIONS = %i(precision limit default null scale primary array).freeze
88
88
 
89
89
  def initialize(column)
90
90
  @column = column
@@ -115,7 +115,8 @@ module Shoulda
115
115
  correct_default? &&
116
116
  correct_null? &&
117
117
  correct_scale? &&
118
- correct_primary?
118
+ correct_primary? &&
119
+ correct_array?
119
120
  end
120
121
 
121
122
  def failure_message
@@ -258,6 +259,23 @@ module Shoulda
258
259
  end
259
260
  end
260
261
 
262
+ def correct_array?
263
+ return true unless @options.key?(:array)
264
+
265
+ if matched_column.array? == @options[:array]
266
+ true
267
+ else
268
+ @missing = "#{model_class} has a db column named #{@column} "
269
+ @missing <<
270
+ if @options[:primary]
271
+ 'that is not array, but should be'
272
+ else
273
+ 'that is array, but should not be'
274
+ end
275
+ false
276
+ end
277
+ end
278
+
261
279
  def matched_column
262
280
  @_matched_column ||= begin
263
281
  column = model_class.columns.detect do |each|
@@ -3,24 +3,12 @@ module Shoulda
3
3
  # @private
4
4
  module RailsShim # rubocop:disable Metrics/ModuleLength
5
5
  class << self
6
- def action_pack_gte_5?
7
- Gem::Requirement.new('>= 5').satisfied_by?(action_pack_version)
8
- end
9
-
10
- def action_pack_lt_5?
11
- Gem::Requirement.new('< 5').satisfied_by?(action_pack_version)
12
- end
13
-
14
6
  def action_pack_version
15
7
  Gem::Version.new(::ActionPack::VERSION::STRING)
16
8
  rescue NameError
17
9
  Gem::Version.new('0')
18
10
  end
19
11
 
20
- def active_record_gte_5?
21
- Gem::Requirement.new('>= 5').satisfied_by?(active_record_version)
22
- end
23
-
24
12
  def active_record_gte_6?
25
13
  Gem::Requirement.new('>= 6').satisfied_by?(active_record_version)
26
14
  end
@@ -57,17 +45,6 @@ module Shoulda
57
45
  )
58
46
  end
59
47
 
60
- def make_controller_request(context, verb, action, request_params)
61
- params =
62
- if action_pack_gte_5?
63
- { params: request_params }
64
- else
65
- request_params
66
- end
67
-
68
- context.__send__(verb, action, params)
69
- end
70
-
71
48
  def serialized_attributes_for(model)
72
49
  attribute_types_for(model).
73
50
  inject({}) do |hash, (attribute_name, attribute_type)|
@@ -85,26 +62,10 @@ module Shoulda
85
62
  serialized_attributes_for(model)[attribute_name.to_s]
86
63
  end
87
64
 
88
- def tables_and_views(connection)
89
- if active_record_gte_5?
90
- connection.data_sources
91
- else
92
- connection.tables
93
- end
94
- end
95
-
96
65
  def verb_for_update
97
66
  :patch
98
67
  end
99
68
 
100
- def validation_message_key_for_association_required_option
101
- if active_record_gte_5?
102
- :required
103
- else
104
- :blank
105
- end
106
- end
107
-
108
69
  def parent_of(mod)
109
70
  if mod.respond_to?(:module_parent)
110
71
  mod.module_parent
@@ -185,7 +185,7 @@ module Shoulda
185
185
  leftover = ''
186
186
  else
187
187
  fitted_line = line[0..index].rstrip
188
- leftover = line[index + 1..-1]
188
+ leftover = line[index + 1..]
189
189
  end
190
190
 
191
191
  { fitted_line: fitted_line, leftover: leftover }
@@ -1,6 +1,6 @@
1
1
  module Shoulda
2
2
  module Matchers
3
3
  # @private
4
- VERSION = '4.5.0'.freeze
4
+ VERSION = '5.1.0'.freeze
5
5
  end
6
6
  end
@@ -36,6 +36,6 @@ Gem::Specification.new do |s|
36
36
  'shoulda-matchers.gemspec']
37
37
  s.require_paths = ['lib']
38
38
 
39
- s.required_ruby_version = '>= 2.4.0'
40
- s.add_dependency('activesupport', '>= 4.2.0')
39
+ s.required_ruby_version = '>= 2.6.0'
40
+ s.add_dependency('activesupport', '>= 5.2.0')
41
41
  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.5.0
4
+ version: 5.1.0
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: 2021-01-11 00:00:00.000000000 Z
17
+ date: 2021-12-22 00:00:00.000000000 Z
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
20
20
  name: activesupport
@@ -22,14 +22,14 @@ dependencies:
22
22
  requirements:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: 4.2.0
25
+ version: 5.2.0
26
26
  type: :runtime
27
27
  prerelease: false
28
28
  version_requirements: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 4.2.0
32
+ version: 5.2.0
33
33
  description: 'Shoulda Matchers provides RSpec- and Minitest-compatible one-liners
34
34
  to test common Rails functionality that, if written by hand, would be much longer,
35
35
  more complex, and error-prone. '
@@ -60,7 +60,6 @@ files:
60
60
  - lib/shoulda/matchers/action_controller/set_session_matcher.rb
61
61
  - lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb
62
62
  - lib/shoulda/matchers/active_model.rb
63
- - lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb
64
63
  - lib/shoulda/matchers/active_model/allow_value_matcher.rb
65
64
  - lib/shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error.rb
66
65
  - lib/shoulda/matchers/active_model/allow_value_matcher/attribute_does_not_exist_error.rb
@@ -186,14 +185,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
186
185
  requirements:
187
186
  - - ">="
188
187
  - !ruby/object:Gem::Version
189
- version: 2.4.0
188
+ version: 2.6.0
190
189
  required_rubygems_version: !ruby/object:Gem::Requirement
191
190
  requirements:
192
191
  - - ">="
193
192
  - !ruby/object:Gem::Version
194
193
  version: '0'
195
194
  requirements: []
196
- rubygems_version: 3.1.4
195
+ rubygems_version: 3.2.32
197
196
  signing_key:
198
197
  specification_version: 4
199
198
  summary: Simple one-liner tests for common Rails functionality
@@ -1,161 +0,0 @@
1
- module Shoulda
2
- module Matchers
3
- module ActiveModel
4
- # The `allow_mass_assignment_of` matcher tests usage of Rails 3's
5
- # `attr_accessible` and `attr_protected` macros, asserting that an
6
- # attribute in your model is contained in either the whitelist or
7
- # blacklist and thus can or cannot be set via mass assignment.
8
- #
9
- # class Post
10
- # include ActiveModel::Model
11
- # include ActiveModel::MassAssignmentSecurity
12
- # attr_accessor :title
13
- #
14
- # attr_accessible :title
15
- # end
16
- #
17
- # class User
18
- # include ActiveModel::Model
19
- # include ActiveModel::MassAssignmentSecurity
20
- # attr_accessor :encrypted_password
21
- #
22
- # attr_protected :encrypted_password
23
- # end
24
- #
25
- # # RSpec
26
- # RSpec.describe Post, type: :model do
27
- # it { should allow_mass_assignment_of(:title) }
28
- # end
29
- #
30
- # RSpec.describe User, type: :model do
31
- # it { should_not allow_mass_assignment_of(:encrypted_password) }
32
- # end
33
- #
34
- # # Minitest (Shoulda)
35
- # class PostTest < ActiveSupport::TestCase
36
- # should allow_mass_assignment_of(:title)
37
- # end
38
- #
39
- # class UserTest < ActiveSupport::TestCase
40
- # should_not allow_mass_assignment_of(:encrypted_password)
41
- # end
42
- #
43
- # #### Optional qualifiers
44
- #
45
- # ##### as
46
- #
47
- # Use `as` if your mass-assignment rules apply only under a certain role
48
- # *(Rails >= 3.1 only)*.
49
- #
50
- # class Post
51
- # include ActiveModel::Model
52
- # include ActiveModel::MassAssignmentSecurity
53
- # attr_accessor :title
54
- #
55
- # attr_accessible :title, as: :admin
56
- # end
57
- #
58
- # # RSpec
59
- # RSpec.describe Post, type: :model do
60
- # it { should allow_mass_assignment_of(:title).as(:admin) }
61
- # end
62
- #
63
- # # Minitest (Shoulda)
64
- # class PostTest < ActiveSupport::TestCase
65
- # should allow_mass_assignment_of(:title).as(:admin)
66
- # end
67
- #
68
- # @return [AllowMassAssignmentOfMatcher]
69
- #
70
- def allow_mass_assignment_of(value)
71
- AllowMassAssignmentOfMatcher.new(value)
72
- end
73
-
74
- # @private
75
- class AllowMassAssignmentOfMatcher
76
- attr_reader :failure_message, :failure_message_when_negated
77
-
78
- def initialize(attribute)
79
- @attribute = attribute.to_s
80
- @options = {}
81
- end
82
-
83
- def as(role)
84
- @options[:role] = role
85
- self
86
- end
87
-
88
- def matches?(subject)
89
- @subject = subject
90
- if attr_mass_assignable?
91
- if whitelisting?
92
- @failure_message_when_negated = "#{@attribute} was made "\
93
- 'accessible'
94
- elsif protected_attributes.empty?
95
- @failure_message_when_negated = 'no attributes were protected'
96
- else
97
- @failure_message_when_negated =
98
- "#{class_name} is protecting " <<
99
- "#{protected_attributes.to_a.to_sentence}, " <<
100
- "but not #{@attribute}."
101
- end
102
- true
103
- else
104
- @failure_message =
105
- if whitelisting?
106
- "Expected #{@attribute} to be accessible"
107
- else
108
- "Did not expect #{@attribute} to be protected"
109
- end
110
- false
111
- end
112
- end
113
-
114
- def description
115
- [base_description, role_description].compact.join(' ')
116
- end
117
-
118
- private
119
-
120
- def base_description
121
- "allow mass assignment of #{@attribute}"
122
- end
123
-
124
- def role_description
125
- if role != :default
126
- "as #{role}"
127
- end
128
- end
129
-
130
- def role
131
- @options[:role] || :default
132
- end
133
-
134
- def protected_attributes
135
- @_protected_attributes ||= (@subject.class.protected_attributes || [])
136
- end
137
-
138
- def accessible_attributes
139
- @_accessible_attributes ||=
140
- (@subject.class.accessible_attributes || [])
141
- end
142
-
143
- def whitelisting?
144
- authorizer.is_a?(::ActiveModel::MassAssignmentSecurity::WhiteList)
145
- end
146
-
147
- def attr_mass_assignable?
148
- !authorizer.deny?(@attribute)
149
- end
150
-
151
- def authorizer
152
- @subject.class.active_authorizer[role]
153
- end
154
-
155
- def class_name
156
- @subject.class.name
157
- end
158
- end
159
- end
160
- end
161
- end