database_validations 0.1.0 → 0.3.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 +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
|