enforce_schema_rules 0.0.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/README +89 -0
  2. data/lib/enforce_schema_rules.rb +96 -0
  3. 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
+