adequate_errors 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.yardopts +1 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +37 -0
- data/README.md +72 -0
- data/Rakefile +25 -0
- data/adequate_errors.gemspec +27 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/adequate_errors/error.rb +129 -0
- data/lib/adequate_errors/errors.rb +95 -0
- data/lib/adequate_errors/interceptor.rb +54 -0
- data/lib/adequate_errors/locale/en.yml +33 -0
- data/lib/adequate_errors/version.rb +3 -0
- data/lib/adequate_errors.rb +6 -0
- metadata +114 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6292086a3e4cbd867447484ac68fbc5a68802a63
|
4
|
+
data.tar.gz: 862ebfd497a58618225482f232b05b08b31c09aa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5193cc15cf703b06b4fbe3e72b894ab25eb757b6defc60411cd5dd67f7518f2cd5aecb2ea3348505ce049d07d9413f1184b95cbfe4ba02c620099bf03081f3bf
|
7
|
+
data.tar.gz: 037de8bbfd563dfa981e5ab22ea581d51d8ba693717223674cb91bed5eec95d23812f75a3e671f57931c5ce2736eb6fb4c1528ab3977e30bc198f9054486179d
|
data/.gitignore
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--no-private
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
adequate_errors (0.1.0)
|
5
|
+
activemodel
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
activemodel (5.1.4)
|
11
|
+
activesupport (= 5.1.4)
|
12
|
+
activesupport (5.1.4)
|
13
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
14
|
+
i18n (~> 0.7)
|
15
|
+
minitest (~> 5.1)
|
16
|
+
tzinfo (~> 1.1)
|
17
|
+
builder (3.2.3)
|
18
|
+
concurrent-ruby (1.0.5)
|
19
|
+
i18n (0.9.1)
|
20
|
+
concurrent-ruby (~> 1.0)
|
21
|
+
minitest (5.10.3)
|
22
|
+
rake (10.5.0)
|
23
|
+
thread_safe (0.3.6)
|
24
|
+
tzinfo (1.2.4)
|
25
|
+
thread_safe (~> 0.1)
|
26
|
+
|
27
|
+
PLATFORMS
|
28
|
+
ruby
|
29
|
+
|
30
|
+
DEPENDENCIES
|
31
|
+
adequate_errors!
|
32
|
+
builder (~> 3.2.3)
|
33
|
+
bundler (~> 1.16.a)
|
34
|
+
rake (~> 10.0)
|
35
|
+
|
36
|
+
BUNDLED WITH
|
37
|
+
1.16.0.pre.3
|
data/README.md
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# AdequateErrors
|
2
|
+
|
3
|
+
Overcoming limitation of Rails model errors API:
|
4
|
+
|
5
|
+
* more expressive `where` query
|
6
|
+
* turn off message's attribute prefix.
|
7
|
+
* lazy evaluation of messages
|
8
|
+
|
9
|
+
## Introduction
|
10
|
+
|
11
|
+
Rails errors API is simple to use, but can be inadequate when coping with more complex requirements.
|
12
|
+
|
13
|
+
The existing API was originally a collection of message strings without much meta data, making it very restrictive. Though `details` hash was added later for storing meta information, many fundamental issues can not be fixed without altering the API and the architecture.
|
14
|
+
|
15
|
+
This gem redesigned the API, placing it in its own object, co-existing with existing Rails API. Thus nothing will break, allowing you to migrate the code one at a time.
|
16
|
+
|
17
|
+
## Quick start
|
18
|
+
|
19
|
+
To access the AdequateErrors object, call:
|
20
|
+
|
21
|
+
model.errors.adequate
|
22
|
+
|
23
|
+
From this object, many convenience methods are provided, for example this would return an array of AdequateErrors::Error objects, which matches the where query.
|
24
|
+
|
25
|
+
model.errors.adequate.where(attribute:'title', :type => :too_short, length: 5)
|
26
|
+
|
27
|
+
The following prints out each error's full message one by one:
|
28
|
+
|
29
|
+
model.errors.adequate.each {|error| puts error.message }
|
30
|
+
|
31
|
+
The following returns an array of all message strings:
|
32
|
+
|
33
|
+
model.errors.adequate.messages
|
34
|
+
|
35
|
+
For full documentation, please see http://www.rubydoc.info/github/lulalala/adequate_errors
|
36
|
+
|
37
|
+
## Key difference to Rails own errors API
|
38
|
+
|
39
|
+
Errors are stored as Ruby objects instead of message strings, this makes more fine-grained query possible.
|
40
|
+
|
41
|
+
Error messages are evaluated lazily, which means it can be rendered in a different locale at view rendering time.
|
42
|
+
|
43
|
+
The messages in the locale file are looked up in its own `adequate_errors` namespace, for example:
|
44
|
+
|
45
|
+
en:
|
46
|
+
adequate_errors:
|
47
|
+
messages:
|
48
|
+
invalid: "%{attribute} is invalid"
|
49
|
+
|
50
|
+
Note that each message by default has the `attribute` prefix. This allow easy removal of attribute prefix by overriding each message in the locale file. You no longer need to attach errors to `:base` for that purpose. This allows prefix to be changed per language.
|
51
|
+
|
52
|
+
Calls to Rails' API are synced to AdequateErrors object, but not the reverse.
|
53
|
+
|
54
|
+
## Migration Note
|
55
|
+
|
56
|
+
Deprecated methods such as `[]=`, `get` and `set` are not supported, therefore calling those methods will not sync to AdequateErrors.
|
57
|
+
|
58
|
+
The gem is developed from ActiveModel 5.1, but it should work with earlier versions.
|
59
|
+
|
60
|
+
## We want to hear your issues too
|
61
|
+
|
62
|
+
If you also have issues with exsting API, share it by filing that issue here.
|
63
|
+
|
64
|
+
We collect use cases in issues and analyze the problem in wiki (publicly editable):
|
65
|
+
|
66
|
+
[So come to our wiki, see what's going on, and join us!](https://github.com/lulalala/adequate_errors/wiki)
|
67
|
+
|
68
|
+
---
|
69
|
+
|
70
|
+
This repo was called Rails Error API Redesign Initiative.
|
71
|
+
This is a fan project and is not affiliated to Rails Core team,
|
72
|
+
but my wish is that one day this can be adapted into Rails too.
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rake/testtask"
|
3
|
+
|
4
|
+
dir = File.dirname(__FILE__)
|
5
|
+
|
6
|
+
task default: :test
|
7
|
+
|
8
|
+
task :package
|
9
|
+
|
10
|
+
Rake::TestTask.new do |t|
|
11
|
+
t.libs << "test"
|
12
|
+
t.test_files = Dir.glob("#{dir}/test/cases/**/*_test.rb")
|
13
|
+
t.warning = true
|
14
|
+
t.verbose = true
|
15
|
+
t.ruby_opts = ["--dev"] if defined?(JRUBY_VERSION)
|
16
|
+
end
|
17
|
+
|
18
|
+
namespace :test do
|
19
|
+
task :isolated do
|
20
|
+
Dir.glob("#{dir}/test/**/*_test.rb").all? do |file|
|
21
|
+
sh(Gem.ruby, "-w", "-I#{dir}/lib", "-I#{dir}/test", file)
|
22
|
+
end || raise("Failures")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "adequate_errors/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "adequate_errors"
|
8
|
+
spec.version = AdequateErrors::VERSION
|
9
|
+
spec.authors = ["lulalala"]
|
10
|
+
spec.email = ["mark@goodlife.tw"]
|
11
|
+
|
12
|
+
spec.summary = %q{Object-Oriented ActiveModel errors interface}
|
13
|
+
spec.homepage = "https://github.com/lulalala/adequate_errors/"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
16
|
+
f.match(%r{^(test|spec|features)/})
|
17
|
+
end
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_dependency "activemodel"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.16.a"
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
spec.add_development_dependency "builder", "~> 3.2.3"
|
27
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "adequate_errors"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
module AdequateErrors
|
2
|
+
# Represents one single error
|
3
|
+
# @!attribute [r] base
|
4
|
+
# @return [ActiveModel::Base] the object which the error belongs to
|
5
|
+
# @!attribute [r] attribute
|
6
|
+
# @return [Symbol] attribute of the object which the error belongs to
|
7
|
+
# @!attribute [r] type
|
8
|
+
# @return [Symbol] error's type
|
9
|
+
# @!attribute [r] options
|
10
|
+
# @return [Hash] additional options
|
11
|
+
class Error
|
12
|
+
def initialize(base, attribute, type, options = {})
|
13
|
+
@base = base
|
14
|
+
@attribute = attribute
|
15
|
+
@type = type
|
16
|
+
@options = options
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :base, :attribute, :type, :options
|
20
|
+
|
21
|
+
# Full message of the error.
|
22
|
+
#
|
23
|
+
# === Key differences to Rails vanilla errors
|
24
|
+
#
|
25
|
+
# ==== 1. Flexible positioning of attribute name interpolation
|
26
|
+
#
|
27
|
+
# In Rails, errors' full messages are always prefixed with attribute name,
|
28
|
+
# and if prefix is not wanted, developer often adds error to the `base' attribute instead.
|
29
|
+
# This can be unreasonable in different languages or special business requirements.
|
30
|
+
#
|
31
|
+
# AdequateErrors leaves the attribute placement to the developer.
|
32
|
+
# For each error message in the locale file, the %{attribute} indicates placement of the attribute.
|
33
|
+
# The same error can have prefix in English, and be prefix-less in Russian.
|
34
|
+
# If no prefix is needed, one should update the locale file accordingly,
|
35
|
+
#
|
36
|
+
# ==== 2. Message evaluated lazily
|
37
|
+
#
|
38
|
+
# In Rails, error message is evaluated during the `add` call.
|
39
|
+
# AdequateErrors evaluates message lazily at `message` call instead,
|
40
|
+
# so one can change message locale after model has been validated.
|
41
|
+
#
|
42
|
+
# === Order of I18n lookup:
|
43
|
+
#
|
44
|
+
# Error messages are first looked up in <tt>activemodel.adequate_errors.models.MODEL.attributes.ATTRIBUTE.MESSAGE</tt>,
|
45
|
+
# if it's not there, it's looked up in <tt>activemodel.adequate_errors.models.MODEL.MESSAGE</tt> and if
|
46
|
+
# that is not there also, it returns the translation of the default message
|
47
|
+
# (e.g. <tt>activemodel.errors.messages.MESSAGE</tt>). The translated model
|
48
|
+
# name, translated attribute name and the value are available for
|
49
|
+
# interpolation.
|
50
|
+
#
|
51
|
+
# When using inheritance in your models, it will check all the inherited
|
52
|
+
# models too, but only if the model itself hasn't been found. Say you have
|
53
|
+
# <tt>class Admin < User; end</tt> and you wanted the translation for
|
54
|
+
# the <tt>:blank</tt> error message for the <tt>title</tt> attribute,
|
55
|
+
# it looks for these translations:
|
56
|
+
#
|
57
|
+
# * <tt>activemodel.adequate_errors.models.admin.attributes.title.blank</tt>
|
58
|
+
# * <tt>activemodel.adequate_errors.models.admin.blank</tt>
|
59
|
+
# * <tt>activemodel.adequate_errors.models.user.attributes.title.blank</tt>
|
60
|
+
# * <tt>activemodel.adequate_errors.models.user.blank</tt>
|
61
|
+
# * any default you provided through the +options+ hash (in the <tt>activemodel.adequate_errors</tt> scope)
|
62
|
+
# * <tt>activemodel.adequate_errors.messages.blank</tt>
|
63
|
+
# * <tt>adequate_errors.attributes.title.blank</tt>
|
64
|
+
# * <tt>adequate_errors.messages.blank</tt>
|
65
|
+
def message
|
66
|
+
if @options[:message].is_a?(Symbol)
|
67
|
+
type = @options.delete(:message)
|
68
|
+
else
|
69
|
+
type = @type
|
70
|
+
end
|
71
|
+
|
72
|
+
if @base.class.respond_to?(:i18n_scope)
|
73
|
+
i18n_scope = @base.class.i18n_scope.to_s
|
74
|
+
defaults = @base.class.lookup_ancestors.flat_map do |klass|
|
75
|
+
[ :"#{i18n_scope}.adequate_errors.models.#{klass.model_name.i18n_key}.attributes.#{attribute}.#{type}",
|
76
|
+
:"#{i18n_scope}.adequate_errors.models.#{klass.model_name.i18n_key}.#{type}" ]
|
77
|
+
end
|
78
|
+
defaults << :"#{i18n_scope}.adequate_errors.messages.#{type}"
|
79
|
+
else
|
80
|
+
defaults = []
|
81
|
+
end
|
82
|
+
|
83
|
+
defaults << :"adequate_errors.attributes.#{attribute}.#{type}"
|
84
|
+
defaults << :"adequate_errors.messages.#{type}"
|
85
|
+
|
86
|
+
key = defaults.shift
|
87
|
+
defaults = @options.delete(:message) if @options[:message]
|
88
|
+
value = (attribute != :base ? @base.send(:read_attribute_for_validation, attribute) : nil)
|
89
|
+
|
90
|
+
i18n_options = {
|
91
|
+
default: defaults,
|
92
|
+
model: @base.model_name.human,
|
93
|
+
attribute: humanized_attribute,
|
94
|
+
value: value,
|
95
|
+
object: @base
|
96
|
+
}.merge!(@options)
|
97
|
+
|
98
|
+
I18n.translate(key, i18n_options)
|
99
|
+
end
|
100
|
+
|
101
|
+
# @param (see Errors#where)
|
102
|
+
# @return [Boolean] whether error matches the params
|
103
|
+
def match?(params)
|
104
|
+
if params.key?(:attribute) && @attribute != params[:attribute]
|
105
|
+
return false
|
106
|
+
end
|
107
|
+
|
108
|
+
if params.key?(:type) && @type != params[:type]
|
109
|
+
return false
|
110
|
+
end
|
111
|
+
|
112
|
+
(params.keys - [:attribute, :type]).each do |key|
|
113
|
+
if @options[key] != params[key]
|
114
|
+
return false
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
true
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
def humanized_attribute
|
124
|
+
default = @attribute.to_s.tr(".", "_").humanize
|
125
|
+
@base.class.human_attribute_name(@attribute, default: default)
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'active_model/errors'
|
2
|
+
require 'forwardable'
|
3
|
+
require 'adequate_errors/error'
|
4
|
+
|
5
|
+
module AdequateErrors
|
6
|
+
# Collection of {Error} objects.
|
7
|
+
# Provides convenience methods to access these errors.
|
8
|
+
# It is accessed via +model.errors.adequate+
|
9
|
+
class Errors
|
10
|
+
include Enumerable
|
11
|
+
|
12
|
+
extend Forwardable
|
13
|
+
def_delegators :@errors, :each, :size, :clear, :blank?, :empty?, *Enumerable.instance_methods(false)
|
14
|
+
|
15
|
+
# @param base [ActiveModel::Base]
|
16
|
+
def initialize(base)
|
17
|
+
@base = base
|
18
|
+
@errors = []
|
19
|
+
end
|
20
|
+
|
21
|
+
# Delete errors of attribute
|
22
|
+
def delete(attribute)
|
23
|
+
@errors.delete_if do |error|
|
24
|
+
error.attribute == attribute
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Adds error.
|
29
|
+
# More than one error can be added to the same `attribute`.
|
30
|
+
# If no `type` is supplied, `:invalid` is assumed.
|
31
|
+
#
|
32
|
+
# @param attribute [Symbol] attribute that the error belongs to
|
33
|
+
# @param type [Symbol] error's type, defaults to `:invalid`.
|
34
|
+
# As convenience, if type is String/Proc/Lambda,
|
35
|
+
# it will be moved to `options[:message]`,
|
36
|
+
# and type itself will be changed to the default `:invalid`.
|
37
|
+
# @param options [Hash] extra conditions such as interpolated value
|
38
|
+
def add(attribute, type = :invalid, options = {})
|
39
|
+
|
40
|
+
if !type.is_a? Symbol
|
41
|
+
options[:message] = type
|
42
|
+
type = :invalid
|
43
|
+
end
|
44
|
+
|
45
|
+
@errors.append(::AdequateErrors::Error.new(@base, attribute, type, options))
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [Array(String)] all error messages
|
49
|
+
def messages
|
50
|
+
@errors.map(&:message)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Convenience method to fetch error messages filtered by where condition.
|
54
|
+
# @param params [Hash] filter condition, see {#where} for details.
|
55
|
+
# @return [Array(String)] error messages
|
56
|
+
def messages_for(params)
|
57
|
+
where(params).map(&:message)
|
58
|
+
end
|
59
|
+
|
60
|
+
# @param params [Hash]
|
61
|
+
# filter condition
|
62
|
+
# The most common keys are +:attribute+ and +:type+,
|
63
|
+
# but other custom keys given during {#add} can also be used.
|
64
|
+
# If params is empty, all errors are returned.
|
65
|
+
# @option params [Symbol] :attribute Filtering on attribute the error belongs to
|
66
|
+
# @option params [Symbol] :type Filter on type of error
|
67
|
+
#
|
68
|
+
# @return [Array(AdequateErrors::Error)] matching {Error}.
|
69
|
+
def where(params)
|
70
|
+
return @errors.dup if params.blank?
|
71
|
+
|
72
|
+
@errors.select {|error|
|
73
|
+
error.match?(params)
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
# @return [Boolean] whether the given attribute contains error.
|
78
|
+
def include?(attribute)
|
79
|
+
@errors.any?{|error| error.attribute == attribute }
|
80
|
+
end
|
81
|
+
|
82
|
+
# @return [Hash] attributes with their error messages
|
83
|
+
def to_hash
|
84
|
+
hash = {}
|
85
|
+
@errors.each do |error|
|
86
|
+
if hash.has_key?(error.attribute)
|
87
|
+
hash[error.attribute] << error.message
|
88
|
+
else
|
89
|
+
hash[error.attribute] = [error.message]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
hash
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "active_model/errors"
|
2
|
+
require "adequate_errors/errors"
|
3
|
+
|
4
|
+
module AdequateErrors
|
5
|
+
# Wraps around Rails' errors object, intercepting its state changes
|
6
|
+
# in order to update AdequateErrors' errors object.
|
7
|
+
module Interceptor
|
8
|
+
def initialize(base)
|
9
|
+
rails_errors = super
|
10
|
+
@adequate_errors = ::AdequateErrors::Errors.new(base)
|
11
|
+
rails_errors
|
12
|
+
end
|
13
|
+
|
14
|
+
def clear
|
15
|
+
super
|
16
|
+
@adequate_errors.clear
|
17
|
+
end
|
18
|
+
|
19
|
+
def delete(key)
|
20
|
+
super
|
21
|
+
@adequate_errors.delete(key)
|
22
|
+
end
|
23
|
+
|
24
|
+
def add(attribute, message = :invalid, options = {})
|
25
|
+
adequate_options = options.dup
|
26
|
+
|
27
|
+
messages = super
|
28
|
+
|
29
|
+
if options.has_key?(:message) && !options[:message].is_a?(Symbol)
|
30
|
+
adequate_options[:message] = full_message(attribute, messages.last)
|
31
|
+
end
|
32
|
+
|
33
|
+
adequate_message = if !message.is_a?(Symbol)
|
34
|
+
full_message(attribute, messages.last)
|
35
|
+
else
|
36
|
+
message
|
37
|
+
end
|
38
|
+
|
39
|
+
@adequate_errors.add(attribute, adequate_message, adequate_options)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Accessor
|
43
|
+
def adequate
|
44
|
+
@adequate_errors
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# @private
|
50
|
+
module ActiveModel
|
51
|
+
class Errors
|
52
|
+
prepend AdequateErrors::Interceptor
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
en:
|
2
|
+
adequate_errors:
|
3
|
+
# The values :model, :attribute and :value are always available for interpolation
|
4
|
+
# The value :count is available when applicable. Can be used for pluralization.
|
5
|
+
messages:
|
6
|
+
model_invalid: "Validation failed: %{errors}"
|
7
|
+
inclusion: "%{attribute} is not included in the list"
|
8
|
+
exclusion: "%{attribute} is reserved"
|
9
|
+
invalid: "%{attribute} is invalid"
|
10
|
+
confirmation: "%{attribute} doesn't match %{attribute}"
|
11
|
+
accepted: "%{attribute} must be accepted"
|
12
|
+
empty: "%{attribute} can't be empty"
|
13
|
+
blank: "%{attribute} can't be blank"
|
14
|
+
present: "%{attribute} must be blank"
|
15
|
+
too_long:
|
16
|
+
one: "%{attribute} is too long (maximum is 1 character)"
|
17
|
+
other: "%{attribute} is too long (maximum is %{count} characters)"
|
18
|
+
too_short:
|
19
|
+
one: "%{attribute} is too short (minimum is 1 character)"
|
20
|
+
other: "%{attribute} is too short (minimum is %{count} characters)"
|
21
|
+
wrong_length:
|
22
|
+
one: "%{attribute} is the wrong length (should be 1 character)"
|
23
|
+
other: "%{attribute} is the wrong length (should be %{count} characters)"
|
24
|
+
not_a_number: "%{attribute} is not a number"
|
25
|
+
not_an_integer: "%{attribute} must be an integer"
|
26
|
+
greater_than: "%{attribute} must be greater than %{count}"
|
27
|
+
greater_than_or_equal_to: "%{attribute} must be greater than or equal to %{count}"
|
28
|
+
equal_to: "%{attribute} must be equal to %{count}"
|
29
|
+
less_than: "%{attribute} must be less than %{count}"
|
30
|
+
less_than_or_equal_to: "%{attribute} must be less than or equal to %{count}"
|
31
|
+
other_than: "%{attribute} must be other than %{count}"
|
32
|
+
odd: "%{attribute} must be odd"
|
33
|
+
even: "%{attribute} must be even"
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: adequate_errors
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- lulalala
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-11-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activemodel
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.16.a
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.16.a
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: builder
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 3.2.3
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 3.2.3
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- mark@goodlife.tw
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".yardopts"
|
78
|
+
- Gemfile
|
79
|
+
- Gemfile.lock
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- adequate_errors.gemspec
|
83
|
+
- bin/console
|
84
|
+
- bin/setup
|
85
|
+
- lib/adequate_errors.rb
|
86
|
+
- lib/adequate_errors/error.rb
|
87
|
+
- lib/adequate_errors/errors.rb
|
88
|
+
- lib/adequate_errors/interceptor.rb
|
89
|
+
- lib/adequate_errors/locale/en.yml
|
90
|
+
- lib/adequate_errors/version.rb
|
91
|
+
homepage: https://github.com/lulalala/adequate_errors/
|
92
|
+
licenses: []
|
93
|
+
metadata: {}
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options: []
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
requirements: []
|
109
|
+
rubyforge_project:
|
110
|
+
rubygems_version: 2.6.13
|
111
|
+
signing_key:
|
112
|
+
specification_version: 4
|
113
|
+
summary: Object-Oriented ActiveModel errors interface
|
114
|
+
test_files: []
|