Commit Graph

19 Commits

Author SHA1 Message Date
Masato Ohba 1b949d12d5
Fix typo: arbitary -> arbitrary (#1515) 2022-10-18 18:29:02 -03:00
Gabriel Sobrinho ed60e91741
Support enum attributes on validate_absence_of (#1464) 2021-12-20 12:33:23 -03:00
Shubhendra Singh Chauhan 293a815fbe
fix: issues affecting code quality (#1420)
* use `delegate` for delegation
* Time should be used with zone
2021-04-15 09:44:33 -06:00
thealiilman e19ebf291d Fix validate_absence_of failing for array columns
This commit fixes [#1240](https://github.com/thoughtbot/shoulda-matchers/issues/1240).

Changelog

- Made `ValidatingAbsenceOfMatcher#value` check whether column is array

- Added tests on array columns for `ValidateAbsenceOfMatcher`
2020-12-03 09:20:58 -07:00
Kapil Sachdev ee1008de7a fix(rubocop): Fix Layout related offenses [ci skip]
- Layout/EmptyLines
- Layout/EmptyLineAfterGuardClause
- Layout/TrailingEmptyLines
- Layout/EmptyLinesAroundBlockBody
- Layout/EmptyLinesAroundModuleBody
- Layout/EmptyLineAfterMagicComment
- Layout/SpaceInsidePercentLiteralDelimiters
- Layout/SpaceAroundEqualsInParameterDefault
- Layout/SpaceInsideArrayLiteralBrackets
- Layout/LeadingCommentSpace
- Layout/SpaceBeforeComment
- Layout/SpaceAroundOperators
- Layout/SpaceInsideRangeLiteral
- Layout/SpaceInsideReferenceBrackets
- Layout/SpaceInLambdaLiteral
- Layout/SpaceAfterComma
- Layout/SpaceInsideHashLiteralBraces
- Layout/TrailingWhitespace
- Layout/ArgumentAlignment
- Layout/HashAlignment
- Layout/DotPosition
- Layout/IndentationWidth
- Layout/EndAlignment
- Layout/MultilineOperationIndentation
- Layout/IndentationConsistency
- Layout/ClosingHeredocIndentation
- Layout/MultilineMethodCallBrace- Layout
- Layout/ClosingParenthesisIndentation
2020-11-03 10:05:25 -07:00
Elliot Winkler 507dc57004 Fix negative versions of validation matchers
When using a validation matcher in the negative, i.e.:

    should_not validate_*(...)

as opposed to:

    should validate_*(...)

...it's common to receive the following error:

    undefined method `attribute_setter' for nil:NilClass

This happens particularly when using a matcher that makes use of
AllowValueMatcher or DisallowValueMatcher internally (which all of the
validation matchers do).

Whenever you make an assertion by using a matcher in the negative as
opposed to the positive, RSpec still calls the `matches?` method for
that matcher; however, the assertion will pass if that returns *false*
as opposed to true. In other words, it just inverts the result.

However, whenever we are using AllowValueMatcher or
DisallowValueMatcher, it doesn't really work to invert the result. like
this. This is because AllowValueMatcher and DisallowValueMatcher,
despite their name, aren't truly opposites of each other.

AllowValueMatcher performs these steps:

1. Set the attribute on the record to some value
2. Run validations on the record
3. Ask whether validations pass or fail
4. If validations fail, store the value that caused the failure along
   with the validation errors and return false
5. Otherwise, return true

However, DisallowValueMatcher performs these steps:

1. Set the attribute on the record to some value
2. Run validations on the record
3. Ask whether validations pass or fail
4. If validations *pass*, store the value that caused the failure along
   with some metadata and return false
5. Otherwise, return true

This difference in logic is achieved by having AllowValueMatcher
implement `does_not_match?` and then having DisallowValueMatcher use
this for its positive case and use `matches?` for its negative case.
It's easy to see because of this that `does_not_match?` is not the same
as `!matches?` and vice versa.

So a matcher that makes use of these submatchers internally needs to use
their opposite versions whenever that matcher is used in the negative
case. In other words, all of the matchers need a `does_not_match?` which
is like `matches?`, except that all of the logic is inverted, and in all
the cases in which AllowValueMatcher is used, DisallowValueMatcher needs
to be used.

Doing this ensures that when `failure_message` is called on
AllowValueMatcher or DisallowValueMatcher, step 4 in the list of steps
above stores a proper value that can then be referenced in the failure
message for the validation matcher itself.
2018-09-15 13:43:30 -03:00
Gui Vieira 9c1c55f533 Revert "Handle uuid columns in validate_absence_of"
This reverts commit 59523e3615.
2018-09-04 11:17:43 -03:00
Ryan Hansen 59523e3615 Handle uuid columns in validate_absence_of
There is not an explicit value set for uuid columns in the
validate_absence_of matcher.  The default string value is used which
will get set to nil instead when the type cast happens.  This causes the
matcher to fail when testing that the model does indeed validate for
absence of that attribute.
2018-09-03 16:33:53 -03:00
Teo Ljungberg 0c07bfb039 Use `BigDecimal()` over `BigDecimal.new`
As the latter is deprecated since: ruby/bigdecimal@5337373
2018-01-02 14:35:41 -02:00
Elliot Winkler afa6a7b666 Update RSpec test style across docs
Instead of using

    describe Foo do
      # ...
    end

use

    RSpec.describe Foo, type: :model do
      # ...
    end

instead. This is not exactly official, as the former style still works,
but the latter style is highly suggested in RSpec documentation and the
like, so this is what people are used to.

[ci skip]
2016-06-15 18:02:07 -06:00
Elliot Winkler 663c2f2c4d Remove most docs for ignoring_interference_by_writer
Since `ignoring_interference_by_writer` is on by default now, we don't
need to explicitly document it (unless someone wants to turn it off, but
that's unlikely).

[ci skip]
2016-01-10 23:19:47 -07:00
Elliot Winkler 1189934806 Add ignoring_interference_by_writer to all matchers
`allow_value` matcher is, of course, concerned with setting values on a
particular attribute on a particular record, and then checking that the
record is valid after doing so. That comes with a caveat: if the
attribute is overridden in such a way so that the same value going into
the attribute isn't the same value coming out of it, then `allow_value`
will balk -- it'll say, "I can't do that because that changes how I
work."

That's all well and good, but what the attribute intentionally changes
incoming values? ActiveRecord's typecasting behavior, for instance,
would trigger such an exception. What if the developer needs a way to
get around this? This is where `ignoring_interference_by_writer` comes
into play. You can tack it on to the end of the matcher, and you're free
to go on your way.

So, prior to this commit you could already apply it to `allow_value`,
but now in this commit it also works on any other matcher.

But, one little thing: sometimes using this qualifier isn't going to
work. Perhaps you or something else actually *is* overriding the
attribute to change incoming values in a specific way, and perhaps the
value that comes out makes the record fail validation, and there's
nothing you can do about it. So in this case, even if you're using
`ignoring_interference_by_writer`, we want to inform you about what the
attribute is doing -- what the input and output was. And so we do.
2016-01-05 00:58:16 -07:00
Elliot Winkler bf5030d34d Refactor absence matcher
This is part of a collection of commits that aim to improve failure
messages across the board, in order to make matchers easier to debug
when something goes wrong.

* Make the description of the matcher more readable.
* Fix or fill in tests involving failure messages and descriptions to
  match recent changes to ValidationMatcher.
2015-12-13 20:22:22 -07:00
Elliot Winkler 142366ef16 Refer to Minitest in docs over Test::Unit
Minitest has been used instead of Test::Unit for quite some time now,
let's get with the times.

[ci skip]
2015-09-30 13:18:23 -06:00
Elliot Winkler 9d9dc4e6b9 Tighten CouldNotSetAttributeError restriction
Why:

* Previously, `allow_value` would raise a CouldNotSetAttributeError
  if the value being set didn't match the value the attribute had after
  being set, but only if the attribute was being changed from nil to
  non-nil or non-nil to nil.
* It turns out it doesn't matter which value you're trying to set the
  attribute to -- if the attribute rejects that change it's confusing
  either way. (In fact, I was recently bit by a case in which I was
  trying to validate numericality of an attribute, where the writer
  method for that attribute was overridden to ensure that the attribute
  always stored a number and never contained non-number characters.
  This ended up making the numericality validation useless, of
  course -- but it caused confusion because the test acted in a way
  I didn't expect.)

To satisfy the above:

* `allow_value` now raises a CouldNotSetAttributeError if the attribute
  rejects the value being set in *any* way.
* However, add a `ignoring_interference_by_writer` qualifier so that
  it is possible to manually override this behavior.
* Fix tests that are failing now because of this new change:
  * Fix tests for allow_value matcher
  * Fix tests for numericality matcher
  * Remove tests for numericality matcher + integer column
    * An integer column will typecast any non-integer value to an
      integer.
    * Because of the typecasting, our tests for the numericality matcher
      against an integer column don't quite work, because we can't
      really test what happens when the attribute is set to a
      non-integer value. Now that `allow_value` is more strict, we're
      getting a CouldNotSetAttributeError when attempting to do so.
    * The tests mentioned were originally added to ensure that we are
      handling RangeErrors that ActiveRecord used to emit. This doesn't
      happen anymore, so the tests aren't necessary anymore either.
  * Fix tests for acceptance matcher
  * Fix tests for absence matcher
2015-09-27 14:56:59 -06:00
Mauro George eddbf3ea3c Add documentation to validate_absence_of on qualifier
[ci skip]
2015-03-28 22:33:43 -06:00
Alexey Blinov 165859247c validate_absence_of: cast `@attribute` to String
ActiveRecord.columns_hash returns Hash with String keys.
This is why `it { expect(offer).to validate_absence_of(:expired_at) }`
is not working.
2014-08-14 15:34:18 -04:00
Elliot Winkler c22d7c89e0 Extract examples in README to inline documentation 2014-06-20 16:41:27 -06:00
jmpage 2cdae242ca Add validates_absence_of matcher 2013-12-23 19:21:22 -07:00