enforce_schema_rules 0.0.14
Sign up to get free protection for your applications and to get access to all the features.
- data/README +89 -0
- data/lib/enforce_schema_rules.rb +96 -0
- metadata +89 -0
data/README
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
Enforce Schema Rules
|
2
|
+
=====================
|
3
|
+
|
4
|
+
This plugin provides a way to validate your model against databse rules
|
5
|
+
you've already created in your schema, including column lengths for
|
6
|
+
strings, "not null" designations, unique index constraints, and
|
7
|
+
ensuring integer input for integer columns.
|
8
|
+
|
9
|
+
The four methods currently supported are:
|
10
|
+
|
11
|
+
enforce_column_limits
|
12
|
+
enforce_integer_columns
|
13
|
+
enforce_not_null
|
14
|
+
enforce_unique_indexes
|
15
|
+
|
16
|
+
You can also just call <tt>enforce_schema_rules</tt> to enforce all the
|
17
|
+
above.
|
18
|
+
|
19
|
+
Accepts the relevant validates_length_of options (i.e. :on and :message)
|
20
|
+
and these assume the usual defaults.
|
21
|
+
|
22
|
+
In addition to the regular options, you can also have an
|
23
|
+
<tt>:except</tt> list enumerating the column that you don't want to
|
24
|
+
validate.
|
25
|
+
|
26
|
+
By default, magic columns (_at, _on, _id, id, position, etc) are
|
27
|
+
skipped. If you'd like to override that behavior, you can define your
|
28
|
+
own <tt>:exclusion_regexp</tt>
|
29
|
+
|
30
|
+
Examples:
|
31
|
+
|
32
|
+
class Person < ActiveRecord::Base
|
33
|
+
enforce_schema_rules :except => :dhh
|
34
|
+
end
|
35
|
+
|
36
|
+
class Book < ActiveRecord::Base
|
37
|
+
enforce_column_limits :message => "exceeds the %d character limit", :on => :update
|
38
|
+
enforce_unique_indexes
|
39
|
+
enforce_not_null :exclusion_regexp => /$fk_/
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
Download
|
44
|
+
--------
|
45
|
+
|
46
|
+
http://github.com/eric1234/enforce_schema_rules
|
47
|
+
|
48
|
+
|
49
|
+
Code of old plugin is located at:
|
50
|
+
|
51
|
+
http://enforce-schema-rules.googlecode.com/svn/trunk/enforce_schema_rules/
|
52
|
+
|
53
|
+
There is also a Rubyforge project of the old plugin at:
|
54
|
+
|
55
|
+
http://rubyforge.org/projects/enforce-schema/
|
56
|
+
|
57
|
+
|
58
|
+
Bugs & feedback
|
59
|
+
---------------
|
60
|
+
Please send bug reports, patches and feedback to Eric Anderson <eric@saveyourcall.com>
|
61
|
+
|
62
|
+
Todo
|
63
|
+
----
|
64
|
+
This updates main goal was to get it to work in Rails 3. Some cleanup
|
65
|
+
was just a side-effect. If anybody is interested additional cleanup
|
66
|
+
items include:
|
67
|
+
|
68
|
+
* Make sure we don't need better test coverage. The original plugin
|
69
|
+
had tests but I don't believe they worked completely. I fixed up
|
70
|
+
all existing tests to pass but there may be coverage we are missing.
|
71
|
+
* I made the smallest number of changes to get things working under
|
72
|
+
Rails 3. This plugin was written a while back. It might could be
|
73
|
+
refactored using some new goodness that comes with a more recent
|
74
|
+
ActiveRecord/Rails implementation.
|
75
|
+
* I most likely dropped support for Rails 2.x. The old plugin worked
|
76
|
+
fine for those (there are some warnings but they can be fixed
|
77
|
+
fairly easily and don't need to be fixed). I'm not sure if we want
|
78
|
+
one plugin that supports both versions but if there is demand for
|
79
|
+
it somebody could probably do it without too much effort.
|
80
|
+
|
81
|
+
Credit
|
82
|
+
------
|
83
|
+
This is an update to the plugin written by Josh Starcher <josh.starcher@gmail.com>.
|
84
|
+
Rails 3 compatibility has been added, it has been converted to a gem
|
85
|
+
for easy project inclusion and various other cleanups have been implemented.
|
86
|
+
In addition the original plugin gave the following credit notes:
|
87
|
+
|
88
|
+
This plugin is basically an extension of David Easley's enforce-limits
|
89
|
+
plugin. Michael Schuerig provided contributed a patch and a syle lesson.
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module Jls
|
4
|
+
module Validations #:nodoc:
|
5
|
+
module EnforceSchemaRules #:nodoc:
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
# Call all enforcement methods
|
13
|
+
def enforce_schema_rules(options = {})
|
14
|
+
enforce_column_limits(options.dup)
|
15
|
+
enforce_integer_columns(options.dup)
|
16
|
+
enforce_not_null(options.dup)
|
17
|
+
enforce_unique_indexes(options.dup)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Enforce string column limits
|
21
|
+
def enforce_column_limits(options = {})
|
22
|
+
args = build_validation_args(options, :string, :too_long)
|
23
|
+
return if args.first.is_a?(Hash)
|
24
|
+
options = args.pop
|
25
|
+
validates_each(*args) do |record, attr, value|
|
26
|
+
limit = record.class.columns_hash[attr.to_s].limit
|
27
|
+
if limit
|
28
|
+
message = options[:message] % {:count => limit}
|
29
|
+
record.errors.add(attr, message) unless value.nil? || value.size <= limit
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Enforce numericality of integer columns
|
35
|
+
def enforce_integer_columns(options = {})
|
36
|
+
# first get the non-integers
|
37
|
+
options[:allow_nil] = true
|
38
|
+
args = build_validation_args(options, :numeric, :not_a_number)
|
39
|
+
validates_numericality_of(*args) unless args.first.is_a? Hash
|
40
|
+
# now do the integers
|
41
|
+
options[:only_integer] = true
|
42
|
+
args = build_validation_args(options, :integer, :not_a_number)
|
43
|
+
validates_numericality_of(*args) unless args.first.is_a? Hash
|
44
|
+
end
|
45
|
+
|
46
|
+
# Enfore "not null" columns settings
|
47
|
+
def enforce_not_null(options = {})
|
48
|
+
args = build_validation_args(options, :not_null, :blank)
|
49
|
+
return if args.first.is_a?(Hash)
|
50
|
+
validates_presence_of(*args)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Enfore unique indexes
|
54
|
+
def enforce_unique_indexes(options = {})
|
55
|
+
attrs = build_validation_args(options, false, :taken)
|
56
|
+
return if attrs.first.is_a?(Hash)
|
57
|
+
options = attrs.pop
|
58
|
+
connection.indexes(table_name).select { |index| index.unique && index.columns.size == 1 && attrs.include?(index.columns.first.to_sym) }.each do |index|
|
59
|
+
validates_uniqueness_of(index.columns.first, options)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def build_validation_args(options, col_type, validation_option = :invalid)
|
64
|
+
options[validation_option] = I18n.translate('errors.messages')[validation_option]
|
65
|
+
options[:message] ||= options[validation_option]
|
66
|
+
exclusion_regexp = options[:exclusion_regexp] || /(_at|_on|_id)$|^(id|position|type)$/
|
67
|
+
# Determine which columns to validate and symbolize their names
|
68
|
+
condition = case col_type
|
69
|
+
when :numeric
|
70
|
+
lambda { |col| col.name !~ exclusion_regexp && col.number? && col.type != :integer }
|
71
|
+
when :not_null
|
72
|
+
# I have to exclude boolean types because of a "feature" of the way validates_presence_of
|
73
|
+
# handles boolean fields
|
74
|
+
# See http://dev.rubyonrails.org/ticket/5090 and http://dev.rubyonrails.org/ticket/3334
|
75
|
+
lambda { |col| (col.name !~ exclusion_regexp || col.name =~ /_id$/) && !col.null && col.type != :boolean }
|
76
|
+
else
|
77
|
+
lambda { |col| col.name !~ exclusion_regexp && col_type == col.type }
|
78
|
+
end
|
79
|
+
cols_to_validate = col_type ? columns.find_all { |col| condition[col] } : columns
|
80
|
+
# exclude columns
|
81
|
+
if except = options[:except]
|
82
|
+
except = Array(except).collect { |attr| attr.to_s }
|
83
|
+
cols_to_validate = cols_to_validate.reject { |col| except.include?(col.name) }
|
84
|
+
end
|
85
|
+
attrs = cols_to_validate.collect { |col| col.name.to_sym }
|
86
|
+
attrs << options
|
87
|
+
attrs
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
ActiveRecord::Base.class_eval do
|
95
|
+
include Jls::Validations::EnforceSchemaRules
|
96
|
+
end
|
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: enforce_schema_rules
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 3
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 14
|
10
|
+
version: 0.0.14
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Josh Starcher
|
14
|
+
- David Easley
|
15
|
+
- Michael Schuerig
|
16
|
+
- Eric Anderson
|
17
|
+
autorequire:
|
18
|
+
bindir: bin
|
19
|
+
cert_chain: []
|
20
|
+
|
21
|
+
date: 2010-10-28 00:00:00 -04:00
|
22
|
+
default_executable:
|
23
|
+
dependencies:
|
24
|
+
- !ruby/object:Gem::Dependency
|
25
|
+
name: activerecord
|
26
|
+
prerelease: false
|
27
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
hash: 3
|
33
|
+
segments:
|
34
|
+
- 0
|
35
|
+
version: "0"
|
36
|
+
type: :runtime
|
37
|
+
version_requirements: *id001
|
38
|
+
description: " A macro-style method that will automatically read the database\n contraints (null requirements, string length, etc) and enforce those\n at the model level to keep validation more DRY. Provides many\n options to customize how automatic it is and what columns it affects.\n"
|
39
|
+
email:
|
40
|
+
- josh.starcher@gmail.com
|
41
|
+
-
|
42
|
+
-
|
43
|
+
- eric@saveyourcall.com
|
44
|
+
executables: []
|
45
|
+
|
46
|
+
extensions: []
|
47
|
+
|
48
|
+
extra_rdoc_files:
|
49
|
+
- README
|
50
|
+
files:
|
51
|
+
- lib/enforce_schema_rules.rb
|
52
|
+
- README
|
53
|
+
has_rdoc: true
|
54
|
+
homepage:
|
55
|
+
licenses: []
|
56
|
+
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options:
|
59
|
+
- --main
|
60
|
+
- README
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
hash: 3
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
version: "0"
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
hash: 3
|
78
|
+
segments:
|
79
|
+
- 0
|
80
|
+
version: "0"
|
81
|
+
requirements: []
|
82
|
+
|
83
|
+
rubyforge_project:
|
84
|
+
rubygems_version: 1.3.7
|
85
|
+
signing_key:
|
86
|
+
specification_version: 3
|
87
|
+
summary: An ActiveRecord plugin to automatically enforce database contraints
|
88
|
+
test_files: []
|
89
|
+
|