• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ruby-grape / grape / 21997725638

13 Feb 2026 06:13PM UTC coverage: 96.849% (-0.06%) from 96.906%
21997725638

Pull #2657

github

ericproulx
Instantiate validators at definition time

  - Store validator instances in ParamsScope/ContractScope and have
    Endpoint#run_validators read them directly
  - Remove ValidatorFactory indirection and eagerly compute validator
    messages/options in constructors
  - Extract Grape::Util::Translation module shared by Exceptions::Base
    and Validators::Base for I18n translate with fallback locale
  - Support Hash messages in translate_message for deferred translation
    with interpolation parameters (e.g. { key: :length, min: 2 })
  - Normalize Grape::Exceptions::Validation params handling and refactor
    validator specs to define routes per example group
  - Drop test-prof dependency and its spec config

Co-authored-by: Cursor <cursoragent@cursor.com>
Pull Request #2657: Instantiate validators at definition time

1057 of 1142 branches covered (92.56%)

Branch coverage included in aggregate %.

168 of 170 new or added lines in 21 files covered. (98.82%)

1 existing line in 1 file now uncovered.

3307 of 3364 relevant lines covered (98.31%)

37590.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.83
/lib/grape/exceptions/validation_errors.rb
1
# frozen_string_literal: true
2

3
module Grape
37✔
4
  module Exceptions
37✔
5
    class ValidationErrors < Base
37✔
6
      ERRORS_FORMAT_KEY = 'grape.errors.format'
37✔
7
      DEFAULT_ERRORS_FORMAT = '%<attributes>s %<message>s'
37✔
8

9
      include Enumerable
37✔
10

11
      attr_reader :errors
37✔
12

13
      def initialize(errors: [], headers: {})
37✔
14
        @errors = errors.group_by(&:params)
11,110✔
15
        super(message: full_messages.join(', '), status: 400, headers: headers)
11,110✔
16
      end
17

18
      def each
37✔
19
        errors.each_pair do |attribute, errors|
11,302✔
20
          errors.each do |error|
13,832✔
21
            yield attribute, error
14,664✔
22
          end
23
        end
24
      end
25

26
      def as_json(**_opts)
37✔
27
        errors.map do |k, v|
64✔
28
          {
29
            params: k,
64✔
30
            messages: v.map(&:to_s)
31
          }
32
        end
33
      end
34

35
      def to_json(*_opts)
37✔
UNCOV
36
        as_json.to_json
×
37
      end
38

39
      def full_messages
37✔
40
        messages = map do |attributes, error|
11,174✔
41
          I18n.t(
14,536✔
42
            ERRORS_FORMAT_KEY,
43
            default: DEFAULT_ERRORS_FORMAT,
44
            attributes: translate_attributes(attributes),
45
            message: error.message
46
          )
47
        end
48
        messages.uniq!
11,174✔
49
        messages
11,174✔
50
      end
51
    end
52
  end
53
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc