activerecord-databasevalidations 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
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
|