Skip to content

feat: Add support for validating multiple attributes at once#1651

Open
matsales28 wants to merge 1 commit into
mainfrom
mus-add-matcher-collection-feature
Open

feat: Add support for validating multiple attributes at once#1651
matsales28 wants to merge 1 commit into
mainfrom
mus-add-matcher-collection-feature

Conversation

@matsales28
Copy link
Copy Markdown
Member

@matsales28 matsales28 commented Sep 13, 2024

This commit adds support for asserting against multiple attributes in a
single matcher expression. Instead of writing one expectation per
attribute, you can pass the attributes as positional arguments:

class Robot
 include ActiveModel::Model
 attr_accessor :arms, :legs

 validates_presence_of :arms, :legs
end

RSpec.describe Robot, type: :model do
 it { expect(subject).to validate_presence_of(:arms, :legs) }
end

This is implemented by a new Shoulda::Matchers::MatcherCollection
class that wraps individual matchers and produces a combined
description and per-attribute failure reasons in a single message.

The following matchers now support multiple attributes:

  • validate_presence_of
  • validate_absence_of
  • validate_acceptance_of
  • validate_confirmation_of
  • validate_length_of
  • validate_numericality_of
  • validate_inclusion_of
  • validate_exclusion_of
  • validate_comparison_of
  • have_readonly_attribute
  • have_one_attached

Qualifiers chained on the matcher are applied to every wrapped
attribute uniformly. For example:

expect(subject).to validate_presence_of(:arms, :legs).allow_nil

asserts that both :arms and :legs allow nil. If any attribute
fails the expectation, the failure message lists every failed
attribute and the specific reason each one failed.

@matsales28 matsales28 force-pushed the mus-add-matcher-collection-feature branch 2 times, most recently from 8fd0a26 to 22c7f16 Compare September 13, 2024 16:45
@matsales28 matsales28 force-pushed the mus-add-matcher-collection-feature branch 3 times, most recently from 655047a to 802626c Compare May 25, 2026 19:48
This commit adds support for asserting against multiple attributes in a
single matcher expression. Instead of writing one expectation per
attribute, you can pass the attributes as positional arguments:

```ruby
class Robot
 include ActiveModel::Model
 attr_accessor :arms, :legs

 validates_presence_of :arms, :legs
end

RSpec.describe Robot, type: :model do
 it { expect(subject).to validate_presence_of(:arms, :legs) }
end
```

This is implemented by a new `Shoulda::Matchers::MatcherCollection`
class that wraps individual matchers and produces a combined
description and per-attribute failure reasons in a single message.

The following matchers now support multiple attributes:

- `validate_presence_of`
- `validate_absence_of`
- `validate_acceptance_of`
- `validate_confirmation_of`
- `validate_length_of`
- `validate_numericality_of`
- `validate_inclusion_of`
- `validate_exclusion_of`
- `validate_comparison_of`
- `have_readonly_attribute`
- `have_one_attached`

Qualifiers chained on the matcher are applied to every wrapped
attribute uniformly. For example:

```ruby
expect(subject).to validate_presence_of(:arms, :legs).allow_nil
```

asserts that both `:arms` and `:legs` allow nil. If any attribute
fails the expectation, the failure message lists every failed
attribute and the specific reason each one failed.
@matsales28 matsales28 force-pushed the mus-add-matcher-collection-feature branch from 802626c to 67927c2 Compare May 25, 2026 20:04
@matsales28 matsales28 marked this pull request as ready for review May 25, 2026 20:13
@matsales28 matsales28 self-assigned this May 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant