active_model-errors_details 1.0.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 +14 -0
- data/.travis.yml +7 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +64 -0
- data/Rakefile +9 -0
- data/active_model-errors_details.gemspec +25 -0
- data/lib/active_model/errors_details/version.rb +5 -0
- data/lib/active_model/errors_details.rb +61 -0
- data/test/minitest_helper.rb +4 -0
- data/test/test_errors_details.rb +93 -0
- metadata +106 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 73354179ee7bcde3fc9788714870cd06981c32ec
|
4
|
+
data.tar.gz: 21b27aa4a7b13a411c780fd2b7af3316686a5843
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0ff23f9ae379f31dc5728421dd8caa798067b95719cda49182f1fc3a261d184d137bc13873371eb6365f3b6af285c58a51464fa31fc8a922c96754ebdf4380bd
|
7
|
+
data.tar.gz: 5014f82de304d637c761b7033f0d55b471743cba24e57807995193ed3a09c7040bf1346eb88d2ae40194bfd16ef6b64528cd8824bc30657338bb3875a62ee122
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Wojciech Wnętrzak
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# ActiveModel::Errors#details
|
2
|
+
|
3
|
+
Feature backported from Rails 5.0 to use with Rails 4.x apps.
|
4
|
+
|
5
|
+
Background: https://github.com/rails/rails/pull/18322
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
```
|
10
|
+
gem install "active_model-errors_details"
|
11
|
+
```
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
To check what validator type was used on invalid attribute, you can use
|
16
|
+
`errors.details[:attribute]`. It returns array of hashes where under `:error`
|
17
|
+
key you will find symbol of used validator.
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
class Person < ActiveRecord::Base
|
21
|
+
validates :name, presence: true
|
22
|
+
end
|
23
|
+
|
24
|
+
person = Person.new
|
25
|
+
person.valid?
|
26
|
+
person.errors.details[:name]
|
27
|
+
# => [{error: :blank}]
|
28
|
+
```
|
29
|
+
|
30
|
+
You can add validator type to details hash when using `errors.add` method.
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
class Person < ActiveRecord::Base
|
34
|
+
def a_method_used_for_validation_purposes
|
35
|
+
errors.add(:name, :invalid_characters)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
person = Person.create(name: "!@#")
|
40
|
+
|
41
|
+
person.errors.details[:name]
|
42
|
+
# => [{error: :invalid_characters}]
|
43
|
+
```
|
44
|
+
|
45
|
+
To improve error details to contain not allowed characters set, you can
|
46
|
+
pass additional options to `errors.add` method.
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
class Person < ActiveRecord::Base
|
50
|
+
def a_method_used_for_validation_purposes
|
51
|
+
errors.add(:name, :invalid_characters, not_allowed: "!@#%*()_-+=")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
person = Person.create(name: "John!")
|
56
|
+
|
57
|
+
person.errors.details[:name]
|
58
|
+
# => [{error: :invalid_characters, not_allowed: "!@#%*()_-+="}]
|
59
|
+
```
|
60
|
+
|
61
|
+
All built in Rails validators populate details hash with corresponding
|
62
|
+
validator types.
|
63
|
+
|
64
|
+
[](https://travis-ci.org/cowbell/active_model-email_confirmation)
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'active_model/errors_details/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "active_model-errors_details"
|
8
|
+
spec.version = ActiveModel::ErrorsDetails::VERSION
|
9
|
+
spec.authors = ["Wojciech Wnętrzak"]
|
10
|
+
spec.email = ["w.wnetrzak@gmail.com"]
|
11
|
+
spec.summary = %q{Adds ActiveModel::Errors#details to return type of used validator}
|
12
|
+
spec.description = %q{Backported from Rails 5.0 to use with 4.x versions}
|
13
|
+
spec.homepage = "https://github.com/cowbell/active_model-errors_details"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "activemodel", ">= 4.0", "< 5.0.0.alpha"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "active_model/errors_details/version"
|
2
|
+
require "active_model/errors"
|
3
|
+
|
4
|
+
module ActiveModel
|
5
|
+
module ErrorsDetails
|
6
|
+
MESSAGE_OPTIONS = [:message]
|
7
|
+
|
8
|
+
def self.included(base)
|
9
|
+
base.class_eval do
|
10
|
+
alias_method :initialize_without_details, :initialize
|
11
|
+
alias_method :initialize, :initialize_with_details
|
12
|
+
|
13
|
+
# alias_method :initialize_dup_without_details, :initialize_dup
|
14
|
+
# alias_method :initialize_dup, :initialize_dup_with_details
|
15
|
+
|
16
|
+
alias_method :delete_without_details, :delete
|
17
|
+
alias_method :delete, :delete_with_details
|
18
|
+
|
19
|
+
alias_method :clear_without_details, :clear
|
20
|
+
alias_method :clear, :clear_with_details
|
21
|
+
|
22
|
+
alias_method :add_without_details, :add
|
23
|
+
alias_method :add, :add_with_details
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# def initialize_dup_with_details(other)
|
28
|
+
# @details = other.details.dup
|
29
|
+
# initialize_dup_without_details(other)
|
30
|
+
# end
|
31
|
+
|
32
|
+
def details
|
33
|
+
@details
|
34
|
+
end
|
35
|
+
|
36
|
+
def initialize_with_details(base)
|
37
|
+
@details = Hash.new { |details, attribute| details[attribute] = [] }
|
38
|
+
initialize_without_details(base)
|
39
|
+
end
|
40
|
+
|
41
|
+
def delete_with_details(key)
|
42
|
+
details.delete(key)
|
43
|
+
delete_without_details(key)
|
44
|
+
end
|
45
|
+
|
46
|
+
def clear_with_details
|
47
|
+
details.clear
|
48
|
+
clear_without_details
|
49
|
+
end
|
50
|
+
|
51
|
+
def add_with_details(attribute, message = :invalid, options = {})
|
52
|
+
message = message.call if message.respond_to?(:call)
|
53
|
+
|
54
|
+
error = {error: message}.merge(options.except(*::ActiveModel::Errors::CALLBACKS_OPTIONS + MESSAGE_OPTIONS))
|
55
|
+
details[attribute.to_sym] << error
|
56
|
+
add_without_details(attribute, message, options)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
ActiveModel::Errors.include(ActiveModel::ErrorsDetails)
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require "minitest_helper"
|
2
|
+
# Bug in rails dependencies
|
3
|
+
# https://github.com/rails/rails/pull/18619
|
4
|
+
require "active_support/core_ext/module/remove_method"
|
5
|
+
require "active_model/naming"
|
6
|
+
|
7
|
+
class TestErrorsDetails < MiniTest::Unit::TestCase
|
8
|
+
class Person
|
9
|
+
extend ActiveModel::Naming
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@errors = ActiveModel::Errors.new(self)
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_accessor :name, :age
|
16
|
+
attr_reader :errors
|
17
|
+
|
18
|
+
def validate
|
19
|
+
errors.add(:name, :blank) if name == nil
|
20
|
+
errors.add(:age, :too_young, years: 20) if age && age < 20
|
21
|
+
end
|
22
|
+
|
23
|
+
def read_attribute_for_validation(attr)
|
24
|
+
send(attr)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.human_attribute_name(attr, options = {})
|
28
|
+
attr
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.lookup_ancestors
|
32
|
+
[]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_returns_empty_array_when_no_errors
|
37
|
+
person = Person.new
|
38
|
+
person.name = "John"
|
39
|
+
person.validate
|
40
|
+
|
41
|
+
assert_empty person.errors.details[:name]
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_adds_details
|
45
|
+
person = Person.new
|
46
|
+
person.validate
|
47
|
+
|
48
|
+
assert_equal({name: [{error: :blank}]}, person.errors.details)
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_adds_details_with_custom_value
|
52
|
+
person = Person.new
|
53
|
+
person.age = 18
|
54
|
+
person.validate
|
55
|
+
|
56
|
+
assert_equal [{error: :too_young, years: 20}], person.errors.details[:age]
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_do_not_include_message_option
|
60
|
+
person = Person.new
|
61
|
+
person.errors.add(:name, :invalid, message: "is bad")
|
62
|
+
|
63
|
+
assert_equal({name: [{error: :invalid}] }, person.errors.details)
|
64
|
+
end
|
65
|
+
|
66
|
+
# TODO: investigate why it doesn't work
|
67
|
+
# def test_dup_duplicates_details
|
68
|
+
# errors = ActiveModel::Errors.new(Person.new)
|
69
|
+
# errors.add(:name, :invalid)
|
70
|
+
# errors_dup = errors.dup
|
71
|
+
# errors_dup.add(:name, :taken)
|
72
|
+
|
73
|
+
# refute_equal errors_dup.details, errors.details
|
74
|
+
# end
|
75
|
+
|
76
|
+
def test_delete_removes_details_on_given_attribute
|
77
|
+
errors = ActiveModel::Errors.new(Person.new)
|
78
|
+
errors.add(:name, :invalid)
|
79
|
+
errors.delete(:name)
|
80
|
+
|
81
|
+
assert_empty errors.details[:name]
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_clear_removes_details
|
85
|
+
person = Person.new
|
86
|
+
person.errors.add(:name, :invalid)
|
87
|
+
|
88
|
+
assert_equal 1, person.errors.details.count
|
89
|
+
person.errors.clear
|
90
|
+
|
91
|
+
assert_empty person.errors.details
|
92
|
+
end
|
93
|
+
end
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: active_model-errors_details
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Wojciech Wnętrzak
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-21 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: '4.0'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 5.0.0.alpha
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '4.0'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 5.0.0.alpha
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: bundler
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.7'
|
40
|
+
type: :development
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1.7'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rake
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '10.0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '10.0'
|
61
|
+
description: Backported from Rails 5.0 to use with 4.x versions
|
62
|
+
email:
|
63
|
+
- w.wnetrzak@gmail.com
|
64
|
+
executables: []
|
65
|
+
extensions: []
|
66
|
+
extra_rdoc_files: []
|
67
|
+
files:
|
68
|
+
- ".gitignore"
|
69
|
+
- ".travis.yml"
|
70
|
+
- Gemfile
|
71
|
+
- LICENSE.txt
|
72
|
+
- README.md
|
73
|
+
- Rakefile
|
74
|
+
- active_model-errors_details.gemspec
|
75
|
+
- lib/active_model/errors_details.rb
|
76
|
+
- lib/active_model/errors_details/version.rb
|
77
|
+
- test/minitest_helper.rb
|
78
|
+
- test/test_errors_details.rb
|
79
|
+
homepage: https://github.com/cowbell/active_model-errors_details
|
80
|
+
licenses:
|
81
|
+
- MIT
|
82
|
+
metadata: {}
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options: []
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
requirements: []
|
98
|
+
rubyforge_project:
|
99
|
+
rubygems_version: 2.4.5
|
100
|
+
signing_key:
|
101
|
+
specification_version: 4
|
102
|
+
summary: Adds ActiveModel::Errors#details to return type of used validator
|
103
|
+
test_files:
|
104
|
+
- test/minitest_helper.rb
|
105
|
+
- test/test_errors_details.rb
|
106
|
+
has_rdoc:
|