typero 0.5.2 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.version +1 -1
- data/lib/adapters/sequel.rb +11 -33
- data/lib/typero.rb +8 -189
- data/lib/typero/params.rb +126 -0
- data/lib/typero/schema.rb +154 -0
- data/lib/typero/type/type.rb +125 -0
- data/lib/typero/type/types/boolean_type.rb +26 -0
- data/lib/typero/type/types/currency_type.rb +21 -0
- data/lib/typero/type/types/date_type.rb +35 -0
- data/lib/typero/type/types/datetime_type.rb +16 -0
- data/lib/typero/type/types/email_type.rb +20 -0
- data/lib/typero/type/types/float_type.rb +24 -0
- data/lib/typero/type/types/hash_type.rb +31 -0
- data/lib/typero/type/types/image_type.rb +22 -0
- data/lib/typero/type/types/integer_type.rb +16 -0
- data/lib/typero/type/types/label_type.rb +20 -0
- data/lib/typero/type/types/locale_type.rb +13 -0
- data/lib/typero/type/types/model_type.rb +23 -0
- data/lib/typero/type/{oib.rb → types/oib_type.rb} +16 -18
- data/lib/typero/type/types/point_type.rb +25 -0
- data/lib/typero/type/types/string_type.rb +20 -0
- data/lib/typero/type/types/text_type.rb +10 -0
- data/lib/typero/type/types/time_type.rb +5 -0
- data/lib/typero/type/types/timezone_type.rb +15 -0
- data/lib/typero/type/types/url_type.rb +13 -0
- data/lib/typero/typero.rb +98 -0
- metadata +33 -27
- data/lib/typero/type.rb +0 -32
- data/lib/typero/type/array.rb +0 -55
- data/lib/typero/type/boolean.rb +0 -16
- data/lib/typero/type/currency.rb +0 -17
- data/lib/typero/type/date.rb +0 -6
- data/lib/typero/type/datetime.rb +0 -6
- data/lib/typero/type/email.rb +0 -27
- data/lib/typero/type/float.rb +0 -27
- data/lib/typero/type/geography.rb +0 -13
- data/lib/typero/type/hash.rb +0 -18
- data/lib/typero/type/integer.rb +0 -25
- data/lib/typero/type/label.rb +0 -20
- data/lib/typero/type/point.rb +0 -25
- data/lib/typero/type/string.rb +0 -29
- data/lib/typero/type/text.rb +0 -7
- data/lib/typero/type/url.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b0ee2233c2ba484ec5ff98778a8da24a876b7b22eb4d24cc6b3ba3a8886e714
|
4
|
+
data.tar.gz: 4a96d10f9c6d0e75e8ae36965d34a6cda8853684974f799e2cf5e32d6a7003c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 880c3e4e551ab660f85530454ad9007ae383118677ea209ffaf0efff54bcd38da220579dc42d87618bd9ea50790b04a46c63dfe3cfd6252508b2bbec6ba1d711
|
7
|
+
data.tar.gz: 6f10437b894c91f3c7f723da03b426218d60b21c8bd161111d8ae7a745bdf35565f4fba84f26552fc75aa9b40211f3902d1cc2418fc420a5e3bce912ac676bc2
|
data/.version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.9.3
|
data/lib/adapters/sequel.rb
CHANGED
@@ -1,67 +1,45 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'typero'
|
4
|
-
|
5
3
|
module Sequel::Plugins::TyperoAttributes
|
6
4
|
module ClassMethods
|
7
|
-
def attributes opts={}, &block
|
8
|
-
instance_variable_set :@typero, Typero.new(&block)
|
9
|
-
|
10
|
-
# attributes migrate: true do ...
|
11
|
-
AutoMigrate.typero to_s.tableize.to_sym if opts[:migrate] && Lux.config.migrate
|
12
|
-
end
|
13
|
-
|
14
5
|
def typero
|
15
|
-
|
6
|
+
Typero.schema self
|
16
7
|
end
|
17
8
|
end
|
18
9
|
|
19
10
|
module InstanceMethods
|
20
11
|
# calling typero! on any object will validate all fields
|
21
|
-
def
|
22
|
-
|
12
|
+
def validate
|
13
|
+
super
|
23
14
|
|
24
|
-
|
15
|
+
schema = Typero.schema(self.class) || return
|
16
|
+
|
17
|
+
schema.validate(self) do |name, err|
|
25
18
|
errors.add(name, err) unless (errors.on(name) || []).include?(err)
|
26
19
|
end
|
27
20
|
|
28
21
|
# this are rules unique to database, so we check them here
|
29
|
-
|
22
|
+
schema.rules.each do |field, rule|
|
30
23
|
# check uniqe fields
|
31
|
-
if rule
|
24
|
+
if unique = rule.dig(:meta, :unique)
|
32
25
|
id = self[:id] || 0
|
33
26
|
value = self[field]
|
34
27
|
|
35
28
|
# we only check if field is changed
|
36
29
|
if value.present? && column_changed?(field) && self.class.xwhere('LOWER(%s)=LOWER(?) and id<>?' % field, value, id).first
|
37
|
-
error =
|
30
|
+
error = unique.class == TrueClass ? %[Value '"#{value}"' for #{field} allready exists] : unique
|
38
31
|
errors.add(field, error) unless (errors.on(field) || []).include?(error)
|
39
32
|
end
|
40
33
|
end
|
41
34
|
|
42
35
|
# check protected fields
|
43
|
-
if rule
|
36
|
+
if prot = rule.dig(:meta, :protected) && self[:id]
|
44
37
|
if column_changed?(field)
|
45
|
-
error =
|
38
|
+
error = prot.class == TrueClass ? "value once defined can't be overwritten." : prot
|
46
39
|
errors.add(field, error) unless (errors.on(field) || []).include?(error)
|
47
40
|
end
|
48
41
|
end
|
49
42
|
end
|
50
|
-
|
51
|
-
# check single field if single field given
|
52
|
-
if field_name
|
53
|
-
raise ArgumentError.new 'Field :%s not found in %s' % [field_name, self] unless self[field_name]
|
54
|
-
return unless errors.on(field_name)
|
55
|
-
|
56
|
-
errors.on(field_name).join(', ')
|
57
|
-
end
|
58
|
-
|
59
|
-
true
|
60
|
-
end
|
61
|
-
|
62
|
-
def validate
|
63
|
-
typero!
|
64
|
-
super
|
65
43
|
end
|
66
44
|
end
|
67
45
|
|
data/lib/typero.rb
CHANGED
@@ -1,194 +1,13 @@
|
|
1
|
-
#
|
2
|
-
# set :name, String, req: true
|
3
|
-
# set :email, :email, req: true
|
4
|
-
# set :skills, [:email], min: 2
|
5
|
-
# end
|
6
|
-
#
|
7
|
-
# or
|
8
|
-
#
|
9
|
-
# rules = Typero.new do
|
10
|
-
# string :name, req: true
|
11
|
-
# email :email, req: true
|
12
|
-
# email [:skills], min: 2
|
13
|
-
# end
|
14
|
-
#
|
15
|
-
# errors = rules.validate @object
|
16
|
-
# rules.valid?
|
17
|
-
# rules.validate(@object) { |errors| ... }
|
1
|
+
# require 'hash_wia'
|
18
2
|
|
19
|
-
|
20
|
-
|
3
|
+
# base libs
|
4
|
+
require_relative 'typero/typero'
|
5
|
+
require_relative 'typero/schema'
|
6
|
+
require_relative 'typero/params'
|
7
|
+
require_relative 'typero/type/type'
|
21
8
|
|
22
|
-
|
23
|
-
|
24
|
-
class << self
|
25
|
-
# validate single value in type
|
26
|
-
def validate type, value, opts={}
|
27
|
-
field = type.to_s.tableize.singularize.to_sym
|
28
|
-
|
29
|
-
# we need to have pointer to hash, so value can be changed (coerced) if needed
|
30
|
-
h = { field => value }
|
31
|
-
|
32
|
-
rule = new
|
33
|
-
rule.set field, type, opts
|
34
|
-
|
35
|
-
if error = rule.validate(h)[field]
|
36
|
-
block_given? ? yield(error) : raise(TypeError.new(error))
|
37
|
-
end
|
38
|
-
|
39
|
-
h[field]
|
40
|
-
end
|
41
|
-
|
42
|
-
# check and coerce value
|
43
|
-
# Typero.set(:label, 'Foo bar') -> "foo-bar"
|
44
|
-
def set type, value, opts={}
|
45
|
-
check = Typero::Type.load(type).new value, opts
|
46
|
-
check.value
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
###
|
51
|
-
|
52
|
-
# accepts dsl block to
|
53
|
-
def initialize hash={}, &block
|
54
|
-
@rules = {}
|
55
|
-
@db = []
|
56
|
-
hash.each { |k, v| set(k, v) }
|
57
|
-
instance_exec &block if block
|
58
|
-
end
|
59
|
-
|
60
|
-
# validates any instance object or object with hash variable interface
|
61
|
-
# it also coarces values
|
62
|
-
def validate instance
|
63
|
-
@errors = {}
|
64
|
-
|
65
|
-
@rules.each do |field, opts|
|
66
|
-
# set value to default if value is blank and default given
|
67
|
-
instance[field] = opts[:default] if opts[:default] && instance[field].blank?
|
68
|
-
|
69
|
-
# get field value
|
70
|
-
value = instance[field]
|
71
|
-
|
72
|
-
if value.present?
|
73
|
-
klass = 'Typero::%sType' % safe_type(opts[:type])
|
74
|
-
check = klass.constantize.new value, opts
|
75
|
-
check.value = check.default if check.value.nil?
|
76
|
-
|
77
|
-
unless check.value.nil?
|
78
|
-
begin
|
79
|
-
check.set
|
80
|
-
check.validate
|
81
|
-
instance[field] = check.value
|
82
|
-
rescue TypeError => e
|
83
|
-
add_error field, e.message
|
84
|
-
end
|
85
|
-
end
|
86
|
-
elsif opts[:required]
|
87
|
-
msg = opts[:required].class == TrueClass ? 'is required' : opts[:req]
|
88
|
-
add_error field, msg
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
if @errors.keys.length > 0 && block_given?
|
93
|
-
@errors.each { |k,v| yield(k, v) }
|
94
|
-
end
|
95
|
-
|
96
|
-
@errors
|
97
|
-
end
|
98
|
-
|
99
|
-
def valid? instance
|
100
|
-
errors = validate instance
|
101
|
-
errors.keys.length == 0
|
102
|
-
end
|
103
|
-
|
104
|
-
# returns field, db_type, db_opts
|
105
|
-
def db_schema
|
106
|
-
out = @rules.inject([]) do |total, (field, opts)|
|
107
|
-
type, opts = Typero::Type.load(opts[:type]).new(nil, opts).db_field
|
108
|
-
total << [type, field, opts]
|
109
|
-
end
|
110
|
-
|
111
|
-
out += @db if @db[0]
|
112
|
-
|
113
|
-
out
|
114
|
-
end
|
115
|
-
|
116
|
-
private
|
117
|
-
|
118
|
-
# adds error to array or prefixes with field name
|
119
|
-
def add_error field, msg
|
120
|
-
if @errors[field]
|
121
|
-
@errors[field] += ', %s' % msg
|
122
|
-
else
|
123
|
-
if msg[0,1].downcase == msg[0,1]
|
124
|
-
field_name = field.to_s.sub(/_id$/,'').humanize
|
125
|
-
msg = '%s %s' % [field_name, msg]
|
126
|
-
end
|
127
|
-
|
128
|
-
@errors[field] = msg
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
# used in dsl to define value
|
133
|
-
def set field, type=String, opts={}
|
134
|
-
opts = type.is_a?(Hash) ? type : opts.merge(type: type)
|
135
|
-
opts[:type] ||= :string
|
136
|
-
opts[:req] = true if opts[:null].class == FalseClass
|
137
|
-
klass = Typero::Type.load opts[:type]
|
138
|
-
@rules[field] = parse_option opts
|
139
|
-
end
|
140
|
-
|
141
|
-
def safe_type type
|
142
|
-
type.to_s.gsub(/[^\w]/,'').classify
|
143
|
-
end
|
144
|
-
|
145
|
-
# coerce opts values
|
146
|
-
def parse_option opts
|
147
|
-
opts[:type] ||= 'string'
|
148
|
-
|
149
|
-
if opts[:type].is_a?(Array)
|
150
|
-
opts[:array_type] = opts[:type][0] if opts[:type][0]
|
151
|
-
opts[:type] = 'array'
|
152
|
-
end
|
153
|
-
|
154
|
-
opts[:type] = opts[:type].to_s.downcase
|
155
|
-
|
156
|
-
opts[:required] = opts.delete(:req) unless opts[:req].nil?
|
157
|
-
opts[:unique] = opts.delete(:uniq) unless opts[:uniq].nil?
|
158
|
-
opts[:description] = opts.delete(:desc) unless opts[:desc].nil?
|
159
|
-
|
160
|
-
opts
|
161
|
-
end
|
162
|
-
|
163
|
-
|
164
|
-
# pass values for db_schema only
|
165
|
-
# db :timestamps
|
166
|
-
# db :add_index, :code -> t.add_index :code
|
167
|
-
def db *args
|
168
|
-
@db.push args
|
169
|
-
end
|
170
|
-
|
171
|
-
# set :age, type: :integer -> integer :age
|
172
|
-
# email :email
|
173
|
-
# set :email, [:emails]
|
174
|
-
# email [:emails]
|
175
|
-
def method_missing name, *args, &block
|
176
|
-
field = args.shift
|
177
|
-
|
178
|
-
if field.class == Array
|
179
|
-
field = field.first
|
180
|
-
name = [name]
|
181
|
-
end
|
182
|
-
|
183
|
-
name = args.shift if name == :set
|
184
|
-
|
185
|
-
set field, type=name, *args
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
require_relative 'typero/type'
|
190
|
-
|
191
|
-
Dir['%s/typero/type/*.rb' % __dir__].each do |file|
|
9
|
+
# checker types
|
10
|
+
Dir['%s/typero/type/types/*.rb' % __dir__].each do |file|
|
192
11
|
require file
|
193
12
|
end
|
194
13
|
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# Base class for schema validation
|
2
|
+
|
3
|
+
module Typero
|
4
|
+
class Params
|
5
|
+
attr_reader :db_rules
|
6
|
+
|
7
|
+
def initialize &block
|
8
|
+
@db_rules = []
|
9
|
+
@rules = {}
|
10
|
+
instance_exec &block
|
11
|
+
end
|
12
|
+
|
13
|
+
def rules
|
14
|
+
@rules.dup
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
# used in dsl to define schema field options
|
20
|
+
def set field, *args, &block
|
21
|
+
raise "Field name not given (Typero)" unless field
|
22
|
+
|
23
|
+
if args.first.is_a?(Hash)
|
24
|
+
opts = args.first || {}
|
25
|
+
else
|
26
|
+
opts = args[1] || {}
|
27
|
+
opts[:type] ||= args[0]
|
28
|
+
end
|
29
|
+
|
30
|
+
opts[:type] = :string if opts[:type].nil?
|
31
|
+
|
32
|
+
field = field.to_s
|
33
|
+
|
34
|
+
if field.include?('!')
|
35
|
+
if block
|
36
|
+
field = field.sub('!', '')
|
37
|
+
@block_type = field.to_sym
|
38
|
+
instance_exec &block
|
39
|
+
@block_type = nil
|
40
|
+
return
|
41
|
+
else
|
42
|
+
raise ArgumentError.new 'If you use ! you have to provide a block'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# name? - opional name
|
47
|
+
if field.include?('?')
|
48
|
+
field = field.sub('?', '')
|
49
|
+
opts[:required] = false
|
50
|
+
end
|
51
|
+
|
52
|
+
if value = opts.delete(:req)
|
53
|
+
opts[:required] = value
|
54
|
+
else
|
55
|
+
opts[:required] = true if opts[:required].nil?
|
56
|
+
end
|
57
|
+
|
58
|
+
# array that allows duplicates
|
59
|
+
if opts[:type].is_a?(Array)
|
60
|
+
opts[:type] = opts[:type].first
|
61
|
+
opts[:array] = true
|
62
|
+
end
|
63
|
+
|
64
|
+
# no duplicates array
|
65
|
+
if opts[:type].is_a?(Set)
|
66
|
+
opts[:type] = opts[:type].to_a.first
|
67
|
+
opts[:array] = true
|
68
|
+
end
|
69
|
+
|
70
|
+
opts[:type] = @block_type if @block_type
|
71
|
+
|
72
|
+
# Boolean
|
73
|
+
if opts[:type].is_a?(TrueClass) || opts[:type] == :true
|
74
|
+
opts[:required] = false
|
75
|
+
opts[:default] = true
|
76
|
+
opts[:type] = :boolean
|
77
|
+
elsif opts[:type].is_a?(FalseClass) || opts[:type] == :false
|
78
|
+
opts[:required] = false
|
79
|
+
opts[:default] = false
|
80
|
+
opts[:type] = :boolean
|
81
|
+
end
|
82
|
+
|
83
|
+
opts[:model] = opts.delete(:schema) if opts[:schema]
|
84
|
+
opts[:type] = :model if opts[:model]
|
85
|
+
|
86
|
+
if block_given?
|
87
|
+
opts[:type] = :model
|
88
|
+
opts[:model] = Typero.schema &block
|
89
|
+
end
|
90
|
+
|
91
|
+
opts[:type] ||= 'string'
|
92
|
+
opts[:type] = opts[:type].to_s.downcase.to_sym
|
93
|
+
|
94
|
+
opts[:description] = opts.delete(:desc) unless opts[:desc].nil?
|
95
|
+
|
96
|
+
# chek alloed params, all optional should go in meta
|
97
|
+
result = opts.keys - Typero::Type::OPTS_KEYS
|
98
|
+
raise ArgumentError.new('Unallowed Type params found: "%s", allowed: %s' % [result.join(' and '), Typero::Type::OPTS_KEYS.sort]) if result.length > 0
|
99
|
+
|
100
|
+
field = field.to_sym
|
101
|
+
|
102
|
+
db :add_index, field if opts.delete(:index)
|
103
|
+
|
104
|
+
# trigger error if type not found
|
105
|
+
Typero::Type.load opts[:type]
|
106
|
+
|
107
|
+
@rules[field] = opts
|
108
|
+
end
|
109
|
+
|
110
|
+
# pass values for db_schema only
|
111
|
+
# db :timestamps
|
112
|
+
# db :add_index, :code -> t.add_index :code
|
113
|
+
def db *args
|
114
|
+
@db_rules.push args
|
115
|
+
end
|
116
|
+
|
117
|
+
# set :age, type: :integer -> integer :age
|
118
|
+
# email :email
|
119
|
+
#
|
120
|
+
# set :emails, Array[:email]
|
121
|
+
# email Array[:emails]
|
122
|
+
def method_missing field, *args, &block
|
123
|
+
set field, *args, &block
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
module Typero
|
2
|
+
class Schema
|
3
|
+
SCHEMAS = {}
|
4
|
+
TYPES = {}
|
5
|
+
|
6
|
+
# accepts dsl block to
|
7
|
+
def initialize &block
|
8
|
+
raise "Params not defined" unless block_given?
|
9
|
+
@schema = Params.new &block
|
10
|
+
end
|
11
|
+
|
12
|
+
# validates any instance object with hash variable interface
|
13
|
+
# it also coarces values
|
14
|
+
def validate object, options=nil
|
15
|
+
@options = options || {}
|
16
|
+
@object = object
|
17
|
+
@errors = {}
|
18
|
+
|
19
|
+
# remove undefined keys if Hash provided
|
20
|
+
if @options[:strict] && object.is_a?(Hash)
|
21
|
+
undefined = object.keys.map(&:to_s) - @schema.rules.keys.map(&:to_s)
|
22
|
+
object.delete_if { |k, _| undefined.include?(k.to_s) }
|
23
|
+
end
|
24
|
+
|
25
|
+
@schema.rules.each do |field, opts|
|
26
|
+
for k in opts.keys
|
27
|
+
opts[k] = @object.instance_exec(&opts[k]) if opts[k].is_a?(Proc)
|
28
|
+
end
|
29
|
+
|
30
|
+
# set value to default if value is blank and default given
|
31
|
+
@object[field] = opts[:default] if opts[:default] && @object[field].blank?
|
32
|
+
|
33
|
+
# get field value
|
34
|
+
value = @object[field]
|
35
|
+
|
36
|
+
if opts[:array]
|
37
|
+
unless value.respond_to?(:each)
|
38
|
+
opts[:delimiter] ||= /\s*[,\n]\s*/
|
39
|
+
value = value.to_s.split(opts[:delimiter])
|
40
|
+
end
|
41
|
+
|
42
|
+
value = value
|
43
|
+
.flatten
|
44
|
+
.map { |el| el.to_s == '' ? nil : check_filed_value(field, el, opts) }
|
45
|
+
.compact
|
46
|
+
|
47
|
+
value = Set.new(value).to_a unless opts[:duplicates]
|
48
|
+
|
49
|
+
opts[:max_count] ||= 100
|
50
|
+
add_error(field, 'Max number of array elements is %d, you have %d' % [opts[:max_count], value.length], opts) if value && value.length > opts[:max_count]
|
51
|
+
add_error(field, 'Min number of array elements is %d, you have %d' % [opts[:min_count], value.length], opts) if value && opts[:min_count] && value.length < opts[:min_count]
|
52
|
+
|
53
|
+
add_required_error field, value.first, opts
|
54
|
+
else
|
55
|
+
value = nil if value.to_s == ''
|
56
|
+
|
57
|
+
# if value is not list of allowed values, raise error
|
58
|
+
allowed = opts[:allow] || opts[:allowed] || opts[:values]
|
59
|
+
if value && allowed && !allowed.include?(value)
|
60
|
+
add_error field, 'Value "%s" is not allowed' % value, opts
|
61
|
+
end
|
62
|
+
|
63
|
+
value = check_filed_value field, value, opts
|
64
|
+
add_required_error field, value, opts
|
65
|
+
end
|
66
|
+
|
67
|
+
# present empty string values as nil
|
68
|
+
@object[field] = value.to_s.sub(/\s+/, '') == '' ? nil : value
|
69
|
+
end
|
70
|
+
|
71
|
+
if @errors.keys.length > 0 && block_given?
|
72
|
+
@errors.each { |k, v| yield(k, v) }
|
73
|
+
end
|
74
|
+
|
75
|
+
@errors
|
76
|
+
end
|
77
|
+
|
78
|
+
def valid? object
|
79
|
+
errors = validate object
|
80
|
+
errors.keys.length == 0
|
81
|
+
end
|
82
|
+
|
83
|
+
# returns field, db_type, db_opts
|
84
|
+
def db_schema
|
85
|
+
out = @schema.rules.inject([]) do |total, (field, opts)|
|
86
|
+
# get db filed schema
|
87
|
+
type, opts = Typero::Type.load(opts[:type]).new(nil, opts).db_field
|
88
|
+
|
89
|
+
# add array true to field it ont defined in schema
|
90
|
+
schema_opts = @schema.rules[field]
|
91
|
+
opts[:array] = true if schema_opts[:array]
|
92
|
+
|
93
|
+
total << [type, field, opts]
|
94
|
+
end
|
95
|
+
|
96
|
+
out += @schema.db_rules
|
97
|
+
|
98
|
+
out
|
99
|
+
end
|
100
|
+
|
101
|
+
# iterate trough all the ruels via block interface
|
102
|
+
# schema.rules do |field, opts|
|
103
|
+
# schema.rules(:url) do |field, opts|
|
104
|
+
def rules filter = nil, &block
|
105
|
+
return @schema.rules unless filter
|
106
|
+
out = @schema.rules
|
107
|
+
out = out.select { |k, v| v[:type].to_s == filter.to_s || v[:array_type].to_s == filter.to_s } if filter
|
108
|
+
return out unless block_given?
|
109
|
+
|
110
|
+
out.each { |k, v| yield k, v }
|
111
|
+
end
|
112
|
+
alias :to_h :rules
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
# adds error to array or prefixes with field name
|
117
|
+
def add_error field, msg, opts
|
118
|
+
if @errors[field]
|
119
|
+
@errors[field] += ", %s" % msg
|
120
|
+
else
|
121
|
+
if msg && msg[0, 1].downcase == msg[0, 1]
|
122
|
+
field_name = opts[:name] || field.to_s.sub(/_id$/, "").capitalize
|
123
|
+
msg = "%s %s" % [field_name, msg]
|
124
|
+
end
|
125
|
+
|
126
|
+
@errors[field] = msg
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def safe_type type
|
131
|
+
type.to_s.gsub(/[^\w]/, "").classify
|
132
|
+
end
|
133
|
+
|
134
|
+
def add_required_error field, value, opts
|
135
|
+
return unless opts[:required] && value.nil?
|
136
|
+
msg = opts[:required].class == TrueClass ? "is required" : opts[:required]
|
137
|
+
add_error field, msg, opts
|
138
|
+
end
|
139
|
+
|
140
|
+
def check_filed_value field, value, opts
|
141
|
+
klass = "Typero::%sType" % safe_type(opts[:type])
|
142
|
+
check = klass.constantize.new value, opts
|
143
|
+
check.get
|
144
|
+
rescue TypeError => e
|
145
|
+
if e.message[0] == '{'
|
146
|
+
for key, msg in JSON.parse(e.message)
|
147
|
+
add_error [field, key].join('.'), msg, opts
|
148
|
+
end
|
149
|
+
else
|
150
|
+
add_error field, e.message, opts
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|