activerecord_mysql_strict 0.1 → 0.1.1
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.
- data/.travis.yml +11 -0
- data/README.md +12 -0
- data/activerecord_mysql_strict.gemspec +1 -0
- data/gemfiles/Gemfile.activerecord-3.2.x +5 -0
- data/gemfiles/Gemfile.activerecord-4.0 +5 -0
- data/lib/active_record/mysql/strict/mixin.rb +18 -8
- data/lib/active_record/mysql/strict/strict_length_validator.rb +28 -0
- data/lib/active_record/mysql/strict/version.rb +1 -1
- data/lib/activerecord_mysql_strict.rb +2 -0
- data/spec/activerecord_mysql_strict/mixin_spec.rb +27 -3
- metadata +24 -4
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# ActiveRecord::MySQL::Strict
|
2
2
|
|
3
3
|
[](https://rubygems.org/gems/activerecord_mysql_strict)
|
4
|
+
[](https://travis-ci.org/mirego/activerecord_mysql_strict)
|
4
5
|
|
5
6
|
`ActiveRecord::MySQL::Strict` adds validations to ActiveRecord models to make sure they do not trigger errors in MySQL strict mode.
|
6
7
|
|
@@ -17,6 +18,7 @@ gem 'activerecord_mysql_strict'
|
|
17
18
|
```ruby
|
18
19
|
create_table "events" do |t|
|
19
20
|
t.string "name"
|
21
|
+
t.string "email", limit: 128
|
20
22
|
t.text "description"
|
21
23
|
t.integer "people_count"
|
22
24
|
end
|
@@ -33,6 +35,12 @@ event.valid? # => false
|
|
33
35
|
event = Event.new(name: '.' * 255)
|
34
36
|
event.valid? # => true
|
35
37
|
|
38
|
+
event = Event.new(email: '.' * 200)
|
39
|
+
event.valid? # => false
|
40
|
+
|
41
|
+
event = Event.new(email: '.' * 100)
|
42
|
+
event.valid? # => true
|
43
|
+
|
36
44
|
# Text columns
|
37
45
|
|
38
46
|
event = Event.new(description: '.' * 70000)
|
@@ -64,6 +72,10 @@ class Event < ActiveRecord::Base
|
|
64
72
|
end
|
65
73
|
```
|
66
74
|
|
75
|
+
## Todo
|
76
|
+
|
77
|
+
* Support other MySQL column types that raise a `Mysql2::Error` exception when given a wrong value.
|
78
|
+
|
67
79
|
## License
|
68
80
|
|
69
81
|
`ActiveRecord::MySQL::Strict` is © 2013 [Mirego](http://www.mirego.com) and may be freely distributed under the [New BSD license](http://opensource.org/licenses/BSD-3-Clause). See the [`LICENSE.md`](https://github.com/mirego/activerecord_mysql_strict/blob/master/LICENSE.md) file.
|
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_dependency 'activerecord', '>= 3.0.0'
|
22
|
+
spec.add_dependency 'activemodel', '>= 3.0.0'
|
22
23
|
spec.add_dependency 'activesupport', '>= 3.0.0'
|
23
24
|
|
24
25
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
@@ -1,6 +1,11 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module MySQL
|
3
3
|
module Strict
|
4
|
+
# Constants
|
5
|
+
MYSQL_STRICT_STRING_LIMIT = 255
|
6
|
+
MYSQL_STRICT_TEXT_LIMIT = 65535
|
7
|
+
MYSQL_STRICT_INTEGER_LIMIT = 2147483647
|
8
|
+
|
4
9
|
module Mixin
|
5
10
|
extend ActiveSupport::Concern
|
6
11
|
|
@@ -17,17 +22,22 @@ module ActiveRecord
|
|
17
22
|
model_columns = model_columns.select { |c| only.include?(c.name.to_sym) }
|
18
23
|
end
|
19
24
|
|
20
|
-
model_columns.
|
21
|
-
|
25
|
+
model_columns.each do |field|
|
26
|
+
method = :"define_mysql_strict_#{field.type}_validation"
|
27
|
+
send(method, field) if respond_to?(method)
|
22
28
|
end
|
29
|
+
end
|
23
30
|
|
24
|
-
|
25
|
-
|
26
|
-
|
31
|
+
def define_mysql_strict_string_validation(field)
|
32
|
+
validates field.name, 'ActiveRecord::MySQL::Strict::StrictLength' => { in: 0..(field.limit || MYSQL_STRICT_STRING_LIMIT) }, allow_blank: true
|
33
|
+
end
|
27
34
|
|
28
|
-
|
29
|
-
|
30
|
-
|
35
|
+
def define_mysql_strict_text_validation(field)
|
36
|
+
validates field.name, 'ActiveRecord::MySQL::Strict::StrictLength' => { in: 0..(field.limit || MYSQL_STRICT_TEXT_LIMIT) }, allow_blank: true
|
37
|
+
end
|
38
|
+
|
39
|
+
def define_mysql_strict_integer_validation(field)
|
40
|
+
validates field.name, numericality: { greather_than_or_equal_to: -MYSQL_STRICT_INTEGER_LIMIT, less_than_or_equal_to: MYSQL_STRICT_INTEGER_LIMIT }, allow_blank: true
|
31
41
|
end
|
32
42
|
end
|
33
43
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module MySQL
|
3
|
+
module Strict
|
4
|
+
class StrictLengthValidator < ActiveModel::Validations::LengthValidator
|
5
|
+
def validate_each(record, attribute, value)
|
6
|
+
value = record.send(:read_attribute, attribute)
|
7
|
+
value_length = value.respond_to?(:length) ? value.length : value.to_s.length
|
8
|
+
errors_options = options.except(*RESERVED_OPTIONS)
|
9
|
+
|
10
|
+
CHECKS.each do |key, validity_check|
|
11
|
+
next unless check_value = options[key]
|
12
|
+
|
13
|
+
if !value.nil? || skip_nil_check?(key)
|
14
|
+
next if value_length.send(validity_check, check_value)
|
15
|
+
end
|
16
|
+
|
17
|
+
errors_options[:count] = check_value
|
18
|
+
|
19
|
+
default_message = options[MESSAGES[key]]
|
20
|
+
errors_options[:message] ||= default_message if default_message
|
21
|
+
|
22
|
+
record.errors.add(attribute, MESSAGES[key], errors_options)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,8 +1,10 @@
|
|
1
1
|
require 'active_record/mysql/strict/version'
|
2
2
|
|
3
3
|
require 'active_record'
|
4
|
+
require 'active_model'
|
4
5
|
require 'active_support'
|
5
6
|
|
7
|
+
require 'active_record/mysql/strict/strict_length_validator'
|
6
8
|
require 'active_record/mysql/strict/mixin'
|
7
9
|
|
8
10
|
class ActiveRecord::Base
|
@@ -115,9 +115,7 @@ describe ActiveRecord::MySQL::Strict::Mixin do
|
|
115
115
|
context 'for model with related validations' do
|
116
116
|
context 'for presence validation' do
|
117
117
|
let(:model) do
|
118
|
-
strict_model
|
119
|
-
validates :name, presence: true
|
120
|
-
end
|
118
|
+
strict_model('User') { validates :name, presence: true }
|
121
119
|
end
|
122
120
|
|
123
121
|
before do
|
@@ -130,5 +128,31 @@ describe ActiveRecord::MySQL::Strict::Mixin do
|
|
130
128
|
it { expect(subject.errors.full_messages).to eql ["Name can't be blank"] }
|
131
129
|
end
|
132
130
|
end
|
131
|
+
|
132
|
+
context 'for model with accessor that returns an invalid string' do
|
133
|
+
let(:model) do
|
134
|
+
strict_model 'User' do
|
135
|
+
attr_reader :long_name
|
136
|
+
|
137
|
+
# When we call `#long_name` it will return an invalid string but
|
138
|
+
# we want the attribute to store the real, valid value because we
|
139
|
+
# want to actually make sure that the real attribute value does
|
140
|
+
# not exceed the limit, not what the accessor returns.
|
141
|
+
define_method :long_name= do |value|
|
142
|
+
@long_name = '*' * 400
|
143
|
+
write_attribute(:long_name, value)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
before do
|
149
|
+
run_migration do
|
150
|
+
create_table(:users, force: true) { |t| t.string :long_name }
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
subject { model.new(long_name: '*' * 10) }
|
155
|
+
it { should be_valid }
|
156
|
+
end
|
133
157
|
end
|
134
158
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord_mysql_strict
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-08-
|
12
|
+
date: 2013-08-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -27,6 +27,22 @@ dependencies:
|
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: 3.0.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: activemodel
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 3.0.0
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 3.0.0
|
30
46
|
- !ruby/object:Gem::Dependency
|
31
47
|
name: activesupport
|
32
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -117,11 +133,15 @@ extra_rdoc_files: []
|
|
117
133
|
files:
|
118
134
|
- .gitignore
|
119
135
|
- .rspec
|
136
|
+
- .travis.yml
|
120
137
|
- Gemfile
|
121
138
|
- README.md
|
122
139
|
- Rakefile
|
123
140
|
- activerecord_mysql_strict.gemspec
|
141
|
+
- gemfiles/Gemfile.activerecord-3.2.x
|
142
|
+
- gemfiles/Gemfile.activerecord-4.0
|
124
143
|
- lib/active_record/mysql/strict/mixin.rb
|
144
|
+
- lib/active_record/mysql/strict/strict_length_validator.rb
|
125
145
|
- lib/active_record/mysql/strict/version.rb
|
126
146
|
- lib/activerecord_mysql_strict.rb
|
127
147
|
- spec/activerecord_mysql_strict/mixin_spec.rb
|
@@ -143,7 +163,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
143
163
|
version: '0'
|
144
164
|
segments:
|
145
165
|
- 0
|
146
|
-
hash: -
|
166
|
+
hash: -369873074256560002
|
147
167
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
148
168
|
none: false
|
149
169
|
requirements:
|
@@ -152,7 +172,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
152
172
|
version: '0'
|
153
173
|
segments:
|
154
174
|
- 0
|
155
|
-
hash: -
|
175
|
+
hash: -369873074256560002
|
156
176
|
requirements: []
|
157
177
|
rubyforge_project:
|
158
178
|
rubygems_version: 1.8.23
|