database_validations 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +53 -41
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 75cc8e49376be81dd56be2da6de60dd9e4763243af4aef1ecb3bc5d5324bfabc
|
4
|
+
data.tar.gz: 7d091827be83bcfa46e89bdbaa7ff5a1964c063272a3b3099b1169e678d5d1b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c60c9a3eb7ea1783235b4636d7c9baa0af690a2218593ba96853e6f18647a01feb0449676c920d9afb6e73145d3d44df0ce1f02f153c4a161a22983204823102
|
7
|
+
data.tar.gz: 478bcddd2b83c208b34632bf782ba27e9c948c878fb7c6d751f65fb08c6ac206f1d3a7c6b28706299499f592e827dd6b8381a306014e03dd8200776ccb24ec60
|
data/README.md
CHANGED
@@ -27,6 +27,35 @@ Or install it yourself as:
|
|
27
27
|
|
28
28
|
Supported databases: `postgresql`, `mysql` and `sqlite`.
|
29
29
|
|
30
|
+
### Pros and Cons
|
31
|
+
|
32
|
+
Advantages:
|
33
|
+
- Provides true uniqueness on the database level because it handles race conditions cases properly.
|
34
|
+
- Check the existence of correct unique index at the boot time.
|
35
|
+
- It's faster. See [Benchmark](https://github.com/toptal/database_validations#benchmark-code) section for details.
|
36
|
+
|
37
|
+
Disadvantages:
|
38
|
+
- Cannot handle multiple validations at once because database raises only one error for all indexes per query.
|
39
|
+
```ruby
|
40
|
+
class User < ActiveRecord::Base
|
41
|
+
validates_db_uniqueness_of :email
|
42
|
+
validates_db_uniqueness_of :name
|
43
|
+
end
|
44
|
+
|
45
|
+
original = User.create(name: 'name', email: 'email@mail.com')
|
46
|
+
dupe = User.create(name: 'name', email: 'email@mail.com')
|
47
|
+
# => false
|
48
|
+
dupe.errors.messages
|
49
|
+
# => {:name=>["has already been taken"]}
|
50
|
+
```
|
51
|
+
|
52
|
+
### How it works?
|
53
|
+
|
54
|
+
We override `save` and `save!` methods where we rescue `ActiveRecord::RecordNotUnique` and add proper errors
|
55
|
+
for compatibility.
|
56
|
+
|
57
|
+
For `valid?` we use implementation from `validates_uniqueness_of` where we query the database.
|
58
|
+
|
30
59
|
### Usage
|
31
60
|
|
32
61
|
```ruby
|
@@ -43,26 +72,29 @@ User.create!(email: 'email@mail.com')
|
|
43
72
|
# => ActiveRecord::RecordInvalid Validation failed: email has already been taken
|
44
73
|
```
|
45
74
|
|
46
|
-
**Note**: keep in mind, we don't check uniqueness validity through `valid?` method.
|
47
|
-
```ruby
|
48
|
-
original = User.create(email: 'email@mail.com')
|
49
|
-
dupe = User.new(email: 'email@mail.com')
|
50
|
-
dupe.valid?
|
51
|
-
# => true
|
52
|
-
dupe.save
|
53
|
-
# => false
|
54
|
-
dupe.errors.messages
|
55
|
-
# => {:email=>["has already been taken"]}
|
56
|
-
```
|
57
|
-
|
58
75
|
### Configuration options
|
59
76
|
|
60
77
|
We want to provide full compatibility with existing `validates_uniqueness_of` validator.
|
61
78
|
|
62
|
-
This list of options
|
79
|
+
This list of supported options from `validates_uniqueness_of` validator:
|
63
80
|
|
64
81
|
- `scope`: One or more columns by which to limit the scope of the uniqueness constraint.
|
65
82
|
- `message`: Specifies a custom error message (default is: "has already been taken").
|
83
|
+
|
84
|
+
**Keep in mind**: Even when we don't support `case_sensitive`, `allow_nil` and `allow_blank` options now, the following:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
validates_db_uniqueness_of :email
|
88
|
+
```
|
89
|
+
|
90
|
+
Is the same by default as following
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
validates_uniqueness_of :email, allow_nil: true, allow_blank: false, case_sensitive: true
|
94
|
+
```
|
95
|
+
|
96
|
+
The list of options to add support:
|
97
|
+
|
66
98
|
- `conditions`: Specify the conditions to be included as a <tt>WHERE</tt> SQL fragment to
|
67
99
|
limit the uniqueness constraint lookup (e.g. <tt>conditions: -> { where(status: 'active') }</tt>).
|
68
100
|
- `case_sensitive`: Looks for an exact match. Ignored by non-text columns (`true` by default).
|
@@ -75,36 +107,16 @@ proc or string should return or evaluate to a `true` or `false` value.
|
|
75
107
|
occur (e.g. <tt>unless: :skip_validation</tt>, or <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>).
|
76
108
|
The method, proc or string should return or evaluate to a `true` or `false` value.
|
77
109
|
|
78
|
-
**Note**: only few options are supported now: `scope`.
|
79
|
-
|
80
110
|
### Benchmark ([code](https://github.com/toptal/database_validations/blob/master/benchmarks/uniqueness_validator_benchmark.rb))
|
81
111
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
validates_uniqueness_of
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
#### Saving only unique items ([code](https://github.com/toptal/database_validations/blob/master/benchmarks/uniqueness_validator_benchmark.rb#L63))
|
92
|
-
|
93
|
-
```
|
94
|
-
validates_db_uniqueness_of
|
95
|
-
3.558k (± 3.5%) i/s - 18.105k in 5.094799s
|
96
|
-
validates_uniqueness_of
|
97
|
-
2.031k (± 8.3%) i/s - 10.241k in 5.080059s
|
98
|
-
```
|
99
|
-
|
100
|
-
#### Each hundredth item is duplicate ([code](https://github.com/toptal/database_validations/blob/master/benchmarks/uniqueness_validator_benchmark.rb#L70))
|
101
|
-
|
102
|
-
```
|
103
|
-
validates_db_uniqueness_of
|
104
|
-
3.499k (± 4.8%) i/s - 17.628k in 5.050887s
|
105
|
-
validates_uniqueness_of
|
106
|
-
2.074k (± 8.6%) i/s - 10.388k in 5.063879s
|
107
|
-
```
|
112
|
+
| Case | Validator | SQLite | PostgreSQL | MySQL |
|
113
|
+
| -------------------------------- | -------------------------- | ------------------------------------------ | ------------------------------------------ | ------------------------------------------ |
|
114
|
+
| Save duplicate item only | validates_db_uniqueness_of | 1.404k (±14.7%) i/s - 6.912k in 5.043409s | 508.889 (± 2.8%) i/s - 2.550k in 5.015044s | 649.356 (±11.5%) i/s - 3.283k in 5.153444s |
|
115
|
+
| | validates_uniqueness_of | 1.505k (±14.6%) i/s - 7.448k in 5.075696s | 637.017 (±14.1%) i/s - 3.128k in 5.043434s | 473.561 (± 9.7%) i/s - 2.352k in 5.021151s |
|
116
|
+
| Save unique item only | validates_db_uniqueness_of | 3.241k (±18.3%) i/s - 15.375k in 5.014244s | 1.345k (± 5.5%) i/s - 6.834k in 5.096706s | 1.439k (±12.9%) i/s - 7.100k in 5.033603s |
|
117
|
+
| | validates_uniqueness_of | 2.002k (±10.9%) i/s - 9.900k in 5.018449s | 667.100 (± 4.8%) i/s - 3.350k in 5.034451s | 606.334 (± 4.9%) i/s - 3.068k in 5.072587s |
|
118
|
+
| Each hundredth item is duplicate | validates_db_uniqueness_of | 3.534k (± 5.6%) i/s - 17.748k in 5.039277s | 1.351k (± 6.5%) i/s - 6.750k in 5.017280s | 1.436k (±11.6%) i/s - 7.154k in 5.062644s |
|
119
|
+
| | validates_uniqueness_of | 2.121k (± 6.8%) i/s - 10.653k in 5.049739s | 658.199 (± 6.1%) i/s - 3.350k in 5.110176s | 596.024 (± 6.7%) i/s - 2.989k in 5.041497s |
|
108
120
|
|
109
121
|
## Development
|
110
122
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: database_validations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evgeniy Demin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-08-
|
11
|
+
date: 2018-08-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|