schema_validations 2.0.1 → 2.0.2
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 +4 -4
- data/.gitignore +1 -0
- data/README.md +4 -0
- data/gemfiles/activerecord-4.2/Gemfile.base +1 -1
- data/gemfiles/activerecord-4.2/Gemfile.mysql2 +2 -2
- data/lib/schema_validations/active_record/validations.rb +177 -177
- data/lib/schema_validations/version.rb +1 -1
- data/lib/schema_validations.rb +1 -9
- data/schema_validations.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8fe25cdf83ff0041992948fe1a400d40cd4e4ebc
|
4
|
+
data.tar.gz: 286fec9f821594ffe76bffdf1fd0b08c87320f18
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7065a87c0ae2eec4d971423b6fa6d9f63c250e4e4c65f7fc3ee775d896408cc9e64fd704936b367d66206869fbc7874d4e326020171dbef15f365aa68d3bad86
|
7
|
+
data.tar.gz: 00c9fd2a04f6ba7f539595e717abbfb68db2c62fc59fa6a140266c069f09f57e31e1b167f1becef7d839cd1bc29bad66a4ae8977296c1c25525168e9acd0ef04
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,216 +1,216 @@
|
|
1
1
|
module SchemaValidations
|
2
2
|
module ActiveRecord
|
3
|
-
module
|
3
|
+
module Base
|
4
4
|
|
5
|
-
def
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
def load_schema_validations
|
6
|
+
self.class.send :load_schema_validations
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
|
11
|
+
def self.extended(base)
|
12
|
+
base.class_eval do
|
13
|
+
class_attribute :schema_validations_loaded
|
9
14
|
end
|
10
|
-
class_attribute :schema_validations_loaded
|
11
15
|
end
|
12
|
-
class << base
|
13
|
-
alias_method_chain :validators, :schema_validations
|
14
|
-
alias_method_chain :validators_on, :schema_validations
|
15
|
-
end if base.respond_to? :validators
|
16
|
-
end
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
def inherited(subclass) # :nodoc:
|
18
|
+
super
|
19
|
+
before_validation :load_schema_validations unless schema_validations_loaded?
|
20
|
+
end
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
def validators
|
23
|
+
load_schema_validations unless schema_validations_loaded?
|
24
|
+
super
|
25
|
+
end
|
27
26
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
def validators_on(*args)
|
28
|
+
load_schema_validations unless schema_validations_loaded?
|
29
|
+
super
|
30
|
+
end
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
32
|
+
# Per-model override of Config options. Use via, e.g.
|
33
|
+
# class MyModel < ActiveRecord::Base
|
34
|
+
# schema_validations :auto_create => false
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# If <tt>:auto_create</tt> is not specified, it is implicitly
|
38
|
+
# specified as true. This allows the "non-invasive" style of using
|
39
|
+
# SchemaValidations in which you set the global Config to
|
40
|
+
# <tt>auto_create = false</tt>, then in any model that you want auto
|
41
|
+
# validations you simply do:
|
42
|
+
#
|
43
|
+
# class MyModel < ActiveRecord::Base
|
44
|
+
# schema_validations
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# Of course other options can be passed, such as
|
48
|
+
#
|
49
|
+
# class MyModel < ActiveRecord::Base
|
50
|
+
# schema_validations :except_type => :validates_presence_of
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
#
|
54
|
+
def schema_validations(opts={})
|
55
|
+
@schema_validations_config = SchemaValidations.config.merge({:auto_create => true}.merge(opts))
|
56
|
+
end
|
58
57
|
|
59
|
-
|
60
|
-
|
61
|
-
|
58
|
+
def schema_validations_config # :nodoc:
|
59
|
+
@schema_validations_config ||= SchemaValidations.config.dup
|
60
|
+
end
|
62
61
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
62
|
+
private
|
63
|
+
# Adds schema-based validations to model.
|
64
|
+
# Attributes as well as associations are validated.
|
65
|
+
# For instance if there is column
|
66
|
+
#
|
67
|
+
# <code>email NOT NULL</code>
|
68
|
+
#
|
69
|
+
# defined at database-level it will be translated to
|
70
|
+
#
|
71
|
+
# <code>validates_presence_of :email</code>
|
72
|
+
#
|
73
|
+
# If there is an association named <tt>user</tt>
|
74
|
+
# based on <tt>user_id NOT NULL</tt> it will be translated to
|
75
|
+
#
|
76
|
+
# <code>validates_presence_of :user</code>
|
77
|
+
#
|
78
|
+
# Note it uses the name of association (user) not the column name (user_id).
|
79
|
+
# Only <tt>belongs_to</tt> associations are validated.
|
80
|
+
#
|
81
|
+
# This accepts following options:
|
82
|
+
# * :only - auto-validate only given attributes
|
83
|
+
# * :except - auto-validate all but given attributes
|
84
|
+
#
|
85
|
+
def load_schema_validations #:nodoc:
|
86
|
+
# Don't bother if: it's already been loaded; the class is abstract; not a base class; or the table doesn't exist
|
87
|
+
return unless create_schema_validations?
|
88
|
+
load_column_validations
|
89
|
+
load_association_validations
|
90
|
+
self.schema_validations_loaded = true
|
91
|
+
end
|
93
92
|
|
94
|
-
|
95
|
-
|
96
|
-
|
93
|
+
def load_column_validations #:nodoc:
|
94
|
+
content_columns.each do |column|
|
95
|
+
name = column.name.to_sym
|
96
|
+
|
97
|
+
# Data-type validation
|
98
|
+
datatype = case
|
99
|
+
when respond_to?(:defined_enums) && defined_enums.has_key?(column.name) then :enum
|
100
|
+
when column.type == :integer then :integer
|
101
|
+
when column.number? then :numeric
|
102
|
+
when column.text? then :text
|
103
|
+
when column.type == :boolean then :boolean
|
104
|
+
end
|
105
|
+
|
106
|
+
case datatype
|
107
|
+
when :integer
|
108
|
+
load_integer_column_validations(name, column)
|
109
|
+
when :numeric
|
110
|
+
validate_logged :validates_numericality_of, name, :allow_nil => true
|
111
|
+
when :text
|
112
|
+
validate_logged :validates_length_of, name, :allow_nil => true, :maximum => column.limit if column.limit
|
113
|
+
end
|
114
|
+
|
115
|
+
# NOT NULL constraints
|
116
|
+
if column.required_on
|
117
|
+
if datatype == :boolean
|
118
|
+
validate_logged :validates_inclusion_of, name, :in => [true, false], :message => :blank
|
119
|
+
else
|
120
|
+
validate_logged :validates_presence_of, name
|
121
|
+
end
|
122
|
+
end
|
97
123
|
|
98
|
-
|
99
|
-
|
100
|
-
when respond_to?(:defined_enums) && defined_enums.has_key?(column.name) then :enum
|
101
|
-
when column.type == :integer then :integer
|
102
|
-
when column.number? then :numeric
|
103
|
-
when column.text? then :text
|
104
|
-
when column.type == :boolean then :boolean
|
105
|
-
end
|
106
|
-
|
107
|
-
case datatype
|
108
|
-
when :integer
|
109
|
-
load_integer_column_validations(name, column)
|
110
|
-
when :numeric
|
111
|
-
validate_logged :validates_numericality_of, name, :allow_nil => true
|
112
|
-
when :text
|
113
|
-
validate_logged :validates_length_of, name, :allow_nil => true, :maximum => column.limit if column.limit
|
124
|
+
# UNIQUE constraints
|
125
|
+
add_uniqueness_validation(column) if column.unique?
|
114
126
|
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def load_integer_column_validations(name, column) # :nodoc:
|
130
|
+
options = { :allow_nil => true, :only_integer => true }
|
115
131
|
|
116
|
-
|
117
|
-
|
118
|
-
if
|
119
|
-
|
132
|
+
if range = column.cast_type.try(:range)
|
133
|
+
options[:greater_than_or_equal_to] = range.begin
|
134
|
+
if range.exclude_end?
|
135
|
+
options[:less_than] = range.end
|
120
136
|
else
|
121
|
-
|
137
|
+
options[:less_than_or_equal_to] = range.end
|
122
138
|
end
|
123
139
|
end
|
124
140
|
|
125
|
-
|
126
|
-
add_uniqueness_validation(column) if column.unique?
|
141
|
+
validate_logged :validates_numericality_of, name, options
|
127
142
|
end
|
128
|
-
end
|
129
143
|
|
130
|
-
|
131
|
-
|
144
|
+
def load_association_validations #:nodoc:
|
145
|
+
reflect_on_all_associations(:belongs_to).each do |association|
|
146
|
+
# :primary_key_name was deprecated (noisily) in rails 3.1
|
147
|
+
foreign_key_method = (association.respond_to? :foreign_key) ? :foreign_key : :primary_key_name
|
148
|
+
column = columns_hash[association.send(foreign_key_method).to_s]
|
149
|
+
next unless column
|
150
|
+
|
151
|
+
# NOT NULL constraints
|
152
|
+
validate_logged :validates_presence_of, association.name if column.required_on
|
132
153
|
|
133
|
-
|
134
|
-
|
135
|
-
if range.exclude_end?
|
136
|
-
options[:less_than] = range.end
|
137
|
-
else
|
138
|
-
options[:less_than_or_equal_to] = range.end
|
154
|
+
# UNIQUE constraints
|
155
|
+
add_uniqueness_validation(column) if column.unique?
|
139
156
|
end
|
140
157
|
end
|
141
158
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
def load_association_validations #:nodoc:
|
146
|
-
reflect_on_all_associations(:belongs_to).each do |association|
|
147
|
-
# :primary_key_name was deprecated (noisily) in rails 3.1
|
148
|
-
foreign_key_method = (association.respond_to? :foreign_key) ? :foreign_key : :primary_key_name
|
149
|
-
column = columns_hash[association.send(foreign_key_method).to_s]
|
150
|
-
next unless column
|
159
|
+
def add_uniqueness_validation(column) #:nodoc:
|
160
|
+
scope = column.unique_scope.map(&:to_sym)
|
161
|
+
name = column.name.to_sym
|
151
162
|
|
152
|
-
|
153
|
-
|
163
|
+
options = {}
|
164
|
+
options[:scope] = scope if scope.any?
|
165
|
+
options[:allow_nil] = true
|
166
|
+
options[:case_sensitive] = false if has_case_insensitive_index?(column, scope)
|
167
|
+
options[:if] = (proc do |record|
|
168
|
+
if scope.all? { |scope_sym| record.public_send(:"#{scope_sym}?") }
|
169
|
+
record.public_send(:"#{column.name}_changed?")
|
170
|
+
else
|
171
|
+
false
|
172
|
+
end
|
173
|
+
end)
|
154
174
|
|
155
|
-
|
156
|
-
add_uniqueness_validation(column) if column.unique?
|
175
|
+
validate_logged :validates_uniqueness_of, name, options
|
157
176
|
end
|
158
|
-
end
|
159
177
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
options = {}
|
165
|
-
options[:scope] = scope if scope.any?
|
166
|
-
options[:allow_nil] = true
|
167
|
-
options[:case_sensitive] = false if has_case_insensitive_index?(column, scope)
|
168
|
-
options[:if] = (proc do |record|
|
169
|
-
if scope.all? { |scope_sym| record.public_send(:"#{scope_sym}?") }
|
170
|
-
record.public_send(:"#{column.name}_changed?")
|
171
|
-
else
|
172
|
-
false
|
173
|
-
end
|
174
|
-
end)
|
175
|
-
|
176
|
-
validate_logged :validates_uniqueness_of, name, options
|
177
|
-
end
|
178
|
+
def has_case_insensitive_index?(column, scope)
|
179
|
+
indexed_columns = (scope + [column.name]).map(&:to_sym).sort
|
180
|
+
index = column.indexes.select { |i| i.unique && i.columns.map(&:to_sym).sort == indexed_columns }.first
|
178
181
|
|
179
|
-
|
180
|
-
|
181
|
-
index = column.indexes.select { |i| i.unique && i.columns.map(&:to_sym).sort == indexed_columns }.first
|
182
|
-
|
183
|
-
index && index.respond_to?(:case_sensitive?) && !index.case_sensitive?
|
184
|
-
end
|
182
|
+
index && index.respond_to?(:case_sensitive?) && !index.case_sensitive?
|
183
|
+
end
|
185
184
|
|
186
|
-
|
187
|
-
|
188
|
-
|
185
|
+
def create_schema_validations? #:nodoc:
|
186
|
+
schema_validations_config.auto_create? && !(schema_validations_loaded || abstract_class? || name.blank? || !table_exists?)
|
187
|
+
end
|
189
188
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
189
|
+
def validate_logged(method, arg, opts={}) #:nodoc:
|
190
|
+
if _filter_validation(method, arg)
|
191
|
+
msg = "[schema_validations] #{self.name}.#{method} #{arg.inspect}"
|
192
|
+
msg += ", #{opts.inspect[1...-1]}" if opts.any?
|
193
|
+
logger.debug msg
|
194
|
+
send method, arg, opts
|
195
|
+
end
|
196
196
|
end
|
197
|
-
end
|
198
197
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
198
|
+
def _filter_validation(macro, name) #:nodoc:
|
199
|
+
config = schema_validations_config
|
200
|
+
types = [macro]
|
201
|
+
if match = macro.to_s.match(/^validates_(.*)_of$/)
|
202
|
+
types << match[1].to_sym
|
203
|
+
end
|
204
|
+
return false if config.only and not Array.wrap(config.only).include?(name)
|
205
|
+
return false if config.except and Array.wrap(config.except).include?(name)
|
206
|
+
return false if config.whitelist and Array.wrap(config.whitelist).include?(name)
|
207
|
+
return false if config.only_type and not (Array.wrap(config.only_type) & types).any?
|
208
|
+
return false if config.except_type and (Array.wrap(config.except_type) & types).any?
|
209
|
+
return false if config.whitelist_type and (Array.wrap(config.whitelist_type) & types).any?
|
210
|
+
return true
|
204
211
|
end
|
205
|
-
return false if config.only and not Array.wrap(config.only).include?(name)
|
206
|
-
return false if config.except and Array.wrap(config.except).include?(name)
|
207
|
-
return false if config.whitelist and Array.wrap(config.whitelist).include?(name)
|
208
|
-
return false if config.only_type and not (Array.wrap(config.only_type) & types).any?
|
209
|
-
return false if config.except_type and (Array.wrap(config.except_type) & types).any?
|
210
|
-
return false if config.whitelist_type and (Array.wrap(config.whitelist_type) & types).any?
|
211
|
-
return true
|
212
|
-
end
|
213
212
|
|
213
|
+
end
|
214
214
|
end
|
215
215
|
|
216
216
|
end
|
data/lib/schema_validations.rb
CHANGED
@@ -4,7 +4,6 @@ require 'schema_plus_columns'
|
|
4
4
|
require 'schema_validations/version'
|
5
5
|
require 'schema_validations/active_record/validations'
|
6
6
|
require 'schema_validations/active_record/type'
|
7
|
-
require 'schema_validations/railtie' if defined?(Rails::Railtie)
|
8
7
|
|
9
8
|
module SchemaValidations
|
10
9
|
|
@@ -109,13 +108,6 @@ module SchemaValidations
|
|
109
108
|
yield config
|
110
109
|
end
|
111
110
|
|
112
|
-
def self.insert #:nodoc:
|
113
|
-
return if @inserted
|
114
|
-
@inserted = true
|
115
|
-
::ActiveRecord::Base.extend SchemaValidations::ActiveRecord::Validations
|
116
|
-
::ActiveRecord::Type::Integer.prepend SchemaValidations::ActiveRecord::Type::Integer
|
117
|
-
end
|
118
|
-
|
119
111
|
end
|
120
112
|
|
121
|
-
|
113
|
+
SchemaMonkey.register SchemaValidations
|
data/schema_validations.gemspec
CHANGED
@@ -24,7 +24,7 @@ Gem::Specification.new do |s|
|
|
24
24
|
s.add_dependency("activerecord", "~> 4.2", ">= 4.2.1")
|
25
25
|
s.add_dependency("valuable")
|
26
26
|
|
27
|
-
s.add_development_dependency("schema_dev", "~> 3.
|
27
|
+
s.add_development_dependency("schema_dev", "~> 3.6")
|
28
28
|
s.add_development_dependency("rake")
|
29
29
|
s.add_development_dependency("rdoc")
|
30
30
|
s.add_development_dependency("rspec")
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: schema_validations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ronen Barzel
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-03-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: schema_plus_columns
|
@@ -65,14 +65,14 @@ dependencies:
|
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '3.
|
68
|
+
version: '3.6'
|
69
69
|
type: :development
|
70
70
|
prerelease: false
|
71
71
|
version_requirements: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '3.
|
75
|
+
version: '3.6'
|
76
76
|
- !ruby/object:Gem::Dependency
|
77
77
|
name: rake
|
78
78
|
requirement: !ruby/object:Gem::Requirement
|