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: 090f45578b6802cdbdba1069b5d37a9a36936e53
4
- data.tar.gz: 8804b23a035aaa84fa334caa69fa862971bf0ffc
3
+ metadata.gz: e4aea1bc84aef567070fd2cb3febe2bdb6895daf
4
+ data.tar.gz: 2e8257b79b80d5b84d791b3ec7dfcffe3d115ea4
5
5
  SHA512:
6
- metadata.gz: 48f4ce81a05aa5798f73b24997eea4920027318e4c48cdae4824c806a3cee5c84688058f204af0bf074b29360037108939bca38c0389b52f18cd3d3fd52ab941
7
- data.tar.gz: 33774245ec628ff1b463559346e3e11699e302b4a41417676caf42ad08b5a8f07f3f613fb0d724c41edd883e7b51b90a660889e75cf4134d9e9526b909c8c438
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
- - `:size` to validate for the size of textual and binary columns. It will pick character
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
- - `:not_null` to validate a NOT NULL contraint.
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'
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module DatabaseValidations
3
- VERSION = "0.1.3"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
@@ -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.1.3
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-10-22 00:00:00.000000000 Z
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
- - ".gitignore"
106
- - ".travis.yml"
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.2.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