activerecord-databasevalidations 0.1.3 → 0.2.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
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e4aea1bc84aef567070fd2cb3febe2bdb6895daf
|
4
|
+
data.tar.gz: 2e8257b79b80d5b84d791b3ec7dfcffe3d115ea4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f7359255dd4cd2ad194d62aca4c6b7c19ffb26c999cb77a8d453b4fc28f7617f4bb4b30e520180a7a3cbf190fccccd08d31ca0d3e776d2d153ef6b4dcb9d41ff
|
7
|
+
data.tar.gz: 320f2a3744403023282bb9399fcc720a6592913142283dd8b3c3ec9e82146de6e7974e78b9678c4cc2e1ac924eb250f9acbe8adb70d9dcb56257b0d492bf96b8
|
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# ActiveRecord::DatabaseValidations
|
2
2
|
|
3
|
-
Add validations to your ActiveRecord models based on your database constraints.
|
3
|
+
Add validations to your ActiveRecord models based on your database constraints.
|
4
4
|
|
5
|
-
This gem is primarily intended for MySQL databases not running in strict mode,
|
6
|
-
which can easily cause data loss. These problems are documented in
|
5
|
+
This gem is primarily intended for MySQL databases not running in strict mode,
|
6
|
+
which can easily cause data loss. These problems are documented in
|
7
7
|
[DataLossTest](https://github.com/wvanbergen/activerecord-databasevalidations/blob/master/test/data_loss_test.rb)
|
8
8
|
|
9
9
|
## Installation
|
@@ -29,6 +29,7 @@ to validate based on the database constraints.
|
|
29
29
|
class Foo < ActiveRecord::Base
|
30
30
|
validates :boolean_field, database_constraints: :not_null
|
31
31
|
validates :string_field, database_constraints: [:size, :basic_multilingual_plane]
|
32
|
+
validates :decimal_field, :integer_field, database_constraints: :range
|
32
33
|
end
|
33
34
|
```
|
34
35
|
|
@@ -44,11 +45,12 @@ end
|
|
44
45
|
|
45
46
|
You have to specify what conatrints you want to validate for. Valid values are:
|
46
47
|
|
47
|
-
- `:
|
48
|
+
- `:range` to validate the numeric range of a column based on it's type.
|
49
|
+
- `:size` to validate for the size of textual and binary columns. It will pick character
|
48
50
|
size or bytesize based on the column's type.
|
49
|
-
- `:
|
50
|
-
- `:basic_multilingual_plane` to validate that all characters for text fields are inside
|
51
|
+
- `:basic_multilingual_plane` to validate that all characters for text fields are inside
|
51
52
|
the basic multilingual plane of unicode (unless you use the utf8mb4 character set).
|
53
|
+
- `:not_null` to validate a NOT NULL contraint.
|
52
54
|
|
53
55
|
The validations will only be created if it makes sense for the column, e.g. a `:not_null`
|
54
56
|
validation will only be added if the column has a NOT NULL constraint defined on it.
|
@@ -64,9 +66,31 @@ class Bar < ActiveRecord::Base
|
|
64
66
|
end
|
65
67
|
```
|
66
68
|
|
67
|
-
Note that this will create validations without inspecting the column to see if it
|
69
|
+
Note that this will create validations without inspecting the column to see if it
|
68
70
|
actually makes sense.
|
69
71
|
|
72
|
+
### Replicating MySQL's truncation behavior
|
73
|
+
|
74
|
+
Sometimes, truncated a string that goes over the column's limit is the best option, if
|
75
|
+
you don't want one field's value being too long prevent the record from saving.
|
76
|
+
|
77
|
+
You can use `truncate_string` to replicate MySQL's non-strict truncating behavior, so
|
78
|
+
you can prepare yourself for eventually turning on strict mode.
|
79
|
+
|
80
|
+
|
81
|
+
``` ruby
|
82
|
+
class Unicorn < ActiveRecord::Base
|
83
|
+
include ActiveRecord::DatabaseValidations::StringTruncator
|
84
|
+
|
85
|
+
before_validation truncate_string(:string_field)
|
86
|
+
validates :string_field, database_constraints: [:size]
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
In this example, it will truncate the string to a size that will fit before validation,
|
91
|
+
so the subsequent size validation will now always pass.
|
92
|
+
|
93
|
+
|
70
94
|
## Contributing
|
71
95
|
|
72
96
|
1. Fork it (http://github.com/wvanbergen/activerecord-databasevalidations/fork)
|
@@ -3,5 +3,6 @@ require 'active_support/i18n'
|
|
3
3
|
require 'active_record/database_validations/version'
|
4
4
|
|
5
5
|
require 'active_record/validations/database_constraints'
|
6
|
+
require 'active_record/validations/string_truncator'
|
6
7
|
|
7
8
|
I18n.load_path << File.dirname(__FILE__) + '/database_validations/locale/en.yml'
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module DatabaseValidations
|
3
|
+
module StringTruncator
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
def truncate_string(field)
|
8
|
+
column = self.columns_hash[field.to_s]
|
9
|
+
case column.type
|
10
|
+
when :string
|
11
|
+
lambda do
|
12
|
+
return unless self.changes.key?(field.to_s)
|
13
|
+
return if self[field].nil?
|
14
|
+
|
15
|
+
limit = StringTruncator.mysql_textual_column_limit(column)
|
16
|
+
value = self[field].to_s
|
17
|
+
if value.length > limit
|
18
|
+
self[field] = value.slice(0, limit)
|
19
|
+
end
|
20
|
+
return true # to make sure the callback chain doesn't halt
|
21
|
+
end
|
22
|
+
|
23
|
+
when :text
|
24
|
+
lambda do
|
25
|
+
return unless self.changes.key?(field.to_s)
|
26
|
+
return if self[field].nil?
|
27
|
+
|
28
|
+
limit = StringTruncator.mysql_textual_column_limit(column)
|
29
|
+
value = self[field].to_s
|
30
|
+
value.encode!('utf-8') if value.encoding != Encoding::UTF_8
|
31
|
+
if value.bytesize > limit
|
32
|
+
self[field] = value.mb_chars.limit(limit).to_s
|
33
|
+
end
|
34
|
+
return true # to make sure the callback chain doesn't halt
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.mysql_textual_column_limit(column)
|
41
|
+
@mysql_textual_column_limits ||= {}
|
42
|
+
@mysql_textual_column_limits[column] ||= begin
|
43
|
+
raise ArgumentError, "Only UTF-8 textual columns are supported." unless column.text? && column.collation =~ /\Autf8_/
|
44
|
+
column.limit
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
ActiveRecord::Migration.suppress_messages do
|
5
|
+
ActiveRecord::Migration.create_table("magical_creatures", force: true, options: "CHARACTER SET utf8mb3") do |t|
|
6
|
+
t.string :string, limit: 255
|
7
|
+
t.text :tinytext, limit: 255
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class MagicalCreature < ActiveRecord::Base
|
12
|
+
include ActiveRecord::DatabaseValidations::StringTruncator
|
13
|
+
|
14
|
+
before_validation truncate_string(:string)
|
15
|
+
before_validation truncate_string(:tinytext)
|
16
|
+
|
17
|
+
validates :string, :tinytext, database_constraints: :size
|
18
|
+
end
|
19
|
+
|
20
|
+
class StringTruncatorTest < Minitest::Test
|
21
|
+
def test_handles_nil_gracefully
|
22
|
+
u_nil = MagicalCreature.create!(string: 'present', tinytext: 'present')
|
23
|
+
u_nil.string, u_nil.tinytext = nil, nil
|
24
|
+
assert_equal ['string', 'tinytext'], u_nil.changed
|
25
|
+
assert u_nil.valid?
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_truncate_varchar_field_using_characters
|
29
|
+
u1 = MagicalCreature.new(string: 'a' * 256)
|
30
|
+
assert u1.valid?
|
31
|
+
assert_equal 'a' * 255, u1.string
|
32
|
+
|
33
|
+
u2 = MagicalCreature.new(string: '漢' * 256)
|
34
|
+
assert u2.valid?
|
35
|
+
assert_equal '漢' * 255, u2.string
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_truncate_text_fields_using_bytes
|
39
|
+
u1 = MagicalCreature.new(string: 'a' * 256)
|
40
|
+
assert u1.valid?
|
41
|
+
assert_equal 'a' * 255, u1.string
|
42
|
+
|
43
|
+
u2 = MagicalCreature.new(tinytext: '漢' * 86)
|
44
|
+
assert u2.valid?
|
45
|
+
assert_equal '漢' * 85, u2.tinytext
|
46
|
+
|
47
|
+
u3 = MagicalCreature.new(tinytext: 'ü' * 128) # note: field limit falls between the two bytes of the last character.
|
48
|
+
assert u3.valid?
|
49
|
+
assert_equal 'ü' * 127, u3.tinytext
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_recoding_support_for_text_fields
|
53
|
+
u4 = MagicalCreature.new(tinytext: ('ü' * 128).encode('ISO-8859-15'))
|
54
|
+
assert u4.valid?
|
55
|
+
assert_equal 'ü' * 127, u4.tinytext
|
56
|
+
assert_equal Encoding::UTF_8, u4.tinytext.encoding
|
57
|
+
end
|
58
|
+
end
|
metadata
CHANGED
@@ -1,97 +1,97 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-databasevalidations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Willem van Bergen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '4.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '4.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rejectu
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - '>='
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - '>='
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: bundler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ~>
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '1.5'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.5'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - '>='
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: minitest
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - '>='
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - '>='
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: mysql2
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - '>='
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - '>='
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
description: Opt-in validations for your ActiveRecord models based on your MySQL database
|
@@ -102,8 +102,8 @@ executables: []
|
|
102
102
|
extensions: []
|
103
103
|
extra_rdoc_files: []
|
104
104
|
files:
|
105
|
-
-
|
106
|
-
-
|
105
|
+
- .gitignore
|
106
|
+
- .travis.yml
|
107
107
|
- Gemfile
|
108
108
|
- Gemfile.activerecord40
|
109
109
|
- Gemfile.activerecord41
|
@@ -118,6 +118,7 @@ files:
|
|
118
118
|
- lib/active_record/database_validations/locale/en.yml
|
119
119
|
- lib/active_record/database_validations/version.rb
|
120
120
|
- lib/active_record/validations/database_constraints.rb
|
121
|
+
- lib/active_record/validations/string_truncator.rb
|
121
122
|
- lib/activerecord-databasevalidations.rb
|
122
123
|
- lib/activerecord/databasevalidations.rb
|
123
124
|
- test/basic_multilingual_plane_validator_test.rb
|
@@ -126,6 +127,7 @@ files:
|
|
126
127
|
- test/database.yml
|
127
128
|
- test/database_constraints_validator_test.rb
|
128
129
|
- test/not_null_validator_test.rb
|
130
|
+
- test/string_truncator_test.rb
|
129
131
|
- test/test_helper.rb
|
130
132
|
homepage: https://github.com/wvanbergen/activerecord-database_validations
|
131
133
|
licenses:
|
@@ -137,17 +139,17 @@ require_paths:
|
|
137
139
|
- lib
|
138
140
|
required_ruby_version: !ruby/object:Gem::Requirement
|
139
141
|
requirements:
|
140
|
-
- -
|
142
|
+
- - '>='
|
141
143
|
- !ruby/object:Gem::Version
|
142
144
|
version: '0'
|
143
145
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
146
|
requirements:
|
145
|
-
- -
|
147
|
+
- - '>='
|
146
148
|
- !ruby/object:Gem::Version
|
147
149
|
version: '0'
|
148
150
|
requirements: []
|
149
151
|
rubyforge_project:
|
150
|
-
rubygems_version: 2.
|
152
|
+
rubygems_version: 2.0.14
|
151
153
|
signing_key:
|
152
154
|
specification_version: 4
|
153
155
|
summary: Add validations to your ActiveRecord models based on MySQL database constraints.
|
@@ -158,4 +160,5 @@ test_files:
|
|
158
160
|
- test/database.yml
|
159
161
|
- test/database_constraints_validator_test.rb
|
160
162
|
- test/not_null_validator_test.rb
|
163
|
+
- test/string_truncator_test.rb
|
161
164
|
- test/test_helper.rb
|