Skip to content

Commit

Permalink
Merge pull request #82 from hlegius/81-blank-values-with-size-attribu…
Browse files Browse the repository at this point in the history
…te-fails

Added blank_value? to size predicate
  • Loading branch information
jodosha committed Nov 26, 2015
2 parents f0b9020 + c4bb8b7 commit e6b5817
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 2 deletions.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,34 @@ person.email # => "me@example.org"
person.age # => raises NoMethodError because `:age` wasn't defined as attribute.
```

#### Blank Values

The framework will treat as valid any blank attributes, __without__ `presence`, for both `format` and `size` predicates.

```ruby
require 'lotus/validations'

class Person
include Lotus::Validations

attribute :name, type: String, size: 5..45
attribute :email, type: String, size: 20..80, format: /@/
attribute :skills, type: Array, size: 1..3
attribute :keys, type: Hash, size: 1..3
end

Person.new.valid? # < true
Person.new(name: '').valid? # < true
Person.new(skills: '').valid? # < true
Person.new(skills: ['ruby', 'lotus']).valid? # < true

Person.new(skills: []).valid? # < false
Person.new(keys: {}).valid? # < false
Person.new(keys: {a: :b}, skills: []).valid? # < false
```

If you want to _disable_ this behaviour, please, refer to [presence](https://github.com/lotus/validations#presence).

### Validations

If you prefer Lotus::Validations to **only define validations**, but **not attributes**,
Expand Down
4 changes: 4 additions & 0 deletions lib/lotus/validations/attribute.rb
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ def confirmation
#
# If the quantity is a Range, the size of the value MUST be included.
#
# If the attribute's value is blank, the size will not be considered
#
# The value is an object which implements `#size`.
#
# @raise [ArgumentError] if the defined quantity isn't a Numeric or a
Expand All @@ -181,6 +183,8 @@ def confirmation
# @since 0.2.0
# @api private
def size
return if blank_value?

_validate(__method__) do |validator|
case validator
when Numeric, ->(v) { v.respond_to?(:to_int) }
Expand Down
10 changes: 10 additions & 0 deletions lib/lotus/validations/blank_value_checker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,18 @@ def _blank_string?
# @since 0.2.2
# @api private
def _empty_value?
return false if _enumerable?
(@value.respond_to?(:empty?) and @value.empty?)
end

# Collectable classes should not be considered as blank value
# even if it's responds _true_ to its own `empty?` method.
#
# @since x.x.x
# @api private
def _enumerable?
@value.respond_to?(:each)
end
end
end
end
13 changes: 13 additions & 0 deletions test/composed_validation_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,19 @@

validator.valid?.must_equal true
end

# Bug https://github.com/lotus/validations/issues/81
it 'is valid if included attributes are blank and does not define presence constraint' do
validator = ComposedValidationsWithoutPresenceTest.new(email: '', name: '')

validator.valid?.must_equal true
end

it 'is not valid if included attributes are invalid' do
validator = ComposedValidationsWithoutPresenceTest.new(email: 'fo', name: 'o')

validator.valid?.must_equal false
end
end

describe 'nested composed validations' do
Expand Down
16 changes: 14 additions & 2 deletions test/fixtures.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ class PresenceValidatorTest
class FormatValidatorTest
include Lotus::Validations

attribute :name, format: /\A[a-zA-Z]+\z/
attribute :age, type: String, format: /\A[0-9]+\z/
attribute :name, format: /\A[a-zA-Z]+\z/
attribute :age, type: String, format: /\A[0-9]+\z/
end

class InclusionValidatorTest
Expand Down Expand Up @@ -185,6 +185,12 @@ module EmailValidations
attribute :email, presence: true, format: /@/
end

module EmailValidationsWithoutPresence
include Lotus::Validations

attribute :email, format: /@/
end

module CommonValidations
include EmailValidations
end
Expand All @@ -193,6 +199,12 @@ class ComposedValidationsTest
include EmailValidations
end

class ComposedValidationsWithoutPresenceTest
include EmailValidationsWithoutPresence

attribute :name, size: 8..50
end

module PasswordValidations
include Lotus::Validations

Expand Down
16 changes: 16 additions & 0 deletions test/size_validation_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,22 @@
end
end

# Bug https://github.com/lotus/validations/issues/81
it 'is valid if attribute is defined as blank' do
validator = SizeValidatorTest.new(password: 'foobarbazqux', ssn: '')

validator.valid?.must_equal true
validator.errors.must_be_empty
end

it 'is not valid if attribute is an empty collection' do
validator = SizeValidatorTest.new(password: 'quxbazbarfoo', ssn: [])

validator.valid?.must_equal false
errors = validator.errors.for(:ssn)
errors.must_include Lotus::Validations::Error.new(:ssn, :size, 11, [])
end

it "raises an error when the validator can't be coerced into an integer" do
-> { SizeValidatorErrorTest.new(password: 'secret').valid? }.must_raise ArgumentError
end
Expand Down

0 comments on commit e6b5817

Please sign in to comment.