activerecord_strict_validations 0.3
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 +7 -0
- data/.gitignore +17 -0
- data/.rspec +1 -0
- data/.travis.yml +11 -0
- data/Gemfile +2 -0
- data/README.md +88 -0
- data/Rakefile +11 -0
- data/activerecord_strict_validations.gemspec +29 -0
- data/gemfiles/Gemfile.activerecord-3.2.x +5 -0
- data/gemfiles/Gemfile.activerecord-4.0 +5 -0
- data/lib/active_record/strict_validations/validation.rb +23 -0
- data/lib/active_record/strict_validations/validation/integer_validation.rb +14 -0
- data/lib/active_record/strict_validations/validation/string_validation.rb +13 -0
- data/lib/active_record/strict_validations/validation/text_validation.rb +13 -0
- data/lib/active_record/strict_validations/validator/strict_length_validator.rb +28 -0
- data/lib/active_record/strict_validations/version.rb +5 -0
- data/lib/activerecord_strict_validations.rb +22 -0
- data/spec/activerecord_mysql_strict/validation/integer_validation_spec.rb +27 -0
- data/spec/activerecord_mysql_strict/validation/string_validation_spec.rb +121 -0
- data/spec/activerecord_mysql_strict/validation/text_validation_spec.rb +50 -0
- data/spec/activerecord_mysql_strict/validation_spec.rb +7 -0
- data/spec/activerecord_mysql_strict_spec.rb +28 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/support/macros/database_macros.rb +33 -0
- data/spec/support/macros/model_macros.rb +19 -0
- metadata +176 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 4714739a02d45b4ed33e30786c6d9dc96f6a7e5b
|
|
4
|
+
data.tar.gz: 31541b254c1ac9db476c8ccf1206adb5d029cf82
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: c4ccfb4a2e7ee025663c70e11a4dacc62854f3f613af4f92e495d344489eb9b9fe4f5197c349482831015dd53e955693ac9598aeaee9b1957151b144c6d84252
|
|
7
|
+
data.tar.gz: 8029bfb1f18894b800dd8e600af411c4e936020a5d138152ff6c8c4244e632a7ecbb729329fd34d1b2c1ebfd2f4ff836051edc76b70369deac042be949623df5
|
data/.gitignore
ADDED
data/.rspec
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--colour
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# ActiveRecord::StrictValidations
|
|
2
|
+
|
|
3
|
+
[](https://rubygems.org/gems/activerecord_strict_validations)
|
|
4
|
+
[](https://codeclimate.com/github/mirego/activerecord_strict_validations)
|
|
5
|
+
[](https://travis-ci.org/mirego/activerecord_strict_validations)
|
|
6
|
+
|
|
7
|
+
`ActiveRecord::StrictValidations` adds validations to ActiveRecord models to make sure they do not trigger database errors.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
Add this line to your application's Gemfile:
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
gem 'activerecord_strict_validations'
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
create_table "events" do |t|
|
|
21
|
+
t.string "name"
|
|
22
|
+
t.string "email", limit: 128
|
|
23
|
+
t.text "description"
|
|
24
|
+
t.integer "people_count"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class Event < ActiveRecord::Base
|
|
28
|
+
validates_strict_columns
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# String columns
|
|
32
|
+
|
|
33
|
+
event = Event.new(name: '.' * 400)
|
|
34
|
+
event.valid? # => false
|
|
35
|
+
|
|
36
|
+
event = Event.new(name: '.' * 255)
|
|
37
|
+
event.valid? # => true
|
|
38
|
+
|
|
39
|
+
event = Event.new(email: '.' * 200)
|
|
40
|
+
event.valid? # => false
|
|
41
|
+
|
|
42
|
+
event = Event.new(email: '.' * 100)
|
|
43
|
+
event.valid? # => true
|
|
44
|
+
|
|
45
|
+
# Text columns
|
|
46
|
+
|
|
47
|
+
event = Event.new(description: '.' * 70000)
|
|
48
|
+
event.valid? # => false
|
|
49
|
+
|
|
50
|
+
event = Event.new(description: '.' * 65535)
|
|
51
|
+
event.valid? # => true
|
|
52
|
+
|
|
53
|
+
# Integer columns
|
|
54
|
+
|
|
55
|
+
event = Event.new(people_count: 9999999999)
|
|
56
|
+
event.valid? # => false
|
|
57
|
+
|
|
58
|
+
event = Event.new(people_count: 2147483647)
|
|
59
|
+
event.valid? # => true
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Options
|
|
63
|
+
|
|
64
|
+
You can use a few options when calling `validates_strict_columns`:
|
|
65
|
+
|
|
66
|
+
```ruby
|
|
67
|
+
class Event < ActiveRecord::Base
|
|
68
|
+
validates_strict_columns, only: [:name]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
class Event < ActiveRecord::Base
|
|
72
|
+
validates_strict_columns, except: [:people_count]
|
|
73
|
+
end
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Todo
|
|
77
|
+
|
|
78
|
+
* Support other database column types that raise an exception when given a wrong value.
|
|
79
|
+
|
|
80
|
+
## License
|
|
81
|
+
|
|
82
|
+
`ActiveRecord::StrictValidations` is © 2013-2014 [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_strict_validations/blob/master/LICENSE.md) file.
|
|
83
|
+
|
|
84
|
+
## About Mirego
|
|
85
|
+
|
|
86
|
+
[Mirego](http://mirego.com) is a team of passionate people who believe that work is a place where you can innovate and have fun. We're a team of [talented people](http://life.mirego.com) who imagine and build beautiful Web and mobile applications. We come together to share ideas and [change the world](http://mirego.org).
|
|
87
|
+
|
|
88
|
+
We also [love open-source software](http://open.mirego.com) and we try to give back to the community as much as we can.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'active_record/strict_validations/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = 'activerecord_strict_validations'
|
|
8
|
+
spec.version = ActiveRecord::StrictValidations::VERSION
|
|
9
|
+
spec.authors = ['Rémi Prévost']
|
|
10
|
+
spec.email = ['rprevost@mirego.com']
|
|
11
|
+
spec.description = 'ActiveRecord::StrictValidations adds validations to ActiveRecord models to make sure they do not trigger database errors.'
|
|
12
|
+
spec.summary = spec.description
|
|
13
|
+
spec.homepage = 'https://github.com/mirego/activerecord_strict_valications'
|
|
14
|
+
spec.license = 'BSD 3-Clause'
|
|
15
|
+
|
|
16
|
+
spec.files = `git ls-files`.split($/)
|
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
|
+
spec.require_paths = ["lib"]
|
|
20
|
+
|
|
21
|
+
spec.add_dependency 'activerecord', '>= 3.0.0'
|
|
22
|
+
spec.add_dependency 'activemodel', '>= 3.0.0'
|
|
23
|
+
spec.add_dependency 'activesupport', '>= 3.0.0'
|
|
24
|
+
|
|
25
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
|
26
|
+
spec.add_development_dependency 'rspec', '~> 2.14'
|
|
27
|
+
spec.add_development_dependency 'rake'
|
|
28
|
+
spec.add_development_dependency 'sqlite3'
|
|
29
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module ActiveRecord
|
|
2
|
+
module StrictValidations
|
|
3
|
+
class Validation < Struct.new(:model, :field)
|
|
4
|
+
# Inject validations into an ActiveRecord model
|
|
5
|
+
def self.inject_validations(model, options = {})
|
|
6
|
+
except = options[:except] || []
|
|
7
|
+
model_columns = model.columns.dup.reject { |c| except.include?(c.name.to_sym) }
|
|
8
|
+
|
|
9
|
+
if only = options[:only]
|
|
10
|
+
model_columns = model_columns.select { |c| only.include?(c.name.to_sym) }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
model_columns.each do |field|
|
|
14
|
+
validation = "#{field.type.to_s.camelize}Validation"
|
|
15
|
+
|
|
16
|
+
if ActiveRecord::StrictValidations::Validation.const_defined?(validation)
|
|
17
|
+
"ActiveRecord::StrictValidations::Validation::#{validation}".constantize.new(model, field).apply
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module ActiveRecord
|
|
2
|
+
module Strict
|
|
3
|
+
class Validation
|
|
4
|
+
class IntegerValidation < Validation
|
|
5
|
+
UPPER_LIMIT = 2147483647
|
|
6
|
+
LOWER_LIMIT = -2147483647
|
|
7
|
+
|
|
8
|
+
def apply
|
|
9
|
+
model.validates field.name, numericality: { greather_than_or_equal_to: LOWER_LIMIT, less_than_or_equal_to: UPPER_LIMIT }, allow_blank: true
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module ActiveRecord
|
|
2
|
+
module Strict
|
|
3
|
+
class Validation
|
|
4
|
+
class StringValidation < Validation
|
|
5
|
+
LIMIT = 255
|
|
6
|
+
|
|
7
|
+
def apply
|
|
8
|
+
model.validates field.name, 'ActiveRecord::StrictValidations::Validator::StrictLength' => { in: 0..(field.limit || LIMIT) }, allow_blank: true
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module ActiveRecord
|
|
2
|
+
module StrictValidations
|
|
3
|
+
class Validation
|
|
4
|
+
class TextValidation < Validation
|
|
5
|
+
LIMIT = 65535
|
|
6
|
+
|
|
7
|
+
def apply
|
|
8
|
+
model.validates field.name, 'ActiveRecord::StrictValidations::Validator::StrictLength' => { in: 0..(field.limit || LIMIT) }, allow_blank: true
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module ActiveRecord
|
|
2
|
+
module StrictValidations
|
|
3
|
+
module Validator
|
|
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
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require 'active_record/strict_validations/version'
|
|
2
|
+
|
|
3
|
+
require 'active_record'
|
|
4
|
+
require 'active_model'
|
|
5
|
+
require 'active_support'
|
|
6
|
+
|
|
7
|
+
# Validators
|
|
8
|
+
require 'active_record/strict_validations/validator/strict_length_validator'
|
|
9
|
+
|
|
10
|
+
# Validations
|
|
11
|
+
require 'active_record/strict_validations/validation'
|
|
12
|
+
require 'active_record/strict_validations/validation/string_validation'
|
|
13
|
+
require 'active_record/strict_validations/validation/text_validation'
|
|
14
|
+
require 'active_record/strict_validations/validation/integer_validation'
|
|
15
|
+
|
|
16
|
+
class ActiveRecord::Base
|
|
17
|
+
def self.validates_strict_columns(options = {})
|
|
18
|
+
if table_exists?
|
|
19
|
+
ActiveRecord::StrictValidations::Validation.inject_validations(self, options)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe ActiveRecord::StrictValidations::Validation::IntegerValidation do
|
|
4
|
+
describe :apply do
|
|
5
|
+
context 'for model without other validations' do
|
|
6
|
+
let(:model) { strict_model 'User' }
|
|
7
|
+
|
|
8
|
+
context 'with field with default limit' do
|
|
9
|
+
before do
|
|
10
|
+
run_migration do
|
|
11
|
+
create_table(:users, force: true) { |t| t.integer :number }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
context 'with field value exceeding limit' do
|
|
16
|
+
subject { model.new(number: 9999999999) }
|
|
17
|
+
it { should_not be_valid }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context 'with field value not exceeding limit' do
|
|
21
|
+
subject { model.new(number: 2147483647) }
|
|
22
|
+
it { should be_valid }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe ActiveRecord::StrictValidations::Validation::StringValidation do
|
|
4
|
+
describe :apply do
|
|
5
|
+
context 'for model without other validations' do
|
|
6
|
+
let(:model) { strict_model 'User' }
|
|
7
|
+
|
|
8
|
+
context 'with field with default limit' do
|
|
9
|
+
before do
|
|
10
|
+
run_migration do
|
|
11
|
+
create_table(:users, force: true) { |t| t.string :name }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
context 'with field value exceeding limit' do
|
|
16
|
+
subject { model.new(name: '*' * 400) }
|
|
17
|
+
it { should_not be_valid }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context 'with field value not exceeding limit' do
|
|
21
|
+
subject { model.new(name: '*' * 100) }
|
|
22
|
+
it { should be_valid }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context 'with field with custom limit' do
|
|
27
|
+
before do
|
|
28
|
+
run_migration do
|
|
29
|
+
create_table(:users, force: true) { |t| t.string :name, limit: 128 }
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
context 'with field value exceeding default limit' do
|
|
34
|
+
subject { model.new(name: '*' * 400) }
|
|
35
|
+
it { should_not be_valid }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
context 'with field value exceeding custom limit' do
|
|
39
|
+
subject { model.new(name: '*' * 140) }
|
|
40
|
+
it { should_not be_valid }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context 'with field value not exceeding custom limit' do
|
|
44
|
+
subject { model.new(name: '*' * 120) }
|
|
45
|
+
it { should be_valid }
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context 'for model with related validations' do
|
|
51
|
+
context 'for presence validation' do
|
|
52
|
+
let(:model) do
|
|
53
|
+
strict_model('User') { validates :name, presence: true }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
before do
|
|
57
|
+
run_migration do
|
|
58
|
+
create_table(:users, force: true) { |t| t.string :name }
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
subject { model.new.tap(&:valid?) }
|
|
63
|
+
it { expect(subject.errors.full_messages).to eql ["Name can't be blank"] }
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context 'for valid model with accessor that returns an invalid string' do
|
|
68
|
+
let(:model) do
|
|
69
|
+
strict_model 'User' do
|
|
70
|
+
attr_reader :long_name
|
|
71
|
+
|
|
72
|
+
# When we call `#long_name` it will return an invalid string but
|
|
73
|
+
# we want the attribute to store the real, valid value because we
|
|
74
|
+
# want to actually make sure that the real attribute value does
|
|
75
|
+
# not exceed the limit, not what the accessor returns.
|
|
76
|
+
define_method :long_name= do |value|
|
|
77
|
+
@long_name = '*' * 400
|
|
78
|
+
write_attribute(:long_name, value)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
before do
|
|
84
|
+
run_migration do
|
|
85
|
+
create_table(:users, force: true) { |t| t.string :long_name }
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
subject { model.new(long_name: '*' * 10) }
|
|
90
|
+
its(:long_name) { should eql '*' * 400 }
|
|
91
|
+
it { should be_valid }
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
context 'for invalid model with accessor that returns a valid string' do
|
|
95
|
+
let(:model) do
|
|
96
|
+
strict_model 'User' do
|
|
97
|
+
attr_reader :short_name
|
|
98
|
+
|
|
99
|
+
# When we call `#short_name` it will return a valid string but
|
|
100
|
+
# we want the attribute to store the real, valid value because we
|
|
101
|
+
# want to actually make sure that the real attribute value does
|
|
102
|
+
# exceed the limit, not what the accessor returns.
|
|
103
|
+
define_method :short_name= do |value|
|
|
104
|
+
@short_name = '*' * 100
|
|
105
|
+
write_attribute(:short_name, value)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
before do
|
|
111
|
+
run_migration do
|
|
112
|
+
create_table(:users, force: true) { |t| t.string :short_name }
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
subject { model.new(short_name: '*' * 400) }
|
|
117
|
+
its(:short_name) { should eql '*' * 100 }
|
|
118
|
+
it { should_not be_valid }
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe ActiveRecord::StrictValidations::Validation::TextValidation do
|
|
4
|
+
describe :apply do
|
|
5
|
+
context 'for model without other validations' do
|
|
6
|
+
let(:model) { strict_model 'User' }
|
|
7
|
+
|
|
8
|
+
context 'with field with default limit' do
|
|
9
|
+
before do
|
|
10
|
+
run_migration do
|
|
11
|
+
create_table(:users, force: true) { |t| t.text :bio }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
context 'with field value exceeding limit' do
|
|
16
|
+
subject { model.new(bio: '*' * 70000) }
|
|
17
|
+
it { should_not be_valid }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context 'with field value not exceeding limit' do
|
|
21
|
+
subject { model.new(bio: '*' * 4000) }
|
|
22
|
+
it { should be_valid }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context 'with field with custom limit' do
|
|
27
|
+
before do
|
|
28
|
+
run_migration do
|
|
29
|
+
create_table(:users, force: true) { |t| t.text :bio, limit: 10000 }
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
context 'with field value exceeding default limit' do
|
|
34
|
+
subject { model.new(bio: '*' * 70000) }
|
|
35
|
+
it { should_not be_valid }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
context 'with field value exceeding custom limit' do
|
|
39
|
+
subject { model.new(bio: '*' * 12000) }
|
|
40
|
+
it { should_not be_valid }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context 'with field value not exceeding custom limit' do
|
|
44
|
+
subject { model.new(bio: '*' * 4000) }
|
|
45
|
+
it { should be_valid }
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe ActiveRecord::StrictValidations do
|
|
4
|
+
describe :validates_strict_columns do
|
|
5
|
+
before do
|
|
6
|
+
spawn_model 'User'
|
|
7
|
+
run_migration do
|
|
8
|
+
create_table(:users, force: true) { |t| t.string :name }
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
context 'without options' do
|
|
13
|
+
before do
|
|
14
|
+
expect(ActiveRecord::StrictValidations::Validation).to receive(:inject_validations).with(User, {})
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it { User.validates_strict_columns }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context 'with options' do
|
|
21
|
+
before do
|
|
22
|
+
expect(ActiveRecord::StrictValidations::Validation).to receive(:inject_validations).with(User, { except: [:bar], only: [:foo] })
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it { User.validates_strict_columns except: [:bar], only: [:foo] }
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
$:.unshift File.expand_path('../lib', __FILE__)
|
|
2
|
+
|
|
3
|
+
require 'rspec'
|
|
4
|
+
require 'sqlite3'
|
|
5
|
+
|
|
6
|
+
require 'activerecord_strict_validations'
|
|
7
|
+
|
|
8
|
+
# Require our macros and extensions
|
|
9
|
+
Dir[File.expand_path('../../spec/support/macros/*.rb', __FILE__)].map(&method(:require))
|
|
10
|
+
|
|
11
|
+
RSpec.configure do |config|
|
|
12
|
+
# Include our macros
|
|
13
|
+
config.include DatabaseMacros
|
|
14
|
+
config.include ModelMacros
|
|
15
|
+
|
|
16
|
+
config.before(:each) do
|
|
17
|
+
# Create the SQLite database
|
|
18
|
+
setup_database
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
config.after(:each) do
|
|
22
|
+
# Make sure we remove our test database file
|
|
23
|
+
cleanup_database
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module DatabaseMacros
|
|
2
|
+
# Run migrations in the test database
|
|
3
|
+
def run_migration(&block)
|
|
4
|
+
# Create a new migration class
|
|
5
|
+
klass = Class.new(ActiveRecord::Migration)
|
|
6
|
+
|
|
7
|
+
# Create a new `up` that executes the argument
|
|
8
|
+
klass.send(:define_method, :up) { self.instance_exec(&block) }
|
|
9
|
+
|
|
10
|
+
# Create a new instance of it and execute its `up` method
|
|
11
|
+
klass.new.up
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.database_file
|
|
15
|
+
@database_file || File.expand_path('../test.db', __FILE__)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def setup_database
|
|
19
|
+
# Make sure the test database file is gone
|
|
20
|
+
cleanup_database
|
|
21
|
+
|
|
22
|
+
# Establish the connection
|
|
23
|
+
SQLite3::Database.new FileUtils.touch(DatabaseMacros.database_file).first
|
|
24
|
+
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: DatabaseMacros.database_file)
|
|
25
|
+
|
|
26
|
+
# Silence everything
|
|
27
|
+
ActiveRecord::Base.logger = ActiveRecord::Migration.verbose = false
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def cleanup_database
|
|
31
|
+
FileUtils.rm(DatabaseMacros.database_file) if File.exists?(DatabaseMacros.database_file)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module ModelMacros
|
|
2
|
+
# Create a new model
|
|
3
|
+
def strict_model(klass_name, options = {}, &block)
|
|
4
|
+
spawn_model klass_name do
|
|
5
|
+
validates_strict_columns options
|
|
6
|
+
instance_exec(&block) if block
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
protected
|
|
11
|
+
|
|
12
|
+
# Create a new model class
|
|
13
|
+
def spawn_model(klass_name, parent_klass = ActiveRecord::Base, &block)
|
|
14
|
+
Object.instance_eval { remove_const klass_name } if Object.const_defined?(klass_name)
|
|
15
|
+
Object.const_set(klass_name, Class.new(parent_klass))
|
|
16
|
+
Object.const_get(klass_name).class_eval(&block) if block_given?
|
|
17
|
+
Object.const_get(klass_name)
|
|
18
|
+
end
|
|
19
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: activerecord_strict_validations
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: '0.3'
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Rémi Prévost
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2014-04-04 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: activerecord
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - '>='
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 3.0.0
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - '>='
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 3.0.0
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: activemodel
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - '>='
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 3.0.0
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - '>='
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: 3.0.0
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: activesupport
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - '>='
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: 3.0.0
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - '>='
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: 3.0.0
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: bundler
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ~>
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '1.3'
|
|
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'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: rspec
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ~>
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '2.14'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ~>
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '2.14'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: rake
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - '>='
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - '>='
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: sqlite3
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - '>='
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0'
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - '>='
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '0'
|
|
111
|
+
description: ActiveRecord::StrictValidations adds validations to ActiveRecord models
|
|
112
|
+
to make sure they do not trigger database errors.
|
|
113
|
+
email:
|
|
114
|
+
- rprevost@mirego.com
|
|
115
|
+
executables: []
|
|
116
|
+
extensions: []
|
|
117
|
+
extra_rdoc_files: []
|
|
118
|
+
files:
|
|
119
|
+
- .gitignore
|
|
120
|
+
- .rspec
|
|
121
|
+
- .travis.yml
|
|
122
|
+
- Gemfile
|
|
123
|
+
- README.md
|
|
124
|
+
- Rakefile
|
|
125
|
+
- activerecord_strict_validations.gemspec
|
|
126
|
+
- gemfiles/Gemfile.activerecord-3.2.x
|
|
127
|
+
- gemfiles/Gemfile.activerecord-4.0
|
|
128
|
+
- lib/active_record/strict_validations/validation.rb
|
|
129
|
+
- lib/active_record/strict_validations/validation/integer_validation.rb
|
|
130
|
+
- lib/active_record/strict_validations/validation/string_validation.rb
|
|
131
|
+
- lib/active_record/strict_validations/validation/text_validation.rb
|
|
132
|
+
- lib/active_record/strict_validations/validator/strict_length_validator.rb
|
|
133
|
+
- lib/active_record/strict_validations/version.rb
|
|
134
|
+
- lib/activerecord_strict_validations.rb
|
|
135
|
+
- spec/activerecord_mysql_strict/validation/integer_validation_spec.rb
|
|
136
|
+
- spec/activerecord_mysql_strict/validation/string_validation_spec.rb
|
|
137
|
+
- spec/activerecord_mysql_strict/validation/text_validation_spec.rb
|
|
138
|
+
- spec/activerecord_mysql_strict/validation_spec.rb
|
|
139
|
+
- spec/activerecord_mysql_strict_spec.rb
|
|
140
|
+
- spec/spec_helper.rb
|
|
141
|
+
- spec/support/macros/database_macros.rb
|
|
142
|
+
- spec/support/macros/model_macros.rb
|
|
143
|
+
homepage: https://github.com/mirego/activerecord_strict_valications
|
|
144
|
+
licenses:
|
|
145
|
+
- BSD 3-Clause
|
|
146
|
+
metadata: {}
|
|
147
|
+
post_install_message:
|
|
148
|
+
rdoc_options: []
|
|
149
|
+
require_paths:
|
|
150
|
+
- lib
|
|
151
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
152
|
+
requirements:
|
|
153
|
+
- - '>='
|
|
154
|
+
- !ruby/object:Gem::Version
|
|
155
|
+
version: '0'
|
|
156
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
157
|
+
requirements:
|
|
158
|
+
- - '>='
|
|
159
|
+
- !ruby/object:Gem::Version
|
|
160
|
+
version: '0'
|
|
161
|
+
requirements: []
|
|
162
|
+
rubyforge_project:
|
|
163
|
+
rubygems_version: 2.1.0
|
|
164
|
+
signing_key:
|
|
165
|
+
specification_version: 4
|
|
166
|
+
summary: ActiveRecord::StrictValidations adds validations to ActiveRecord models to
|
|
167
|
+
make sure they do not trigger database errors.
|
|
168
|
+
test_files:
|
|
169
|
+
- spec/activerecord_mysql_strict/validation/integer_validation_spec.rb
|
|
170
|
+
- spec/activerecord_mysql_strict/validation/string_validation_spec.rb
|
|
171
|
+
- spec/activerecord_mysql_strict/validation/text_validation_spec.rb
|
|
172
|
+
- spec/activerecord_mysql_strict/validation_spec.rb
|
|
173
|
+
- spec/activerecord_mysql_strict_spec.rb
|
|
174
|
+
- spec/spec_helper.rb
|
|
175
|
+
- spec/support/macros/database_macros.rb
|
|
176
|
+
- spec/support/macros/model_macros.rb
|