Skip to content

Commit

Permalink
Merge pull request #662 from stind/fix-full-error-messages
Browse files Browse the repository at this point in the history
Fix full error messages

[changelog]

fixed: "Full messages work correctly with rule failures now (issue #661 fixed via #662) (@stind)"
  • Loading branch information
solnic committed Aug 5, 2020
2 parents bb188ee + 9962922 commit 57a7a53
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 14 deletions.
36 changes: 22 additions & 14 deletions lib/dry/validation/messages/resolver.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# frozen_string_literal: true

require "dry/validation/message"
require "dry/schema/message_compiler"

module Dry
module Validation
module Messages
FULL_MESSAGE_WHITESPACE = Dry::Schema::MessageCompiler::FULL_MESSAGE_WHITESPACE

# Resolve translated messages from failure arguments
#
# @api public
Expand Down Expand Up @@ -33,7 +36,7 @@ def call(message:, tokens:, path:, meta: EMPTY_HASH)
when Symbol
Message[->(**opts) { message(message, path: path, tokens: tokens, **opts) }, path, meta]
when String
Message[->(**opts) { [message_text(message, path, **opts), meta] }, path, meta]
Message[->(**opts) { [message_text(message, path: path, **opts), meta] }, path, meta]
when Hash
meta = message.dup
text = meta.delete(:text) { |key|
Expand All @@ -51,18 +54,6 @@ def call(message:, tokens:, path:, meta: EMPTY_HASH)
end
alias_method :[], :call

# Resolve a message
#
# @return String
#
# @api public
def message_text(message, path, locale: nil, full: false, **opts)
keys = path.to_a.compact
msg_opts = EMPTY_HASH.merge(path: keys, locale: locale || messages.default_locale)

full ? "#{messages.rule(keys.last, msg_opts) || keys.last} #{message}" : message
end

# Resolve a message
#
# @return [String]
Expand Down Expand Up @@ -90,12 +81,29 @@ def message(rule, tokens: EMPTY_HASH, locale: nil, full: false, path:)
parsed_tokens = parse_tokens(tokens)
text = template.(template.data(parsed_tokens))

[full ? "#{messages.rule(keys.last, msg_opts)} #{text}" : text, meta]
[message_text(text, path: path, locale: locale, full: full), meta]
end
# rubocop:enable Metrics/AbcSize

private

def message_text(text, path:, locale: nil, full: false)
return text unless full

key = key_text(path: path, locale: locale)

[key, text].compact.join(FULL_MESSAGE_WHITESPACE[locale])
end

def key_text(path:, locale: nil)
locale ||= messages.default_locale

keys = path.to_a.compact
msg_opts = {path: keys, locale: locale}

messages.rule(keys.last, msg_opts) || keys.last
end

def parse_tokens(tokens)
Hash[
tokens.map do |key, token|
Expand Down
1 change: 1 addition & 0 deletions spec/fixtures/messages/errors.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ en:
rules:
email: "E-mail"
errors:
format: "has invalid format"
rules:
not_weekend: "this only works on weekends"
email:
Expand Down
8 changes: 8 additions & 0 deletions spec/fixtures/messages/errors.ja.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
ja:
dry_validation:
rules:
email: "Eメール"
errors:
rules:
email:
filled?: "は必須入力です"
3 changes: 3 additions & 0 deletions spec/fixtures/messages/errors.pl.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
pl:
dry_validation:
rules:
email: "E-mail"
errors:
format: "ma nieprawidłowy format"
rules:
not_weekend: "to działa tylko w weekendy"
email:
Expand Down
55 changes: 55 additions & 0 deletions spec/integration/messages/resolver_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,28 @@
Message template for :not_here under "email" was not found
STR
end

context "with full: true option" do
it "returns full message text for base rule" do
expect(resolver.message(:not_weekend, path: [nil], locale: locale, full: true))
.to eql(["this only works on weekends", {}])
end

it "returns message text with translated key name" do
expect(resolver.message(:format, path: [:email], locale: locale, full: true))
.to eql(["E-mail has invalid format", {}])
end

it "supports untranslated key names" do
expect(resolver.message(:format, path: [:non_translated_key], locale: locale, full: true))
.to eql(["non_translated_key has invalid format", {}])
end

it "returns full message text for nested rule" do
expect(resolver.message(:invalid, path: %i[address street], locale: locale, full: true))
.to eql(["street doesn't look good", {}])
end
end
end

context ":pl" do
Expand All @@ -70,6 +92,39 @@
expect(resolver.message(:invalid, path: %i[address street], locale: locale))
.to eql(["nie wygląda dobrze", {}])
end

context "with full: true option" do
it "returns full message text for base rule" do
expect(resolver.message(:not_weekend, path: [nil], locale: locale, full: true))
.to eql(["to działa tylko w weekendy", {}])
end

it "returns message text with translated key name" do
expect(resolver.message(:format, path: [:email], locale: locale, full: true))
.to eql(["E-mail ma nieprawidłowy format", {}])
end

it "supports untranslated key names" do
expect(resolver.message(:format, path: [:non_translated_key], locale: locale, full: true))
.to eql(["non_translated_key ma nieprawidłowy format", {}])
end

it "returns full message text for nested rule" do
expect(resolver.message(:invalid, path: %i[address street], locale: locale, full: true))
.to eql(["street nie wygląda dobrze", {}])
end
end
end

context ":ja" do
let(:locale) { :ja }

context "with full: true option" do
it "returns full message text with defined whitespace character" do
expect(resolver.message(:filled?, path: [:email], locale: locale, full: true))
.to eql(["Eメールは必須入力です", {}])
end
end
end
end

Expand Down

0 comments on commit 57a7a53

Please sign in to comment.