activerecord_mysql_strict 0.0.1 → 0.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/.rspec +1 -0
- data/README.md +72 -0
- data/Rakefile +11 -1
- data/activerecord_mysql_strict.gemspec +2 -0
- data/lib/active_record/mysql/strict/mixin.rb +33 -2
- data/lib/active_record/mysql/strict/version.rb +1 -1
- data/lib/activerecord_mysql_strict.rb +13 -0
- data/spec/activerecord_mysql_strict/mixin_spec.rb +134 -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 +46 -5
- data/lib/active_record_mysql_strict.rb +0 -6
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/README.md
CHANGED
@@ -1,3 +1,75 @@
|
|
1
1
|
# ActiveRecord::MySQL::Strict
|
2
2
|
|
3
|
+
[](https://rubygems.org/gems/activerecord_mysql_strict)
|
4
|
+
|
3
5
|
`ActiveRecord::MySQL::Strict` adds validations to ActiveRecord models to make sure they do not trigger errors in MySQL strict mode.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'activerecord_mysql_strict'
|
13
|
+
```
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
create_table "events" do |t|
|
19
|
+
t.string "name"
|
20
|
+
t.text "description"
|
21
|
+
t.integer "people_count"
|
22
|
+
end
|
23
|
+
|
24
|
+
class Event < ActiveRecord::Base
|
25
|
+
validates_strict_columns
|
26
|
+
end
|
27
|
+
|
28
|
+
# String columns
|
29
|
+
|
30
|
+
event = Event.new(name: '.' * 400)
|
31
|
+
event.valid? # => false
|
32
|
+
|
33
|
+
event = Event.new(name: '.' * 255)
|
34
|
+
event.valid? # => true
|
35
|
+
|
36
|
+
# Text columns
|
37
|
+
|
38
|
+
event = Event.new(description: '.' * 70000)
|
39
|
+
event.valid? # => false
|
40
|
+
|
41
|
+
event = Event.new(description: '.' * 65535)
|
42
|
+
event.valid? # => true
|
43
|
+
|
44
|
+
# Integer columns
|
45
|
+
|
46
|
+
event = Event.new(people_count: 9999999999)
|
47
|
+
event.valid? # => false
|
48
|
+
|
49
|
+
event = Event.new(people_count: 2147483647)
|
50
|
+
event.valid? # => true
|
51
|
+
```
|
52
|
+
|
53
|
+
### Options
|
54
|
+
|
55
|
+
You can use a few options when calling `validates_strict_columns`:
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
class Event < ActiveRecord::Base
|
59
|
+
validates_strict_columns, only: [:name]
|
60
|
+
end
|
61
|
+
|
62
|
+
class Event < ActiveRecord::Base
|
63
|
+
validates_strict_columns, except: [:people_count]
|
64
|
+
end
|
65
|
+
```
|
66
|
+
|
67
|
+
## License
|
68
|
+
|
69
|
+
`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.
|
70
|
+
|
71
|
+
## About Mirego
|
72
|
+
|
73
|
+
Mirego is a team of passionate people who believe that work is a place where you can innovate and have fun. We proudly build mobile applications for [iPhone](http://mirego.com/en/iphone-app-development/ "iPhone application development"), [iPad](http://mirego.com/en/ipad-app-development/ "iPad application development"), [Android](http://mirego.com/en/android-app-development/ "Android application development"), [Blackberry](http://mirego.com/en/blackberry-app-development/ "Blackberry application development"), [Windows Phone](http://mirego.com/en/windows-phone-app-development/ "Windows Phone application development") and [Windows 8](http://mirego.com/en/windows-8-app-development/ "Windows 8 application development") in beautiful Quebec City.
|
74
|
+
|
75
|
+
We also love [open-source software](http://open.mirego.com/) and we try to extract as much code as possible from our projects to give back to the community.
|
data/Rakefile
CHANGED
@@ -1 +1,11 @@
|
|
1
|
-
require
|
1
|
+
require 'bundler'
|
2
|
+
require 'rake'
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
task default: :spec
|
7
|
+
|
8
|
+
desc 'Run all specs'
|
9
|
+
RSpec::Core::RakeTask.new(:spec) do |task|
|
10
|
+
task.pattern = 'spec/**/*_spec.rb'
|
11
|
+
end
|
@@ -22,5 +22,7 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_dependency 'activesupport', '>= 3.0.0'
|
23
23
|
|
24
24
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
25
|
+
spec.add_development_dependency 'rspec', '~> 2.14'
|
25
26
|
spec.add_development_dependency 'rake'
|
27
|
+
spec.add_development_dependency 'sqlite3'
|
26
28
|
end
|
@@ -1,5 +1,36 @@
|
|
1
1
|
module ActiveRecord
|
2
|
-
module
|
3
|
-
|
2
|
+
module MySQL
|
3
|
+
module Strict
|
4
|
+
module Mixin
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
define_mysql_strict_validations
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
def define_mysql_strict_validations
|
13
|
+
except = @mysql_strict_options[:except] || []
|
14
|
+
model_columns = self.columns.dup.reject { |c| except.include?(c.name.to_sym) }
|
15
|
+
|
16
|
+
if only = @mysql_strict_options[:only]
|
17
|
+
model_columns = model_columns.select { |c| only.include?(c.name.to_sym) }
|
18
|
+
end
|
19
|
+
|
20
|
+
model_columns.select { |c| c.type == :string }.each do |field|
|
21
|
+
validates field.name, length: { in: 0..(field.limit || 255) }, allow_blank: true
|
22
|
+
end
|
23
|
+
|
24
|
+
model_columns.select { |c| c.type == :text }.each do |field|
|
25
|
+
validates field.name, length: { in: 0..(field.limit || 65535) }, allow_blank: true
|
26
|
+
end
|
27
|
+
|
28
|
+
model_columns.select { |c| c.type == :integer }.each do |field|
|
29
|
+
validates field.name, numericality: { greather_than_or_equal_to: -2147483647, less_than_or_equal_to: 2147483647 }, allow_blank: true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
4
35
|
end
|
5
36
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'active_record/mysql/strict/version'
|
2
|
+
|
3
|
+
require 'active_record'
|
4
|
+
require 'active_support'
|
5
|
+
|
6
|
+
require 'active_record/mysql/strict/mixin'
|
7
|
+
|
8
|
+
class ActiveRecord::Base
|
9
|
+
def self.validates_strict_columns(options = {})
|
10
|
+
@mysql_strict_options = options
|
11
|
+
include ActiveRecord::MySQL::Strict::Mixin
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveRecord::MySQL::Strict::Mixin do
|
4
|
+
describe :validates_strict_columns do
|
5
|
+
context 'for model without other validations' do
|
6
|
+
let(:model) { strict_model 'User' }
|
7
|
+
|
8
|
+
context 'for `string` columns' do
|
9
|
+
context 'with field with default limit' do
|
10
|
+
before do
|
11
|
+
run_migration do
|
12
|
+
create_table(:users, force: true) { |t| t.string :name }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'with field value exceeding limit' do
|
17
|
+
subject { model.new(name: '*' * 400) }
|
18
|
+
it { should_not be_valid }
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'with field value not exceeding limit' do
|
22
|
+
subject { model.new(name: '*' * 100) }
|
23
|
+
it { should be_valid }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'with field with custom limit' do
|
28
|
+
before do
|
29
|
+
run_migration do
|
30
|
+
create_table(:users, force: true) { |t| t.string :name, limit: 128 }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'with field value exceeding default limit' do
|
35
|
+
subject { model.new(name: '*' * 400) }
|
36
|
+
it { should_not be_valid }
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'with field value exceeding custom limit' do
|
40
|
+
subject { model.new(name: '*' * 140) }
|
41
|
+
it { should_not be_valid }
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'with field value not exceeding custom limit' do
|
45
|
+
subject { model.new(name: '*' * 120) }
|
46
|
+
it { should be_valid }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'for `text` columns' do
|
52
|
+
context 'with field with default limit' do
|
53
|
+
before do
|
54
|
+
run_migration do
|
55
|
+
create_table(:users, force: true) { |t| t.text :bio }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'with field value exceeding limit' do
|
60
|
+
subject { model.new(bio: '*' * 70000) }
|
61
|
+
it { should_not be_valid }
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'with field value not exceeding limit' do
|
65
|
+
subject { model.new(bio: '*' * 4000) }
|
66
|
+
it { should be_valid }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'with field with custom limit' do
|
71
|
+
before do
|
72
|
+
run_migration do
|
73
|
+
create_table(:users, force: true) { |t| t.text :bio, limit: 10000 }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'with field value exceeding default limit' do
|
78
|
+
subject { model.new(bio: '*' * 70000) }
|
79
|
+
it { should_not be_valid }
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'with field value exceeding custom limit' do
|
83
|
+
subject { model.new(bio: '*' * 12000) }
|
84
|
+
it { should_not be_valid }
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'with field value not exceeding custom limit' do
|
88
|
+
subject { model.new(bio: '*' * 4000) }
|
89
|
+
it { should be_valid }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'for `integer` columns' do
|
95
|
+
context 'with field with default limit' do
|
96
|
+
before do
|
97
|
+
run_migration do
|
98
|
+
create_table(:users, force: true) { |t| t.integer :number }
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context 'with field value exceeding limit' do
|
103
|
+
subject { model.new(number: 9999999999) }
|
104
|
+
it { should_not be_valid }
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'with field value not exceeding limit' do
|
108
|
+
subject { model.new(number: 2147483647) }
|
109
|
+
it { should be_valid }
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context 'for model with related validations' do
|
116
|
+
context 'for presence validation' do
|
117
|
+
let(:model) do
|
118
|
+
strict_model 'User' do
|
119
|
+
validates :name, presence: true
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
before do
|
124
|
+
run_migration do
|
125
|
+
create_table(:users, force: true) { |t| t.string :name }
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
subject { model.new.tap(&:valid?) }
|
130
|
+
it { expect(subject.errors.full_messages).to eql ["Name can't be blank"] }
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
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_mysql_strict'
|
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 microscope model
|
3
|
+
def strict_model(klass_name, options = {}, &block)
|
4
|
+
spawn_model klass_name, ActiveRecord::Base 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, &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
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: 0.
|
4
|
+
version: '0.1'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -59,6 +59,22 @@ dependencies:
|
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '1.3'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rspec
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '2.14'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '2.14'
|
62
78
|
- !ruby/object:Gem::Dependency
|
63
79
|
name: rake
|
64
80
|
requirement: !ruby/object:Gem::Requirement
|
@@ -75,6 +91,22 @@ dependencies:
|
|
75
91
|
- - ! '>='
|
76
92
|
- !ruby/object:Gem::Version
|
77
93
|
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: sqlite3
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
78
110
|
description: ActiveRecord::MySQL::Strict adds validations to ActiveRecord models to
|
79
111
|
make sure they do not trigger errors in MySQL strict mode.
|
80
112
|
email:
|
@@ -84,13 +116,18 @@ extensions: []
|
|
84
116
|
extra_rdoc_files: []
|
85
117
|
files:
|
86
118
|
- .gitignore
|
119
|
+
- .rspec
|
87
120
|
- Gemfile
|
88
121
|
- README.md
|
89
122
|
- Rakefile
|
90
123
|
- activerecord_mysql_strict.gemspec
|
91
124
|
- lib/active_record/mysql/strict/mixin.rb
|
92
125
|
- lib/active_record/mysql/strict/version.rb
|
93
|
-
- lib/
|
126
|
+
- lib/activerecord_mysql_strict.rb
|
127
|
+
- spec/activerecord_mysql_strict/mixin_spec.rb
|
128
|
+
- spec/spec_helper.rb
|
129
|
+
- spec/support/macros/database_macros.rb
|
130
|
+
- spec/support/macros/model_macros.rb
|
94
131
|
homepage: https://github.com/mirego/activerecord_mysql_strict
|
95
132
|
licenses:
|
96
133
|
- BSD 3-Clause
|
@@ -106,7 +143,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
106
143
|
version: '0'
|
107
144
|
segments:
|
108
145
|
- 0
|
109
|
-
hash: -
|
146
|
+
hash: -412845040514754438
|
110
147
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
148
|
none: false
|
112
149
|
requirements:
|
@@ -115,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
115
152
|
version: '0'
|
116
153
|
segments:
|
117
154
|
- 0
|
118
|
-
hash: -
|
155
|
+
hash: -412845040514754438
|
119
156
|
requirements: []
|
120
157
|
rubyforge_project:
|
121
158
|
rubygems_version: 1.8.23
|
@@ -123,4 +160,8 @@ signing_key:
|
|
123
160
|
specification_version: 3
|
124
161
|
summary: ActiveRecord::MySQL::Strict adds validations to ActiveRecord models to make
|
125
162
|
sure they do not trigger errors in MySQL strict mode.
|
126
|
-
test_files:
|
163
|
+
test_files:
|
164
|
+
- spec/activerecord_mysql_strict/mixin_spec.rb
|
165
|
+
- spec/spec_helper.rb
|
166
|
+
- spec/support/macros/database_macros.rb
|
167
|
+
- spec/support/macros/model_macros.rb
|