Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adds support of explict argument for #rule_error? method #673

Merged
merged 2 commits into from
Nov 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
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
22 changes: 22 additions & 0 deletions docsite/source/rules.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,28 @@ FooContract.new.(foo: 'foo').errors.to_h
# { foo: ['failure added', 'failure added after checking'] }
```

Also it is possible for checking other rule error by passing explicit argument to `rule_error?` method

```ruby
class PersonContract < Dry::Validation::Contract
schema do
required(:email).filled(:string)
required(:name).filled(:string)
end

rule(:name) do
key.failure('name rule error')
end

rule(:email) do
key.failure('email rule error') if rule_error?(:name)
end
end

PersonContract.new.call(email: 'bar', name: 'foo').errors.to_h
# {name: ['name rule error'], email: ['email rule error']}
```

### Defining a rule for each element of an array

To check each element of an array you can simply use `Rule#each` shortcut. It works just like a normal rule, which means it's only applied when a value passed schema checks and supports setting failure messages in the standard way.
Expand Down
10 changes: 8 additions & 2 deletions lib/dry/validation/evaluator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -187,11 +187,17 @@ def schema_error?(path)

# Check if there are any errors on the current rule
#
# @param path [Symbol, String, Array] A Path-compatible spec
#
# @return [Boolean]
#
# @api public
def rule_error?
!key(path).empty?
def rule_error?(path = nil)
if path.nil?
!key(self.path).empty?
else
result.rule_error?(path)
end
end

# @api private
Expand Down
7 changes: 7 additions & 0 deletions lib/dry/validation/result.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@ def schema_error?(key)
schema_result.error?(key)
end

# Check if the rules includes an error for the provided key
#
# @api private
def rule_error?(key)
!schema_error?(key) && error?(key)
end

# Check if there's any error for the provided key
#
# This does not consider errors from the nested values
Expand Down
57 changes: 45 additions & 12 deletions spec/integration/contract/evaluator/errors_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,56 @@
end

describe "#rule_error?" do
let(:contract) do
Class.new(Dry::Validation::Contract) do
schema do
required(:foo).filled(:string)
end
context "without argument" do
let(:contract) do
Class.new(Dry::Validation::Contract) do
schema do
required(:foo).filled(:string)
end

rule(:foo) do
key.failure("failure added")
key.failure("failure added after checking") if rule_error?
rule(:foo) do
key.failure("failure added")
key.failure("failure added after checking") if rule_error?
end
end
end

it "checks for errors in current rule" do
expect(contract.new.(foo: "some@email.com").errors.to_h).to eql(
foo: ["failure added", "failure added after checking"]
)
end
end

it "checks for errors in current rule" do
expect(contract.new.(foo: "some@email.com").errors.to_h).to eql(
foo: ["failure added", "failure added after checking"]
)
context "with argument" do
let(:contract) do
Class.new(Dry::Validation::Contract) do
schema do
required(:name).filled(:string)
required(:email).filled(:string)
end

rule(:name) do
key.failure("expected")
end

rule(:email) do
key.failure("also expected") if rule_error?(:name)
end
end
end

it "checks for error in rule with name provided in argument" do
expect(contract.new.(name: "John", email: "some@email.com").errors.to_h).to eql(
{name: ["expected"], email: ["also expected"]}
)
end

it "does not evaluate if schema with provided key is falling down" do
expect(contract.new.(name: nil, email: "some@email.com").errors.to_h).to eql(
{name: ["must be a string"]}
)
end
end
end
end