typero 0.8.0 → 0.9.4
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/.version +1 -1
- data/lib/adapters/sequel.rb +10 -27
- data/lib/typero.rb +3 -0
- data/lib/typero/params.rb +57 -12
- data/lib/typero/schema.rb +165 -0
- data/lib/typero/type/type.rb +68 -10
- 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 +38 -0
- data/lib/typero/type/types/datetime_type.rb +19 -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.rb → image_type.rb} +4 -10
- 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/types/{oib.rb → oib_type.rb} +7 -10
- data/lib/typero/type/types/point_type.rb +25 -0
- data/lib/typero/type/types/string_type.rb +23 -0
- data/lib/typero/type/types/{text.rb → text_type.rb} +3 -5
- 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 +72 -141
- metadata +26 -21
- data/lib/typero/type/types/boolean.rb +0 -16
- data/lib/typero/type/types/currency.rb +0 -19
- data/lib/typero/type/types/date.rb +0 -10
- data/lib/typero/type/types/datetime.rb +0 -10
- data/lib/typero/type/types/email.rb +0 -21
- data/lib/typero/type/types/float.rb +0 -21
- data/lib/typero/type/types/hash.rb +0 -22
- data/lib/typero/type/types/integer.rb +0 -21
- data/lib/typero/type/types/label.rb +0 -15
- data/lib/typero/type/types/point.rb +0 -29
- data/lib/typero/type/types/string.rb +0 -23
- data/lib/typero/type/types/url.rb +0 -18
@@ -0,0 +1,26 @@
|
|
1
|
+
class Typero::BooleanType < Typero::Type
|
2
|
+
error :en, :unsupported_boolean, 'Unsupported boolean param value: %s'
|
3
|
+
|
4
|
+
def set
|
5
|
+
value do |_|
|
6
|
+
bool = _.to_s
|
7
|
+
|
8
|
+
if value == ''
|
9
|
+
false
|
10
|
+
elsif %w(true 1 on).include?(bool)
|
11
|
+
true
|
12
|
+
elsif %w(false 0 off).include?(bool)
|
13
|
+
false
|
14
|
+
else
|
15
|
+
error_for :unsupported_boolean, bool
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def db_schema
|
21
|
+
[:boolean, {
|
22
|
+
default: opts[:default] || false
|
23
|
+
}]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# you should not use this filed for currency calculations
|
2
|
+
# use integer and covert in code
|
3
|
+
# Example: use cents and divide by 100 for $
|
4
|
+
|
5
|
+
require_relative './float_type'
|
6
|
+
|
7
|
+
class Typero::CurrencyType < Typero::FloatType
|
8
|
+
|
9
|
+
def set
|
10
|
+
value { |data| data.to_f.round(2) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def db_schema
|
14
|
+
[:decimal, {
|
15
|
+
precision: 8,
|
16
|
+
scale: 2
|
17
|
+
}]
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Typero::DateType < Typero::Type
|
2
|
+
opts :min, 'Smallest date-time allowed'
|
3
|
+
opts :max, 'Maximal date-time allowed'
|
4
|
+
|
5
|
+
error :en, :min_date, 'Minimal allowed date is %s'
|
6
|
+
error :en, :max_date, 'Maximal allowed date is %s'
|
7
|
+
|
8
|
+
def set
|
9
|
+
unless [Date].include?(value.class)
|
10
|
+
value { |data| DateTime.parse(data) }
|
11
|
+
end
|
12
|
+
|
13
|
+
value { |data| DateTime.new(data.year, data.month, data.day) }
|
14
|
+
|
15
|
+
check_date_min_max
|
16
|
+
end
|
17
|
+
|
18
|
+
def db_schema
|
19
|
+
[:date, {}]
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def check_date_min_max
|
25
|
+
if min = opts[:min]
|
26
|
+
min = DateTime.parse(min)
|
27
|
+
error_for(:min_date, min) % min if min > value
|
28
|
+
end
|
29
|
+
|
30
|
+
if max = opts[:max]
|
31
|
+
max = DateTime.parse(max)
|
32
|
+
error_for(:max_date, max) % max if value > max
|
33
|
+
end
|
34
|
+
|
35
|
+
value
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative 'date_type'
|
2
|
+
|
3
|
+
class Typero::DatetimeType < Typero::DateType
|
4
|
+
opts :min, 'Smallest date allowed'
|
5
|
+
opts :max, 'Maximal date allowed'
|
6
|
+
|
7
|
+
def set
|
8
|
+
unless [Time, DateTime].include?(value.class)
|
9
|
+
value { |data| DateTime.parse(data) }
|
10
|
+
end
|
11
|
+
|
12
|
+
check_date_min_max
|
13
|
+
end
|
14
|
+
|
15
|
+
def db_schema
|
16
|
+
[:datetime]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Typero::EmailType < Typero::Type
|
2
|
+
error :en, :not_8_chars_error, 'is not having at least 8 characters'
|
3
|
+
error :en, :missing_monkey_error, 'is missing @'
|
4
|
+
|
5
|
+
def set
|
6
|
+
value do |email|
|
7
|
+
email.downcase.gsub(/\s+/,'+')
|
8
|
+
end
|
9
|
+
|
10
|
+
error_for(:not_8_chars_error) unless value.to_s.length > 7
|
11
|
+
error_for(:missing_monkey_error) unless value.include?('@')
|
12
|
+
end
|
13
|
+
|
14
|
+
def db_schema
|
15
|
+
[:string, {
|
16
|
+
limit: @opts[:max] || 120
|
17
|
+
}]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class Typero::FloatType < Typero::Type
|
2
|
+
opts :min, 'Minimum value'
|
3
|
+
opts :max, 'Maximun value'
|
4
|
+
opts :round, 'Round to (decimal spaces)'
|
5
|
+
|
6
|
+
def set
|
7
|
+
@value =
|
8
|
+
if opts[:round]
|
9
|
+
value.to_f.round(opts[:round])
|
10
|
+
else
|
11
|
+
value.to_f
|
12
|
+
end
|
13
|
+
|
14
|
+
error_for(:min_length_error, opts[:min], value) if opts[:min] && value < opts[:min]
|
15
|
+
error_for(:max_length_error, opts[:max], value) if opts[:max] && value > opts[:max]
|
16
|
+
end
|
17
|
+
|
18
|
+
def db_schema
|
19
|
+
opts = {}
|
20
|
+
opts[:null] = false if opts[:required]
|
21
|
+
[:float, opts]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class Typero::HashType < Typero::Type
|
2
|
+
error :en, :not_hash_type_error, 'value is not hash type'
|
3
|
+
|
4
|
+
def set
|
5
|
+
if value.is_a?(String) && value[0,1] == '{'
|
6
|
+
@value = JSON.load(value)
|
7
|
+
end
|
8
|
+
|
9
|
+
@value ||= {}
|
10
|
+
|
11
|
+
error_for(:not_hash_type_error) unless @value.respond_to?(:keys) && @value.respond_to?(:values)
|
12
|
+
|
13
|
+
if opts[:allow]
|
14
|
+
for key in @value.keys
|
15
|
+
@value.delete(key) unless opts[:allow].include?(key)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def default
|
21
|
+
{}
|
22
|
+
end
|
23
|
+
|
24
|
+
def db_schema
|
25
|
+
[:jsonb, {
|
26
|
+
null: false,
|
27
|
+
default: '{}'
|
28
|
+
}]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -7,22 +7,16 @@ class Typero::ImageType < Typero::Type
|
|
7
7
|
opts :strict, 'Force image to have known extension (%s)' % FORMATS.join(', ')
|
8
8
|
|
9
9
|
def set
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
def validate
|
14
|
-
error_for(:image_not_starting_error) unless @value =~ /^https?:\/\/./
|
10
|
+
error_for(:image_not_starting_error) unless value =~ /^https?:\/\/./
|
15
11
|
|
16
12
|
if opts[:strict]
|
17
|
-
ext =
|
13
|
+
ext = value.split('.').last.downcase
|
18
14
|
error_for(:image_not_image_format) unless FORMATS.include?(ext)
|
19
15
|
end
|
20
16
|
end
|
21
17
|
|
22
|
-
def
|
23
|
-
|
24
|
-
opts[:null] = false if @opts[:required]
|
25
|
-
[:string, opts]
|
18
|
+
def db_schema
|
19
|
+
[:string]
|
26
20
|
end
|
27
21
|
end
|
28
22
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class Typero::IntegerType < Typero::Type
|
2
|
+
opts :min, 'Minimum value'
|
3
|
+
opts :max, 'Maximun value'
|
4
|
+
|
5
|
+
def set
|
6
|
+
value(&:to_i)
|
7
|
+
|
8
|
+
error_for(:min_value_error, opts[:min], value) if opts[:min] && value < opts[:min]
|
9
|
+
error_for(:max_value_error, opts[:max], value) if opts[:max] && value > opts[:max]
|
10
|
+
end
|
11
|
+
|
12
|
+
def db_schema
|
13
|
+
[:integer, {}]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Typero::LabelType < Typero::Type
|
2
|
+
def set
|
3
|
+
value do |data|
|
4
|
+
data
|
5
|
+
.to_s
|
6
|
+
.gsub(/\s+/,'-')
|
7
|
+
.gsub(/[^\w\-]/,'')
|
8
|
+
.gsub(/\-+/, '-')[0,30]
|
9
|
+
.downcase
|
10
|
+
end
|
11
|
+
|
12
|
+
error_for(:unallowed_characters_error) unless value =~ /^[\w\-]+$/
|
13
|
+
end
|
14
|
+
|
15
|
+
def db_schema
|
16
|
+
[:string, {
|
17
|
+
limit: 30
|
18
|
+
}]
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class Typero::LocaleType < Typero::Type
|
2
|
+
error :en, :locale_bad_format, 'Locale "%s" is in bad format (should be xx or xx-xx)'
|
3
|
+
|
4
|
+
def set
|
5
|
+
error_for(:locale_bad_format, value) unless value =~ /^[\w\-]{2,5}$/
|
6
|
+
end
|
7
|
+
|
8
|
+
def db_schema
|
9
|
+
[:string, { limit: 5 }]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Typero::ModelType < Typero::Type
|
2
|
+
def set
|
3
|
+
value(&:to_h)
|
4
|
+
|
5
|
+
errors = {}
|
6
|
+
|
7
|
+
schema = opts[:model].is_a?(Typero::Schema) ? opts[:model] : Typero.schema(opts[:model])
|
8
|
+
|
9
|
+
# by default models in schems are strict true (remove undefined keys)
|
10
|
+
schema.validate value, strict: true do |field, error|
|
11
|
+
errors[field] = error
|
12
|
+
end
|
13
|
+
|
14
|
+
raise TypeError.new errors.to_json if errors.keys.first
|
15
|
+
end
|
16
|
+
|
17
|
+
def db_schema
|
18
|
+
[:jsonb, {
|
19
|
+
null: false
|
20
|
+
}]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -2,18 +2,15 @@ class Typero::OibType < Typero::Type
|
|
2
2
|
error :en, :not_an_oib_error, 'not in an OIB format'
|
3
3
|
|
4
4
|
def set
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
def validate
|
9
|
-
error_for(:not_an_oib_error) unless check?(@value)
|
5
|
+
value do |data|
|
6
|
+
check?(data) ? data.to_i : error_for(:not_an_oib_error)
|
7
|
+
end
|
10
8
|
end
|
11
9
|
|
12
|
-
def
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
[:string, opts]
|
10
|
+
def db_schema
|
11
|
+
[:string, {
|
12
|
+
limit: 11
|
13
|
+
}]
|
17
14
|
end
|
18
15
|
|
19
16
|
private
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# for postgres - select st_asewkt(lon_lat) || st_astext(lon_lat)
|
2
|
+
# point = @object.class.xselect("ST_AsText(#{field}) as #{field}").where(id: @object.id).first[field.to_sym]
|
3
|
+
|
4
|
+
class Typero::PointType < Typero::Type
|
5
|
+
def set
|
6
|
+
if value.include?('/@')
|
7
|
+
point = value.split('/@', 2).last.split(',')
|
8
|
+
value { [point[0], point[1]].join(',') }
|
9
|
+
end
|
10
|
+
|
11
|
+
if !value.include?('POINT') && value.include?(',')
|
12
|
+
point = value.sub(/,\s*/, ' ')
|
13
|
+
value { 'SRID=4326;POINT(%s)' % point }
|
14
|
+
end
|
15
|
+
|
16
|
+
if value && value.include?(',') && !value =~ /^SRID=4326;POINT\(/
|
17
|
+
error_for(:unallowed_characters_error)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def db_schema
|
22
|
+
[:geography, {}]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Typero::StringType < Typero::Type
|
2
|
+
opts :min, 'Minimun string length'
|
3
|
+
opts :max, 'Maximun string length'
|
4
|
+
opts :downcase, 'is the string in downcase?'
|
5
|
+
|
6
|
+
def set
|
7
|
+
value(&:to_s)
|
8
|
+
value(&:downcase) if opts[:downcase]
|
9
|
+
|
10
|
+
# this is database default for string type and it is good to define default unless defined
|
11
|
+
opts[:max] ||= 255
|
12
|
+
|
13
|
+
error_for(:min_length_error, opts[:min], value.length) if opts[:min] && value.length < opts[:min]
|
14
|
+
error_for(:max_length_error, opts[:max], value.length) if opts[:max] && value.length > opts[:max]
|
15
|
+
end
|
16
|
+
|
17
|
+
def db_schema
|
18
|
+
[:string, {
|
19
|
+
limit: @opts[:max] || 255
|
20
|
+
}]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -1,12 +1,10 @@
|
|
1
|
-
require_relative '
|
1
|
+
require_relative 'string_type'
|
2
2
|
|
3
3
|
class Typero::TextType < Typero::StringType
|
4
4
|
opts :min, 'Minimun string length'
|
5
5
|
opts :max, 'Maximun string length'
|
6
6
|
|
7
|
-
def
|
8
|
-
|
9
|
-
opts[:null] = false if @opts[:required]
|
10
|
-
[:text, opts]
|
7
|
+
def db_schema
|
8
|
+
[:text, {}]
|
11
9
|
end
|
12
10
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Typero::TimezoneType < Typero::Type
|
2
|
+
error :en, :invalid_time_zone, 'Invalid time zone'
|
3
|
+
|
4
|
+
def set
|
5
|
+
TZInfo::Timezone.get(value)
|
6
|
+
rescue TZInfo::InvalidTimezoneIdentifier
|
7
|
+
error_for :invalid_time_zone
|
8
|
+
end
|
9
|
+
|
10
|
+
def db_schema
|
11
|
+
[:string, { length: 50 }]
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class Typero::UrlType < Typero::Type
|
2
|
+
error :en, :url_not_starting_error, 'URL is not starting with http or https'
|
3
|
+
|
4
|
+
def set
|
5
|
+
parts = value.split('://')
|
6
|
+
error_for(:url_not_starting_error) unless parts[1]
|
7
|
+
end
|
8
|
+
|
9
|
+
def db_schema
|
10
|
+
[:string, {}]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
data/lib/typero/typero.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# rules = Typero.
|
1
|
+
# rules = Typero.schema do
|
2
2
|
# set :name, String, req: true
|
3
3
|
# set :email, :email, req: true
|
4
4
|
# set :skills, [:email], min: 2
|
@@ -6,7 +6,7 @@
|
|
6
6
|
#
|
7
7
|
# or
|
8
8
|
#
|
9
|
-
# rules = Typero.
|
9
|
+
# rules = Typero.schema do
|
10
10
|
# string :name, req: true
|
11
11
|
# email :email, req: true
|
12
12
|
# email [:skills], min: 2
|
@@ -16,162 +16,93 @@
|
|
16
16
|
# rules.valid?
|
17
17
|
# rules.validate(@object) { |errors| ... }
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
class << self
|
23
|
-
# check and coerce value
|
24
|
-
# Typero.set(:label, 'Foo bar') -> "foo-bar"
|
25
|
-
def set type, value, opts = {}, &block
|
26
|
-
check = Typero::Type.load(type).new value, opts
|
27
|
-
check.set
|
28
|
-
check.validate
|
29
|
-
check.value
|
30
|
-
rescue TypeError => error
|
31
|
-
if block
|
32
|
-
block.call error
|
33
|
-
false
|
34
|
-
else
|
35
|
-
raise error
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
###
|
19
|
+
module Typero
|
20
|
+
extend self
|
41
21
|
|
42
|
-
|
43
|
-
def initialize &block
|
44
|
-
raise "Params not defined" unless block_given?
|
45
|
-
@schema = Params.new &block
|
46
|
-
end
|
47
|
-
|
48
|
-
# validates any instance object with hash variable interface
|
49
|
-
# it also coarces values
|
50
|
-
def validate object
|
51
|
-
@object = object
|
52
|
-
@errors = {}
|
53
|
-
|
54
|
-
@schema.rules.each do |field, opts|
|
55
|
-
# set value to default if value is blank and default given
|
56
|
-
@object[field] = opts[:default] if opts[:default] && @object[field].blank?
|
22
|
+
VERSION = File.read File.expand_path "../../.version", File.dirname(__FILE__)
|
57
23
|
|
58
|
-
|
59
|
-
|
24
|
+
# check and coerce value
|
25
|
+
# Typero.type(:label) -> Typero::LabelType
|
26
|
+
# Typero.type(:label, 'Foo bar') -> "foo-bar"
|
27
|
+
def type klass_name, value = :_undefined, opts = {}, &block
|
28
|
+
klass = Typero::Type.load(klass_name)
|
60
29
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
30
|
+
if value == :_undefined
|
31
|
+
klass
|
32
|
+
else
|
33
|
+
begin
|
34
|
+
check = klass.new value, opts
|
35
|
+
check.get
|
36
|
+
rescue TypeError => error
|
37
|
+
if block
|
38
|
+
block.call error
|
39
|
+
false
|
40
|
+
else
|
41
|
+
raise error
|
65
42
|
end
|
66
|
-
|
67
|
-
value = value
|
68
|
-
.map { |el| check_filed_value field, el, opts }
|
69
|
-
.map { |el| el.to_s == '' ? nil : el }
|
70
|
-
.compact
|
71
|
-
|
72
|
-
value = Set.new(value).to_a unless opts[:duplicates]
|
73
|
-
|
74
|
-
opts[:max_count] ||= 100
|
75
|
-
add_error(field, 'Max number of array elements is %d, you have %d' % [opts[:max_count], value.length], opts) if value.length > opts[:max_count]
|
76
|
-
|
77
|
-
check_required field, value.first, opts
|
78
|
-
else
|
79
|
-
value = check_filed_value field, value, opts
|
80
|
-
check_required field, value, opts
|
81
|
-
end
|
82
|
-
|
83
|
-
# if value is not list of allowed values, raise error
|
84
|
-
if opts[:allowed] && !opts[:values].include?(value)
|
85
|
-
add_error field, 'Value "%s" is not allowed' % value, opts
|
86
43
|
end
|
87
|
-
|
88
|
-
# present empty string values as nil
|
89
|
-
@object[field] = value.to_s.sub(/\s+/, '') == '' ? nil : value
|
90
|
-
end
|
91
|
-
|
92
|
-
if @errors.keys.length > 0 && block_given?
|
93
|
-
@errors.each { |k, v| yield(k, v) }
|
94
44
|
end
|
95
|
-
|
96
|
-
@errors
|
97
45
|
end
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
#
|
105
|
-
def
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
out
|
120
|
-
end
|
121
|
-
|
122
|
-
# iterate trough all the ruels via block interface
|
123
|
-
# schema.rules do |field, opts|
|
124
|
-
# schema.rules(:url) do |field, opts|
|
125
|
-
def rules(filter = nil, &block)
|
126
|
-
return @schema.rules unless filter
|
127
|
-
out = @schema.rules
|
128
|
-
out = out.select { |k, v| v[:type].to_s == filter.to_s || v[:array_type].to_s == filter.to_s } if filter
|
129
|
-
return out unless block_given?
|
130
|
-
|
131
|
-
out.each { |k, v| yield k, v }
|
132
|
-
end
|
133
|
-
|
134
|
-
private
|
135
|
-
|
136
|
-
# adds error to array or prefixes with field name
|
137
|
-
def add_error field, msg, opts
|
138
|
-
if @errors[field]
|
139
|
-
@errors[field] += ", %s" % msg
|
46
|
+
alias :set :type
|
47
|
+
|
48
|
+
# load or set type schema
|
49
|
+
# Typero.schema(:blog) { ... }
|
50
|
+
# Typero.schema(:blog, type: :model) { ... }
|
51
|
+
# Typero.schema(:blog)
|
52
|
+
# Typero.schema(type: :model)
|
53
|
+
def schema name=nil, opts=nil, &block
|
54
|
+
klass = name.to_s.classify if name && !name.is_a?(Hash)
|
55
|
+
|
56
|
+
if block_given?
|
57
|
+
Typero::Schema.new(&block).tap do |schema|
|
58
|
+
if klass
|
59
|
+
Typero::Schema::SCHEMAS[klass] = schema
|
60
|
+
|
61
|
+
if opts && opts[:type]
|
62
|
+
Typero::Schema::TYPES[opts[:type]] ||= []
|
63
|
+
Typero::Schema::TYPES[opts[:type]].push klass unless Typero::Schema::TYPES[opts[:type]].include?(klass)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
140
67
|
else
|
141
|
-
|
142
|
-
|
143
|
-
|
68
|
+
# Schema not given, get schema
|
69
|
+
if name.is_a?(Hash)
|
70
|
+
# Typero.schema type: :model
|
71
|
+
if type = name[:type]
|
72
|
+
Typero::Schema::TYPES[type]
|
73
|
+
end
|
74
|
+
elsif klass
|
75
|
+
# Typero.schema :user
|
76
|
+
schema = Typero::Schema::SCHEMAS[klass]
|
77
|
+
schema ||= class_finder klass, :schema
|
78
|
+
schema || nil
|
79
|
+
else
|
80
|
+
raise ArgumentError, 'Schema type not defined.'
|
144
81
|
end
|
145
|
-
|
146
|
-
@errors[field] = msg
|
147
82
|
end
|
148
83
|
end
|
149
84
|
|
150
|
-
def
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
return if !opts[:required] || value
|
156
|
-
msg = opts[:required].class == TrueClass ? "is required" : opts[:required]
|
157
|
-
add_error field, msg, opts
|
85
|
+
def defined? name
|
86
|
+
Typero::Type.load name
|
87
|
+
true
|
88
|
+
rescue ArgumentError
|
89
|
+
false
|
158
90
|
end
|
159
91
|
|
160
|
-
|
161
|
-
return unless value
|
92
|
+
private
|
162
93
|
|
163
|
-
|
164
|
-
|
165
|
-
|
94
|
+
# class_finder :user, :exporter, :representer
|
95
|
+
# find first UserExporter, User::Exporter, User::Representer, UserRepresenter
|
96
|
+
def class_finder *args
|
97
|
+
name = args.shift.to_s.classify
|
166
98
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
check.value
|
172
|
-
rescue TypeError => e
|
173
|
-
add_error field, e.message, opts
|
99
|
+
for el in args
|
100
|
+
for separator in ['_','/']
|
101
|
+
klass = [name, el].join(separator).classify
|
102
|
+
return klass.constantize if const_defined? klass
|
174
103
|
end
|
175
104
|
end
|
105
|
+
|
106
|
+
nil
|
176
107
|
end
|
177
108
|
end
|