validates_lengths_from_database 0.7.0 → 1.0.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
- SHA1:
3
- metadata.gz: ee05414f5d7aef3fb39a4e692b6616259d20db11
4
- data.tar.gz: '096b57b2a49d98450f1127f27dfd135c34556d86'
2
+ SHA256:
3
+ metadata.gz: 5cf4553c64ac4dd1b06fce9e8b6123f3bb426a7a83d0e8ee4949db2ae530aa76
4
+ data.tar.gz: b714ddd62d656a23029b181448e7d6881542c3da7b3b1988ff63e4153b7e43dc
5
5
  SHA512:
6
- metadata.gz: dd35abc81106fe376476a747e78a89aeedaf2828a9aeff2e1f30181a486efc7da88474e5914b82a5df3706bb6f2dd8c0995ea5c05d8a9986ebc234ea40f3cb2c
7
- data.tar.gz: d637ae88ae7aa3e2a738e095981270d0228817ab660f8e98214bc0f0bfc23b09e463bb8ab62be5221a6191a9c9504e089d3ceb62d96b23f5d95f9530437a6714
6
+ metadata.gz: 381df3fa482b0f1d882ac8d81b35282db35a8d66cfe523c9f9f6a9ebbb6234d2319a1fa3264f06bc36e2c5fafc3e022dce53091350fff5bfa231e73d440da9e5
7
+ data.tar.gz: 896b9a14a0104a7723a7bc026d3fc5479ca8c0d5128a6107064ec08314bc08c60485c5bac8b2e334cb4dae10ac0fe3b96391732c877bb6e1cfae9535b8111f26
data/CHANGELOG.md ADDED
@@ -0,0 +1,50 @@
1
+ # Changelog
2
+
3
+ ## v1.0.0 (2026-10-14)
4
+
5
+ - Require Rails (ActiveRecord) 6.1+ and Ruby 2.7+. Apps on older versions can stay on 0.8.x.
6
+ - Tested against Rails 6.1 through 8.1 on SQLite, PostgreSQL and MySQL.
7
+ - The "too long (bytes)" error for TEXT columns can now be translated with the `too_long_bytes` key (#42) - thanks @Bhalani
8
+ - Validate the lower bound of DECIMAL columns, so -1000 is rejected for DECIMAL(5,2)
9
+ - No longer modify the options hash passed to `validates_lengths_from_database`
10
+ - Accept string keys in the `:limit` hash
11
+
12
+ ## v0.8.0 (2019-10-30)
13
+
14
+ - Enforce validation length on TEXT columns via bytes instead of characters (#25)
15
+ - Drop support for ruby 1.9 (#26)
16
+
17
+ ## v0.7.0 (2017-10-09)
18
+
19
+ - Drop hard reliance on rails (can use with just activerecord) - thanks @grosser
20
+ - Drop requiring of rubygems (unnecessary) - thanks @grosser
21
+ - Update dependencies to modern, build-able versions
22
+
23
+ ## v0.6.0 (2017-05-02)
24
+
25
+ - Drop support for integer length validations (too many issues)
26
+
27
+ ## v0.5.2 (2017-04-28)
28
+
29
+ - Fix handling with STI models - thanks @iNecas
30
+
31
+ ## v0.5.1 (2017-04-27)
32
+
33
+ - Fix sharing options between models - thanks @iNecas
34
+
35
+ ## v0.5.0 (2016-01-28)
36
+
37
+ - Drop support for rails 2
38
+ - Implement lazy-evaluation of column information for better compatibility with early load orders - thanks @domcleal.
39
+
40
+ ## v0.4.0 (2015-01-03)
41
+
42
+ - Drop support for ruby 1.8.7 and 1.9.2 - too many issues with backwards-compatibility
43
+
44
+ ## v0.3.0 (2015-01-03)
45
+
46
+ - Explicit support for Rails 4.1 and 4.2
47
+ - Up-to-date Appraisals and dependencies
48
+ - Better support for postgres text columns via conditional length validation
49
+ - Bug fix for postgres array column types
50
+
data/README.md ADDED
@@ -0,0 +1,127 @@
1
+ # Validates Lengths from Database
2
+
3
+ [![CI](https://github.com/eigenben/validates_lengths_from_database/actions/workflows/ci.yml/badge.svg)](https://github.com/eigenben/validates_lengths_from_database/actions/workflows/ci.yml)
4
+ [![Gem Version](https://badge.fury.io/rb/validates_lengths_from_database.svg)](https://rubygems.org/gems/validates_lengths_from_database)
5
+
6
+ Few people add length validations to fields in their database, and when saving such fields that have exhausted their length, an SQL error occurs.
7
+ This gem introspects your table schema for maximum lengths on string and text fields and automatically adds length validations to the model.
8
+
9
+ ## Requirements
10
+
11
+ * Ruby 2.7 or newer
12
+ * ActiveRecord 6.1 or newer
13
+
14
+ For older versions of Rails or Ruby, use the 0.8.x releases.
15
+
16
+ ## Installation
17
+
18
+ Include the gem using bundler in your Gemfile:
19
+
20
+ ```ruby
21
+ gem "validates_lengths_from_database"
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ In your model you can activate validations:
27
+
28
+ ```ruby
29
+ class Post < ActiveRecord::Base
30
+ validates_lengths_from_database
31
+ end
32
+ ```
33
+
34
+ It also supports filter-style `:only` and `:except` options:
35
+
36
+ ```ruby
37
+ class Post < ActiveRecord::Base
38
+ validates_lengths_from_database only: [:title, :contents]
39
+ end
40
+
41
+ class Post < ActiveRecord::Base
42
+ validates_lengths_from_database except: [:other_field]
43
+ end
44
+ ```
45
+
46
+ If you'd rather specify the limits explicitly instead of pulling them from the database, you can set it:
47
+
48
+ ```ruby
49
+ class Post < ActiveRecord::Base
50
+ validates_lengths_from_database limit: 255
51
+ end
52
+ ```
53
+
54
+ Or to set the limit differently for string (`VARCHAR`) and `TEXT` columns:
55
+
56
+ ```ruby
57
+ class Post < ActiveRecord::Base
58
+ validates_lengths_from_database limit: { string: 255, text: 4092 }
59
+ end
60
+ ```
61
+
62
+ You can use `validates_lengths_from_database` on an abstract parent (without a table), such as `ApplicationRecord` or `ActiveRecord::Base`:
63
+
64
+ ```ruby
65
+ class ApplicationRecord < ActiveRecord::Base
66
+ self.abstract_class = true
67
+ validates_lengths_from_database limit: 255
68
+ end
69
+
70
+ # This will use the validations with default options (from parent)
71
+ class Post < ApplicationRecord
72
+ end
73
+
74
+ # This will use the validations, with overriding the default options (the limit will not be applied)
75
+ class User < ApplicationRecord
76
+ validates_lengths_from_database only: [:name]
77
+ end
78
+
79
+ # This will use the validations, using the default options + adding some class specific customizations
80
+ class Comment < ApplicationRecord
81
+ validate_lengths_from_database_options[:only] << :name
82
+ end
83
+ ```
84
+
85
+ ## What gets validated
86
+
87
+ * **String (`VARCHAR`) columns** are limited to the column's length in characters.
88
+ * **`TEXT` columns** are limited to the column's length in bytes, since that is how MySQL measures them.
89
+ * **`DECIMAL` columns** with a precision and scale must fit within them. For example, `DECIMAL(5,2)` accepts -999.99 through 999.99.
90
+
91
+ Columns without a limit are skipped, so what this gem does depends on your database:
92
+
93
+ * **MySQL**: `t.string` columns are `VARCHAR(255)` and `t.text` columns are `TEXT` (65,535 bytes) unless you say otherwise. This is where the gem helps most, turning `ActiveRecord::ValueTooLong` exceptions into validation errors.
94
+ * **PostgreSQL**: Rails creates `t.string` columns with no length limit, and `TEXT` columns never have one, so only columns declared with an explicit `limit:` are validated.
95
+ * **SQLite**: limits declared in migrations are validated, even though SQLite itself does not enforce them.
96
+
97
+ ## Translating the bytes error message
98
+
99
+ `TEXT` columns that are too long get the `too_long_bytes` error, which defaults to "is too long (maximum is %{count} bytes)".
100
+ Override it in your locale files like any other ActiveModel error message:
101
+
102
+ ```yaml
103
+ en:
104
+ errors:
105
+ messages:
106
+ too_long_bytes:
107
+ one: "is too long (maximum is 1 byte)"
108
+ other: "is too long (maximum is %{count} bytes)"
109
+ ```
110
+
111
+ ## Running Tests
112
+
113
+ The specs run against SQLite by default:
114
+
115
+ ```
116
+ bundle install
117
+ bundle exec rspec
118
+ ```
119
+
120
+ Set `DB=postgresql` or `DB=mysql` to test against those databases instead. Both expect a database named `validates_lengths_from_database_test`, and connection settings can be changed with environment variables (see `spec/db/database.yml`).
121
+
122
+ To test against a specific Rails version, use one of the gemfiles in `gemfiles/`:
123
+
124
+ ```
125
+ BUNDLE_GEMFILE=gemfiles/rails_7.0.gemfile bundle install
126
+ BUNDLE_GEMFILE=gemfiles/rails_7.0.gemfile bundle exec rspec
127
+ ```
@@ -0,0 +1,6 @@
1
+ en:
2
+ errors:
3
+ messages:
4
+ too_long_bytes:
5
+ one: "is too long (maximum is 1 byte)"
6
+ other: "is too long (maximum is %{count} bytes)"
@@ -1,20 +1,26 @@
1
1
  module ValidatesLengthsFromDatabase
2
- def self.included(base)
3
- base.send(:extend, ClassMethods)
4
- base.send(:include, InstanceMethods)
2
+ extend ActiveSupport::Concern
3
+
4
+ class BytesizeValidator < ActiveModel::Validations::LengthValidator
5
+ def validate_each(record, attribute, value)
6
+ value_for_validation = value.is_a?(String) ? value.bytes : value
7
+
8
+ super(record, attribute, value_for_validation)
9
+ end
5
10
  end
6
11
 
7
12
  module ClassMethods
8
13
  def validates_lengths_from_database(options = {})
9
- options.symbolize_keys!
14
+ # Copy everything we keep so later changes to the stored options
15
+ # (see README) never leak back into the caller's hash or arrays.
16
+ options = options.symbolize_keys
10
17
 
11
- options[:only] = Array[options[:only]] if options[:only] && !options[:only].is_a?(Array)
12
- options[:except] = Array[options[:except]] if options[:except] && !options[:except].is_a?(Array)
13
- options[:limit] ||= {}
18
+ options[:only] = Array(options[:only]).dup if options[:only]
19
+ options[:except] = Array(options[:except]).dup if options[:except]
20
+
21
+ limit = options[:limit] || {}
22
+ options[:limit] = limit.is_a?(Hash) ? limit.symbolize_keys : {:string => limit, :text => limit}
14
23
 
15
- if options[:limit] and !options[:limit].is_a?(Hash)
16
- options[:limit] = {:string => options[:limit], :text => options[:limit], :decimal => options[:limit], :integer => options[:limit], :float => options[:limit]}
17
- end
18
24
  @validate_lengths_from_database_options = options
19
25
 
20
26
  validate :validate_lengths_from_database
@@ -36,35 +42,67 @@ module ValidatesLengthsFromDatabase
36
42
  end
37
43
  end
38
44
 
39
- module InstanceMethods
40
- def validate_lengths_from_database
41
- options = self.class.validate_lengths_from_database_options
45
+ def validate_lengths_from_database
46
+ options = self.class.validate_lengths_from_database_options
42
47
 
43
- if options[:only]
44
- columns_to_validate = options[:only].map(&:to_s)
45
- else
46
- columns_to_validate = self.class.column_names.map(&:to_s)
47
- columns_to_validate -= options[:except].map(&:to_s) if options[:except]
48
- end
48
+ if options[:only]
49
+ columns_to_validate = options[:only].map(&:to_s)
50
+ else
51
+ columns_to_validate = self.class.column_names.map(&:to_s)
52
+ columns_to_validate -= options[:except].map(&:to_s) if options[:except]
53
+ end
54
+
55
+ columns_to_validate.each do |column|
56
+ column_schema = self.class.columns_hash[column]
57
+
58
+ next if column_schema.nil?
59
+ next if column_schema.respond_to?(:array) && column_schema.array
60
+ next unless [:string, :text, :decimal].include?(column_schema.type)
49
61
 
50
- columns_to_validate.each do |column|
51
- column_schema = self.class.columns.find {|c| c.name == column }
52
- next if column_schema.nil?
53
- next if column_schema.respond_to?(:array) && column_schema.array
54
- next unless [:string, :text, :decimal].include?(column_schema.type)
55
- case column_schema.type
56
- when :string, :text
57
- column_limit = options[:limit][column_schema.type] || column_schema.limit
58
- if column_limit
59
- ActiveModel::Validations::LengthValidator.new(:maximum => column_limit, :allow_blank => true, :attributes => [column]).validate(self)
60
- end
61
- when :decimal
62
- if column_schema.precision && column_schema.scale
63
- max_val = (10 ** column_schema.precision)/(10 ** column_schema.scale)
64
- ActiveModel::Validations::NumericalityValidator.new(:less_than => max_val, :allow_blank => true, :attributes => [column]).validate(self)
65
- end
62
+ case column_schema.type
63
+ when :string
64
+ if column_limit = options[:limit][column_schema.type] || column_schema.limit
65
+ validate_length_by_characters(column, column_limit)
66
+ end
67
+ when :text
68
+ if column_limit = options[:limit][column_schema.type] || column_schema.limit
69
+ validate_length_by_bytesize(column, column_limit)
70
+ end
71
+ when :decimal
72
+ if column_schema.precision && column_schema.scale
73
+ validate_numericality_with_precision(column, column_schema)
66
74
  end
67
75
  end
68
76
  end
69
77
  end
78
+
79
+ private
80
+
81
+ def validate_length_by_characters(column, column_limit)
82
+ ActiveModel::Validations::LengthValidator.new(
83
+ :allow_blank => true,
84
+ :attributes => [column],
85
+ :maximum => column_limit
86
+ ).validate(self)
87
+ end
88
+
89
+ def validate_length_by_bytesize(column, column_limit)
90
+ BytesizeValidator.new(
91
+ :allow_blank => true,
92
+ :attributes => [column],
93
+ :maximum => column_limit,
94
+ :too_long => :too_long_bytes
95
+ ).validate(self)
96
+ end
97
+
98
+ def validate_numericality_with_precision(column, column_schema)
99
+ max_val = (10 ** column_schema.precision)/(10 ** column_schema.scale)
100
+
101
+ ActiveModel::Validations::NumericalityValidator.new(
102
+ :allow_blank => true,
103
+ :attributes => [column],
104
+ :less_than => max_val,
105
+ :greater_than => -max_val
106
+ ).validate(self)
107
+ end
70
108
  end
@@ -13,7 +13,7 @@ module ValidatesLengthsFromDatabase
13
13
 
14
14
  class Railtie
15
15
  def self.insert
16
- ActiveRecord::Base.send(:include, ValidatesLengthsFromDatabase)
16
+ ActiveRecord::Base.include(ValidatesLengthsFromDatabase)
17
17
  end
18
18
  end
19
19
  end
@@ -1,3 +1,3 @@
1
1
  module ValidatesLengthsFromDatabase
2
- VERSION = "0.7.0"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -1,3 +1,7 @@
1
+ require "active_support"
2
+ require "active_support/i18n"
3
+
4
+ I18n.load_path << File.expand_path("../config/locales/en.yml", __dir__)
1
5
 
2
6
  require "validates_lengths_from_database/core"
3
7
  require "validates_lengths_from_database/railtie"
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: validates_lengths_from_database
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Hughes
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2017-10-09 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activerecord
@@ -16,169 +15,37 @@ dependencies:
16
15
  requirements:
17
16
  - - ">="
18
17
  - !ruby/object:Gem::Version
19
- version: '3'
18
+ version: '6.1'
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - ">="
25
24
  - !ruby/object:Gem::Version
26
- version: '3'
27
- - !ruby/object:Gem::Dependency
28
- name: activesupport
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '3'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '3'
41
- - !ruby/object:Gem::Dependency
42
- name: rspec
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '2.0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '2.0'
55
- - !ruby/object:Gem::Dependency
56
- name: sqlite3
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: 1.3.4
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: 1.3.4
69
- - !ruby/object:Gem::Dependency
70
- name: appraisal
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: 1.0.2
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: 1.0.2
83
- - !ruby/object:Gem::Dependency
84
- name: pg
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: 0.17.1
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: 0.17.1
97
- - !ruby/object:Gem::Dependency
98
- name: rdoc
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: '3.12'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '3.12'
111
- - !ruby/object:Gem::Dependency
112
- name: rake
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
- - !ruby/object:Gem::Dependency
126
- name: i18n
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - ">="
130
- - !ruby/object:Gem::Version
131
- version: '0'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - ">="
137
- - !ruby/object:Gem::Version
138
- version: '0'
139
- - !ruby/object:Gem::Dependency
140
- name: iconv
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: 1.0.4
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "~>"
151
- - !ruby/object:Gem::Version
152
- version: 1.0.4
25
+ version: '6.1'
153
26
  description: Introspects your database string field maximum lengths and automatically
154
27
  defines length validations.
155
- email: ben@railsgarden.com
28
+ email: me@benhughes.name
156
29
  executables: []
157
30
  extensions: []
158
31
  extra_rdoc_files: []
159
32
  files:
160
- - Appraisals
161
- - CHANGELOG.rdoc
162
- - Gemfile
163
- - Gemfile.lock
33
+ - CHANGELOG.md
164
34
  - LICENSE
165
- - README.rdoc
166
- - Rakefile
167
- - init.rb
35
+ - README.md
36
+ - config/locales/en.yml
168
37
  - lib/validates_lengths_from_database.rb
169
38
  - lib/validates_lengths_from_database/core.rb
170
39
  - lib/validates_lengths_from_database/railtie.rb
171
40
  - lib/validates_lengths_from_database/version.rb
172
- - rails/init.rb
173
- - spec/db/database.yml
174
- - spec/db/schema.rb
175
- - spec/db/test.sqlite3
176
- - spec/spec_helper.rb
177
- - spec/validates_lengths_from_database_spec.rb
178
- homepage: http://github.com/rubiety/validates_lengths_from_database
179
- licenses: []
180
- metadata: {}
181
- post_install_message:
41
+ homepage: https://github.com/eigenben/validates_lengths_from_database
42
+ licenses:
43
+ - MIT
44
+ metadata:
45
+ source_code_uri: https://github.com/eigenben/validates_lengths_from_database
46
+ changelog_uri: https://github.com/eigenben/validates_lengths_from_database/blob/master/CHANGELOG.md
47
+ bug_tracker_uri: https://github.com/eigenben/validates_lengths_from_database/issues
48
+ rubygems_mfa_required: 'true'
182
49
  rdoc_options: []
183
50
  require_paths:
184
51
  - lib
@@ -186,16 +53,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
186
53
  requirements:
187
54
  - - ">="
188
55
  - !ruby/object:Gem::Version
189
- version: 1.9.3
56
+ version: '2.7'
190
57
  required_rubygems_version: !ruby/object:Gem::Requirement
191
58
  requirements:
192
59
  - - ">="
193
60
  - !ruby/object:Gem::Version
194
- version: 1.3.4
61
+ version: '0'
195
62
  requirements: []
196
- rubyforge_project: validates_lengths_from_database
197
- rubygems_version: 2.6.11
198
- signing_key:
63
+ rubygems_version: 3.6.7
199
64
  specification_version: 4
200
65
  summary: Automatic maximum-length validations.
201
66
  test_files: []
data/Appraisals DELETED
@@ -1,23 +0,0 @@
1
- appraise "3.0" do
2
- gem "rails", "~> 3.0.12"
3
- end
4
-
5
- appraise "3.1" do
6
- gem "rails", "~> 3.1.4"
7
- end
8
-
9
- appraise "3.2" do
10
- gem "rails", "~> 3.2.2"
11
- end
12
-
13
- appraise "4.0" do
14
- gem "rails", "~> 4.0.12"
15
- end
16
-
17
- appraise "4.1" do
18
- gem "rails", "~> 4.1.8"
19
- end
20
-
21
- appraise "4.2" do
22
- gem "rails", "~> 4.2.0"
23
- end
data/CHANGELOG.rdoc DELETED
@@ -1,34 +0,0 @@
1
- == v0.7.0 (2017-10-09)
2
-
3
- * Drop hard reliance on rails (can use with just activerecord) - thanks @grosser
4
- * Drop requiring of rubygems (unnecessary) - thanks @grosser
5
- * Update dependencies to modern, build-able versions
6
-
7
- == v0.6.0 (2017-05-02)
8
-
9
- * Drop support for integer length validations (too many issues)
10
-
11
- == v0.5.2 (2017-04-28)
12
-
13
- * Fix handling with STI models - thanks @iNecas
14
-
15
- == v0.5.1 (2017-04-27)
16
-
17
- * Fix sharing options between models - thanks @iNecas
18
-
19
- == v0.5.0 (2016-01-28)
20
-
21
- * Drop support for rails 2
22
- * Implement lazy-evaluation of column information for better compatibility with early load orders - thanks @domcleal.
23
-
24
- == v0.4.0 (2015-01-03)
25
-
26
- * Drop support for ruby 1.8.7 and 1.9.2 - too many issues with backwards-compatibility
27
-
28
- == v0.3.0 (2015-01-03)
29
-
30
- * Explicit support for Rails 4.1 and 4.2
31
- * Up-to-date Appraisals and dependencies
32
- * Better support for postgres text columns via conditional length validation
33
- * Bug fix for postgres array column types
34
-
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- # Specify your gem's dependencies in testgem.gemspec
4
- gemspec
data/Gemfile.lock DELETED
@@ -1,70 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- validates_lengths_from_database (0.6.0)
5
- activerecord (>= 3)
6
-
7
- GEM
8
- remote: http://rubygems.org/
9
- specs:
10
- activemodel (4.0.12)
11
- activesupport (= 4.0.12)
12
- builder (~> 3.1.0)
13
- activerecord (4.0.12)
14
- activemodel (= 4.0.12)
15
- activerecord-deprecated_finders (~> 1.0.2)
16
- activesupport (= 4.0.12)
17
- arel (~> 4.0.0)
18
- activerecord-deprecated_finders (1.0.4)
19
- activesupport (4.0.12)
20
- i18n (~> 0.6, >= 0.6.9)
21
- minitest (~> 4.2)
22
- multi_json (~> 1.3)
23
- thread_safe (~> 0.1)
24
- tzinfo (~> 0.3.37)
25
- appraisal (1.0.2)
26
- bundler
27
- rake
28
- thor (>= 0.14.0)
29
- arel (4.0.2)
30
- builder (3.1.4)
31
- diff-lcs (1.1.2)
32
- i18n (0.7.0)
33
- iconv (1.0.4)
34
- json (1.8.6)
35
- minitest (4.7.5)
36
- multi_json (1.10.1)
37
- pg (0.17.1)
38
- rake (0.9.2.2)
39
- rdoc (3.12)
40
- json (~> 1.4)
41
- rspec (2.5.0)
42
- rspec-core (~> 2.5.0)
43
- rspec-expectations (~> 2.5.0)
44
- rspec-mocks (~> 2.5.0)
45
- rspec-core (2.5.1)
46
- rspec-expectations (2.5.0)
47
- diff-lcs (~> 1.1.2)
48
- rspec-mocks (2.5.0)
49
- sqlite3 (1.3.11)
50
- thor (0.19.1)
51
- thread_safe (0.3.4)
52
- tzinfo (0.3.42)
53
-
54
- PLATFORMS
55
- ruby
56
-
57
- DEPENDENCIES
58
- activesupport (>= 3)
59
- appraisal (~> 1.0.2)
60
- i18n
61
- iconv (~> 1.0.4)
62
- pg (~> 0.17.1)
63
- rake
64
- rdoc (~> 3.12)
65
- rspec (~> 2.0)
66
- sqlite3 (~> 1.3.4)
67
- validates_lengths_from_database!
68
-
69
- BUNDLED WITH
70
- 1.15.4
data/README.rdoc DELETED
@@ -1,85 +0,0 @@
1
- {<img src="https://secure.travis-ci.org/rubiety/validates_lengths_from_database.png?branch=master" alt="Build Status" />}[http://travis-ci.org/rubiety/validates_lengths_from_database]
2
- {<img src="https://gemnasium.com/rubiety/validates_lengths_from_database.png" alt="Dependency Status" />}[https://gemnasium.com/rubiety/validates_lengths_from_database]
3
- {<img src="https://codeclimate.com/github/rubiety/validates_lengths_from_database.png" />}[https://codeclimate.com/github/rubiety/validates_lengths_from_database]
4
-
5
- == Validates Lengths from Database
6
-
7
- Few people add length validations to fields in their database, and when saving such fields that have exhausted their length, an SQL error occurs.
8
- This gem introspects your table schema for maximum lengths on string and text fields and automatically adds length validations to the model.
9
-
10
- == Requirements
11
-
12
- As of v0.5.0, validates_lengths_from_database lazily loads column information and requires Rails 3+. If you are using Rails 2, please use the v0.4.0 release.
13
-
14
- Due to issues maintaining backwards compatibility, as of v0.4.0 validates_lengths_from_database requires ruby 1.9.3 or higher.
15
- If you are still using 1.8.7 or 1.9.2, please use the v0.3.0 release.
16
-
17
- == Installation
18
-
19
- Include the gem using bundler in your Gemfile:
20
-
21
- gem "validates_lengths_from_database"
22
-
23
- == Usage
24
-
25
- In your model you can activate validations:
26
-
27
- class Post < ActiveRecord::Base
28
- validates_lengths_from_database
29
- end
30
-
31
- It also supports filter-style :only and :except options:
32
-
33
- class Post < ActiveRecord::Base
34
- validates_lengths_from_database :only => [:title, :contents]
35
- end
36
-
37
- class Post < ActiveRecord::Base
38
- validates_lengths_from_database :except => [:other_field]
39
- end
40
-
41
- If you'd rather specify the limits explicitly instead of pulling them from the database, you can set it:
42
-
43
- class Post < ActiveRecord::Base
44
- validates_lengths_from_database :limit => 255
45
- end
46
-
47
- Or to set the limit differently for string (VARCHAR) and (TEXT) columns:
48
-
49
- class Post < ActiveRecord::Base
50
- validates_lengths_from_database :limit => {:string => 255, :text => 4092}
51
- end
52
-
53
- Since v0.5.2, it's possible to use the `validate_lengths_from_database`
54
- on an abstract parent (without a table), such as +ApplicationRecord+ or <tt>ActiveRecord::Base</tt>.
55
-
56
- class ApplicationRecord < ActiveRecord::Base
57
- self.abstract_class = true
58
- validates_lengths_from_database :limit => 255
59
- end
60
-
61
- # This will use the validations with default options (from parent)
62
- class Post < ApplicationRecord
63
- end
64
-
65
- # This will use the validations, with overriding the default options (the limit will not be applied)
66
- class User < ApplicationRecord
67
- validates_lengths_from_database :only => [:name]
68
- end
69
-
70
- # This will use the validations, using the default options + adding some class specific customizations
71
- class Comment < ApplicationRecord
72
- validate_lengths_from_database_options[:only] << :name
73
- end
74
-
75
- == Running Tests
76
-
77
- This gem uses appraisal to test with different versions of the dependencies. See Appraisal first for which versions are tested.
78
-
79
- # Just the gems locked in Gemfile.lock
80
- $ rake test
81
-
82
- # All of the Appraisals:
83
- $ appraisal install
84
- $ appraisal rake test
85
-
data/Rakefile DELETED
@@ -1,24 +0,0 @@
1
- require 'rubygems'
2
- require 'bundler/setup'
3
-
4
- require 'rake'
5
- require 'rspec/core/rake_task'
6
-
7
- Bundler::GemHelper.install_tasks
8
-
9
- desc 'Default: run unit tests.'
10
- task :default => [:clean, :test]
11
-
12
- desc "Run Specs"
13
- RSpec::Core::RakeTask.new(:spec) do |t|
14
- end
15
-
16
- task :test => :spec
17
-
18
- desc "Clean up files."
19
- task :clean do |t|
20
- FileUtils.rm_rf "tmp"
21
- Dir.glob("spec/db/*.sqlite3").each {|f| FileUtils.rm f }
22
- Dir.glob("validates_lengths_from_database-*.gem").each {|f| FileUtils.rm f }
23
- end
24
-
data/init.rb DELETED
@@ -1,4 +0,0 @@
1
- require "validates_lengths_from_database"
2
-
3
- ValidatesLengthsFromDatabase::Railtie.insert
4
-
data/rails/init.rb DELETED
@@ -1,4 +0,0 @@
1
- require "validates_lengths_from_database"
2
-
3
- ValidatesLengthsFromDatabase::Railtie.insert
4
-
data/spec/db/database.yml DELETED
@@ -1,21 +0,0 @@
1
- sqlite:
2
- adapter: sqlite
3
- database: spec/db/test.sqlite
4
-
5
- sqlite3:
6
- adapter: sqlite3
7
- database: spec/db/test.sqlite3
8
-
9
- postgresql:
10
- adapter: postgresql
11
- username: postgres
12
- password: postgres
13
- database: has_draft_plugin_test
14
- min_messages: ERROR
15
-
16
- mysql:
17
- adapter: mysql
18
- host: localhost
19
- username: root
20
- password:
21
- database: has_draft_plugin_test
data/spec/db/schema.rb DELETED
@@ -1,38 +0,0 @@
1
- ActiveRecord::Schema.define(:version => 0) do
2
- create_table :articles, :force => true do |t|
3
- t.string :string_1, :limit => 5
4
- t.string :string_2, :limit => 5
5
-
6
- if postgresql?
7
- # PostgreSQL doesn't support limits on text columns
8
- t.text :text_1
9
- else
10
- t.text :text_1, :limit => 5
11
- end
12
-
13
- t.date :date_1
14
-
15
- t.integer :integer_1, :limit => 5
16
- t.decimal :decimal_1, :precision => 5, :scale => 2
17
- t.float :float_1, :limit => 5
18
-
19
- if database_supports_arrays?
20
- t.string :array_1, :array => true, :limit => 5
21
- end
22
- end
23
-
24
- create_table :articles_high_limit, :force => true do |t|
25
- t.string :string_1
26
- t.string :string_2
27
- t.text :text_1
28
- t.date :date_1
29
- t.integer :integer_1
30
- t.decimal :decimal_1, :precision => 11, :scale => 2
31
- t.float :float_1
32
-
33
- if database_supports_arrays?
34
- t.string :array_1, :array => true
35
- end
36
- end
37
- end
38
-
data/spec/db/test.sqlite3 DELETED
Binary file
data/spec/spec_helper.rb DELETED
@@ -1,27 +0,0 @@
1
- require "rubygems"
2
- require "rspec"
3
- require "active_record"
4
- require "active_support"
5
- require "yaml"
6
-
7
- # Establish DB Connection
8
- config = YAML::load(IO.read(File.join(File.dirname(__FILE__), 'db', 'database.yml')))
9
- ActiveRecord::Base.configurations = {'test' => config[ENV['DB'] || 'sqlite3']}
10
- ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])
11
-
12
- def database_supports_arrays?
13
- postgresql? && active_record_4?
14
- end
15
-
16
- def postgresql?
17
- ActiveRecord::Base.connection.instance_values["config"][:adapter] == 'postgresql'
18
- end
19
-
20
- def active_record_4?
21
- ActiveRecord::VERSION::MAJOR >= 4
22
- end
23
-
24
- # Load Test Schema into the Database
25
- load(File.dirname(__FILE__) + "/db/schema.rb")
26
-
27
- require File.dirname(__FILE__) + '/../init'
@@ -1,305 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe ValidatesLengthsFromDatabase do
4
-
5
- LONG_ATTRIBUTES = {
6
- :string_1 => "123456789",
7
- :string_2 => "123456789",
8
- :text_1 => "123456789",
9
- :date_1 => Date.today,
10
- :integer_1 => 123456789,
11
- :decimal_1 => 123456789.01,
12
- :float_1 => 123456789.01
13
- }
14
-
15
- SHORT_ATTRIBUTES = {
16
- :string_1 => "12",
17
- :string_2 => "12",
18
- :text_1 => "12",
19
- :date_1 => Date.today,
20
- :integer_1 => 123,
21
- :decimal_1 => 12.34,
22
- :float_1 => 12.34
23
- }
24
-
25
- before(:all) do
26
- ActiveSupport::Deprecation.silenced = true
27
- end
28
-
29
- class ApplicationRecord < ActiveRecord::Base
30
- self.abstract_class = true
31
- validates_lengths_from_database :limit => 255
32
- end
33
-
34
- context "Model without associated table" do
35
- specify "defining validates_lengths_from_database should not raise an error" do
36
- lambda {
37
- class InvalidTableArticle < ActiveRecord::Base
38
- self.table_name = "articles_invalid"
39
- validates_lengths_from_database
40
- end
41
- }.should_not raise_error
42
- end
43
- end
44
-
45
- context "Model without a table yet" do
46
- before do
47
- class LazyTableArticle < ActiveRecord::Base
48
- self.table_name = "articles_lazy"
49
- validates_lengths_from_database
50
- end
51
- end
52
-
53
- context "before the table is created" do
54
- specify "should fail to create records" do
55
- lambda { LazyTableArticle.new }.should raise_error
56
- end
57
- end
58
-
59
- context "after the table is created" do
60
- before do
61
- ActiveRecord::Schema.define do
62
- create_table :articles_lazy, :force => false do |t|
63
- t.string :string_1, :limit => 5
64
- end
65
- end
66
- end
67
-
68
- after do
69
- ActiveRecord::Schema.define do
70
- drop_table :articles_lazy
71
- end
72
- end
73
-
74
- context "an article with long attributes" do
75
- before { @article = LazyTableArticle.new(LONG_ATTRIBUTES.slice(:string_1)); @article.valid? }
76
-
77
- specify "should not be valid" do
78
- @article.should_not be_valid
79
- end
80
- end
81
-
82
- context "an article with short attributes" do
83
- before { @article = LazyTableArticle.new(SHORT_ATTRIBUTES.slice(:string_1)); @article.valid? }
84
-
85
- specify "should be valid" do
86
- @article.should be_valid
87
- end
88
- end
89
- end
90
- end
91
-
92
- context "Model without validates_lengths_from_database" do
93
- before do
94
- class ArticleValidateAll < ActiveRecord::Base
95
- self.table_name = "articles"
96
- end
97
- end
98
-
99
- context "an article with overloaded attributes" do
100
- before { @article = ArticleValidateAll.new(LONG_ATTRIBUTES); @article.valid? }
101
-
102
- it "should be valid" do
103
- @article.should be_valid
104
- end
105
- end
106
- end
107
-
108
- context "Model with validates_lengths_from_database" do
109
- before do
110
- class ArticleValidateAll < ActiveRecord::Base
111
- self.table_name = "articles"
112
- validates_lengths_from_database
113
- end
114
-
115
- class ArticleValidateText < ActiveRecord::Base
116
- self.table_name = "articles"
117
- validates_lengths_from_database :only => [:string_1]
118
- end
119
- end
120
-
121
- context "an article with overloaded attributes" do
122
- before { @article = ArticleValidateAll.new(LONG_ATTRIBUTES); @article.valid? }
123
-
124
- it "should not be valid" do
125
- @article.should_not be_valid
126
- end
127
-
128
- it "should have errors on all string/text attributes" do
129
- @article.errors["string_1"].join.should =~ /too long/
130
- @article.errors["string_2"].join.should =~ /too long/
131
- @article.errors["text_1"].join.should =~ /too long/ unless postgresql? # PostgreSQL doesn't support limits on text columns
132
- @article.errors["decimal_1"].join.should =~ /less than/
133
- end
134
- end
135
-
136
- context "inheritance" do
137
- before do
138
- class ArticleValidateChild < ApplicationRecord
139
- self.table_name = "articles"
140
- validates_lengths_from_database :only => [:string_1]
141
- end
142
- class ArticleValidateChildOverwrite < ArticleValidateChild
143
- validate_lengths_from_database_options[:only] << :string_2
144
- end
145
- class ArticleWithoutValidations < ApplicationRecord
146
- self.table_name = "articles"
147
- validates_lengths_from_database :only => []
148
- end
149
- end
150
-
151
- it "should inherit the validation options from the parent" do
152
- @article = ArticleValidateChild.new(LONG_ATTRIBUTES)
153
- @article.valid?
154
- @article.errors["string_1"].join.should =~ /too long/
155
- @article.errors["string_2"].join.should_not =~ /too long/
156
- end
157
-
158
- it "should allow changing the validation options of child" do
159
- @article = ArticleValidateChildOverwrite.new(LONG_ATTRIBUTES)
160
- @article.valid?
161
- @article.errors["string_1"].join.should =~ /too long/
162
- @article.errors["string_2"].join.should =~ /too long/
163
- end
164
- end
165
-
166
- context "an article with short attributes" do
167
- before { @article = ArticleValidateAll.new(SHORT_ATTRIBUTES); @article.valid? }
168
-
169
- it "should be valid" do
170
- @article.should be_valid
171
- end
172
- end
173
-
174
- if database_supports_arrays?
175
- context "an article with with string array attribute" do
176
- before { @article = ArticleValidateAll.new(:array_1 => %w(1 2 3 4 5 6 7 8 9 10)); @article.valid? }
177
-
178
- it "should be valid" do
179
- @article.should be_valid
180
- end
181
- end
182
- end
183
- end
184
-
185
- context "Model with validates_lengths_from_database :limit => 5" do
186
- before do
187
- class ArticleValidateLimit < ActiveRecord::Base
188
- self.table_name = "articles_high_limit"
189
- validates_lengths_from_database :limit => 5
190
- end
191
- end
192
-
193
- context "an article with overloaded attributes" do
194
- before { @article = ArticleValidateLimit.new(LONG_ATTRIBUTES); @article.valid? }
195
-
196
- it "should not be valid" do
197
- @article.should_not be_valid
198
- end
199
-
200
- it "should have errors on all string/text attributes" do
201
- @article.errors["string_1"].join.should =~ /too long/
202
- @article.errors["string_2"].join.should =~ /too long/
203
- @article.errors["text_1"].join.should =~ /too long/
204
- end
205
- end
206
-
207
- context "an article with short attributes" do
208
- before { @article = ArticleValidateLimit.new(SHORT_ATTRIBUTES); @article.valid? }
209
-
210
-
211
- it "should be valid" do
212
- @article.should be_valid
213
- end
214
- end
215
- end
216
-
217
- context "Model with validates_lengths_from_database :limit => {:string => 5, :text => 100}" do
218
- before do
219
- class ArticleValidateSpecificLimit < ActiveRecord::Base
220
- self.table_name = "articles_high_limit"
221
- validates_lengths_from_database :limit => {:string => 5, :text => 100}
222
- end
223
- end
224
-
225
- context "an article with overloaded attributes" do
226
- before { @article = ArticleValidateSpecificLimit.new(LONG_ATTRIBUTES); @article.valid? }
227
-
228
- it "should not be valid" do
229
- @article.should_not be_valid
230
- end
231
-
232
- it "should have errors on all string/text attributes" do
233
- @article.errors["string_1"].join.should =~ /too long/
234
- @article.errors["string_2"].join.should =~ /too long/
235
- @article.errors["text_1"].should_not be_present
236
- @article.errors["decimal_1"].should_not be_present
237
- end
238
- end
239
- end
240
-
241
- context "Model with validates_lengths_from_database :only => [:string_1, :text_1]" do
242
- before do
243
- class ArticleValidateOnly < ActiveRecord::Base
244
- self.table_name = "articles"
245
- validates_lengths_from_database :only => [:string_1, :text_1]
246
- end
247
- end
248
-
249
- context "an article with long attributes" do
250
- before { @article = ArticleValidateOnly.new(LONG_ATTRIBUTES); @article.valid? }
251
-
252
- it "should not be valid" do
253
- @article.should_not be_valid
254
- end
255
-
256
- it "should have errors on only string_1 and text_1" do
257
- @article.errors["string_1"].join.should =~ /too long/
258
- (@article.errors["string_2"] || []).should be_empty
259
- @article.errors["text_1"].join.should =~ /too long/ unless postgresql? # PostgreSQL doesn't support limits on text columns
260
- (@article.errors["decimal_1"] || []).should be_empty
261
- end
262
- end
263
-
264
- context "an article with short attributes" do
265
- before { @article = ArticleValidateOnly.new(SHORT_ATTRIBUTES); @article.valid? }
266
-
267
- it "should be valid" do
268
- @article.should be_valid
269
- end
270
- end
271
- end
272
-
273
- context "Model with validates_lengths_from_database :except => [:string_1, :text_1]" do
274
- before do
275
- class ArticleValidateExcept < ActiveRecord::Base
276
- self.table_name = "articles"
277
- validates_lengths_from_database :except => [:string_1, :text_1]
278
- end
279
- end
280
-
281
- context "an article with long attributes" do
282
- before { @article = ArticleValidateExcept.new(LONG_ATTRIBUTES); @article.valid? }
283
-
284
- it "should not be valid" do
285
- @article.should_not be_valid
286
- end
287
-
288
- it "should have errors on columns other than string_1 and text_1 only" do
289
- (@article.errors["string_1"] || []).should be_empty
290
- (@article.errors["text_1"] || []).should be_empty
291
- @article.errors["decimal_1"].join.should =~ /less than/
292
- @article.errors["string_2"].join.should =~ /too long/
293
- end
294
- end
295
-
296
- context "an article with short attributes" do
297
- before { @article = ArticleValidateOnly.new(SHORT_ATTRIBUTES); @article.valid? }
298
-
299
- it "should be valid" do
300
- @article.should be_valid
301
- end
302
- end
303
- end
304
-
305
- end