Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 118 additions & 2 deletions lib/shoulda/matchers/active_record/association_matcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,25 @@ module ActiveRecord
#
# @return [AssociationMatcher]
#
# ##### deprecated
#
# Use `deprecated` to assert that the `:deprecated` option was specified.
# (Enabled by default in Rails 8.1+).
#
# class Account < ActiveRecord::Base
# belongs_to :bank, deprecated: true
# end
#
# # RSpec
# RSpec.describe Account, type: :model do
# it { should belong_to(:bank).deprecated(true) }
# end
#
# # Minitest (Shoulda)
# class AccountTest < ActiveSupport::TestCase
# should belong_to(:bank).deprecated(true)
# end
#
Comment on lines +375 to +393
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move this up before the line 375

# ... new doc
#
# @return [AssociationMatcher]

The same comment applies to the other doc comments.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, thanks! Done in 2239770

def belong_to(name)
AssociationMatcher.new(:belongs_to, name)
end
Expand Down Expand Up @@ -683,7 +702,25 @@ def belong_to(name)
#
# @return [AssociationMatcher]
#

# ##### deprecated
#
# Use `deprecated` to assert that the association is not allowed to be nil.
# (Enabled by default in Rails 8.1+).
#
# class Vehicle < ActiveRecord::Base
# delegated_type :drivable, types: %w(Car Truck), deprecated: true
# end
#
# # RSpec
# describe Vehicle
# it { should have_delegated_type(:drivable).deprecated }
# end
#
# # Minitest (Shoulda)
# class VehicleTest < ActiveSupport::TestCase
# should have_delegated_type(:drivable).deprecated
# end
#
def have_delegated_type(name)
AssociationMatcher.new(:belongs_to, name)
end
Expand Down Expand Up @@ -972,6 +1009,25 @@ def have_delegated_type(name)
#
# @return [AssociationMatcher]
#
# ##### deprecated
#
# Use `deprecated` to assert that the `:deprecated` option was specified.
# (Enabled by default in Rails 8.1+)
#
# class Player < ActiveRecord::Base
# has_many :games, deprecated: true
# end
#
# # RSpec
# RSpec.describe Player, type: :model do
# it { should have_many(:games).deprecated(true) }
# end
#
# # Minitest (Shoulda)
# class PlayerTest < ActiveSupport::TestCase
# should have_many(:games).deprecated(true)
# end
#
def have_many(name)
AssociationMatcher.new(:has_many, name)
end
Expand Down Expand Up @@ -1219,6 +1275,25 @@ def have_many(name)
#
# @return [AssociationMatcher]
#
# ##### deprecated
#
# Use `deprecated` to assert that the `:deprecated` option was specified.
# (Enabled by default in Rails 8.1+).
#
# class Account < ActiveRecord::Base
# has_one :bank, deprecated: true
# end
#
# # RSpec
# RSpec.describe Account, type: :model do
# it { should have_one(:bank).deprecated(true) }
# end
#
# # Minitest (Shoulda)
# class AccountTest < ActiveSupport::TestCase
# should have_one(:bank).deprecated(true)
# end
#
def have_one(name)
AssociationMatcher.new(:has_one, name)
end
Expand Down Expand Up @@ -1377,6 +1452,27 @@ def have_one(name)
#
# @return [AssociationMatcher]
#
# ##### deprecated
#
# Use `deprecated` to assert that the `:deprecated` option was specified.
# (Enabled by default in Rails 8.1+).
#
# class Publisher < ActiveRecord::Base
# has_and_belongs_to_many :advertisers, deprecated: true
# end
#
# # RSpec
# RSpec.describe Publisher, type: :model do
# it { should have_and_belong_to_many(:advertisers).deprecated(true) }
# end
#
# # Minitest (Shoulda)
# class AccountTest < ActiveSupport::TestCase
# should have_and_belong_to_many(:advertisers).deprecated(true)
# end
#
# @return [AssociationMatcher]
#
def have_and_belong_to_many(name)
AssociationMatcher.new(:has_and_belongs_to_many, name)
end
Expand Down Expand Up @@ -1546,6 +1642,16 @@ def join_table(join_table_name)
self
end

def deprecated(deprecated = true)
if ::ActiveRecord::VERSION::STRING >= '8.1'
@options[:deprecated] = deprecated
self
else
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can have a new method in the lib/shoulda/matchers/rails_shim.rb file to have that active record version check.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great idea! Refactored this in 9450ae8

raise NotImplementedError,
'`deprecated` association matcher is only available on Active Record >= 8.1.'
end
end

def without_validating_presence
remove_submatcher(AssociationMatchers::RequiredMatcher)
self
Expand Down Expand Up @@ -1586,7 +1692,8 @@ def matches?(subject)
touch_correct? &&
types_correct? &&
strict_loading_correct? &&
submatchers_match?
submatchers_match? &&
deprecated_correct?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's leave the submatchers_match? as the last check, as they're usually a slower check.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in df61574

end

def join_table_name
Expand Down Expand Up @@ -1848,6 +1955,15 @@ def touch_correct?
end
end

def deprecated_correct?
if option_verifier.correct_for_boolean?(:deprecated, options[:deprecated])
true
else
@missing = "#{name} should have deprecated: #{options[:deprecated]}"
false
end
end

def types_correct?
if options.key?(:types)
types = options[:types]
Expand Down
Loading
Loading