typero 0.2 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/typero.rb +7 -6
- data/lib/typero/hash.rb +16 -0
- data/lib/typero/instance.rb +52 -0
- data/lib/typero/schema.rb +65 -0
- data/lib/typero/type.rb +107 -0
- data/lib/typero/type/array.rb +25 -0
- data/lib/typero/type/boolean.rb +13 -0
- data/lib/typero/type/email.rb +16 -0
- data/lib/typero/type/float.rb +16 -0
- data/lib/typero/type/hash.rb +8 -0
- data/lib/typero/type/integer.rb +8 -0
- data/lib/typero/type/label.rb +13 -0
- data/lib/typero/type/string.rb +10 -0
- data/lib/typero/type/url.rb +9 -0
- metadata +17 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 486d7ae19f1e96968faec9db6c8b37f99f8d24d7
|
4
|
+
data.tar.gz: de030fc9d1d929f6a8bfd8b8699dcd6ebc544051
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8612e66e0904743bedc0aa646f40004b4b82707b3cf74f3858d2588c223ccc9ac57c4a407b6f1ec3d5c2d7bcb31d26a9fd49477ec3c3c99e55bb3d52293498f8
|
7
|
+
data.tar.gz: ecd369fa535014e651faea154e010f23d5eaef43924a359692aef03a540ffb474235677991377cd131c03a3b99caa1cb59781fdd05a818acf404578bbc95e782
|
data/lib/typero.rb
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
require_relative './typero/instance'
|
2
|
+
require_relative './typero/schema'
|
3
|
+
require_relative './typero/type'
|
4
|
+
require_relative './typero/hash'
|
5
|
+
|
6
|
+
Dir["#{File.dirname(__FILE__)}/typero/type/*.rb"].each{ |f| load f }
|
7
|
+
|
1
8
|
# attribute :url, :url
|
2
9
|
# attribute :name, req:'Link name is required'
|
3
10
|
# attribute :tags, Array[:label]
|
@@ -81,9 +88,3 @@ module Typero
|
|
81
88
|
end
|
82
89
|
end
|
83
90
|
|
84
|
-
require './lib/typero/instance'
|
85
|
-
require './lib/typero/schema'
|
86
|
-
require './lib/typero/type'
|
87
|
-
require './lib/typero/hash'
|
88
|
-
|
89
|
-
Dir['lib/typero/type/*.rb'].each{ |f| require "./#{f.sub('.rb','')}" }
|
data/lib/typero/hash.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
module Typero
|
2
|
+
module Instance
|
3
|
+
def self.included(base)
|
4
|
+
def base.attribute(name, *args)
|
5
|
+
if !args[0]
|
6
|
+
opts = { type: :string }
|
7
|
+
elsif args[0].class.to_s == 'Hash'
|
8
|
+
if args[0].keys.length == 0
|
9
|
+
opts = { type: :hash }
|
10
|
+
else
|
11
|
+
type = args[0][:type] || :string
|
12
|
+
opts = args[0].merge( type: type )
|
13
|
+
end
|
14
|
+
elsif args[1]
|
15
|
+
opts = args[1]
|
16
|
+
opts[:type] = args[0]
|
17
|
+
else
|
18
|
+
opts = { type: args[0] }
|
19
|
+
end
|
20
|
+
|
21
|
+
if opts[:type].class.to_s == 'Array' && opts[:type][0] # Array[:email] -> array of emails
|
22
|
+
opts[:array_type] = opts[:type][0].to_s.downcase.to_sym
|
23
|
+
opts[:type] = :array
|
24
|
+
end
|
25
|
+
|
26
|
+
opts[:type] = opts[:type].to_s.downcase.to_sym
|
27
|
+
opts[:type] = :array if opts[:type] == :[]
|
28
|
+
opts[:req] = "#{name.to_s.humanize.capitalize} is required" if opts[:req].class == TrueClass
|
29
|
+
|
30
|
+
Typero.define_instance(self, name, opts)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# def attributes=(opts)
|
35
|
+
# for k,v in opts
|
36
|
+
# send("#{k}=", v)
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
|
40
|
+
def attribute_errors
|
41
|
+
# hash = InstanceAttributes.opts[self.class.to_s]
|
42
|
+
klass = self.class.to_s
|
43
|
+
opts = Typero.opts[klass]
|
44
|
+
return [] unless opts
|
45
|
+
errors = []
|
46
|
+
for k, v in opts
|
47
|
+
errors.push [k, v.opts[:req]] if v.opts[:req] && !v.present?(self[k])
|
48
|
+
end
|
49
|
+
errors
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# validates hash against the schema
|
2
|
+
# good if you can create validate objects and check against for function parameters
|
3
|
+
# use whenever you want to check hash values of variables
|
4
|
+
# in Lux FW, used in api cell
|
5
|
+
|
6
|
+
module Typero
|
7
|
+
class Schema
|
8
|
+
class << self
|
9
|
+
# loads schema from hash and creates schema object
|
10
|
+
def load_schema(hash)
|
11
|
+
validate = new
|
12
|
+
for k,v in hash
|
13
|
+
validate.set(k,v)
|
14
|
+
end
|
15
|
+
validate
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
###
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@check = {}
|
23
|
+
end
|
24
|
+
|
25
|
+
# set field values to check
|
26
|
+
# :age, Integer, { min:18, max:110 }
|
27
|
+
# :email, :email, { req:false }
|
28
|
+
def set(field, opts={}, &block)
|
29
|
+
opts[:req] ||= true unless opts[:req].class == FalseClass
|
30
|
+
opts[:func] = block if block_given?
|
31
|
+
opts[:type] ||= String
|
32
|
+
@check[field] = opts
|
33
|
+
end
|
34
|
+
|
35
|
+
# check agains hash of values { email:'dux@net.hr', age:'40' }
|
36
|
+
def check(hash)
|
37
|
+
errors = {}
|
38
|
+
for field in @check.keys
|
39
|
+
value = hash[field]
|
40
|
+
check_hash = @check[field]
|
41
|
+
type = check_hash[:type]
|
42
|
+
|
43
|
+
if value.blank? && check_hash[:req].class != FalseClass
|
44
|
+
errors[field] = check_hash[:req].kind_of?(String) ? check_hash[:req] : "#{field.to_s.capitalize} is required"
|
45
|
+
next
|
46
|
+
end
|
47
|
+
|
48
|
+
if check_hash[:func]
|
49
|
+
begin
|
50
|
+
check_hash[:func].call(value.to_s)
|
51
|
+
rescue
|
52
|
+
errors[field] = $!.message
|
53
|
+
end
|
54
|
+
elsif !Typero.validate(value, type)
|
55
|
+
errors[field] = "#{field.to_s.capitalize} is #{Typero.last_error}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
errors.keys.length > 0 ? errors : nil
|
59
|
+
end
|
60
|
+
|
61
|
+
def keys
|
62
|
+
@check.keys
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/typero/type.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
# str = Typero::StringType.new(req:true, default:'Miki')
|
2
|
+
# str.set_value('Dino')
|
3
|
+
# puts str.get_value
|
4
|
+
|
5
|
+
# str = Typero::EmailType.new()
|
6
|
+
# str.set_value('dux|at|dux.net') -> raises eror
|
7
|
+
module Typero
|
8
|
+
class Type
|
9
|
+
attr_accessor :opts
|
10
|
+
|
11
|
+
### SAFE TO OVERLOAD: START
|
12
|
+
|
13
|
+
# default min implementation
|
14
|
+
def min(value, length)
|
15
|
+
raise TypeError, "Min #{@type} lenght for #{@name} is #{length}, you have #{value.to_s.length}" if value.to_s.length < length
|
16
|
+
end
|
17
|
+
|
18
|
+
# default max implementation
|
19
|
+
def max(value, length)
|
20
|
+
raise TypeError, "Max #{@type} length for #{@name} is #{length}, you have #{value.to_s.length}" if value.to_s.length > length
|
21
|
+
end
|
22
|
+
|
23
|
+
# if value is not blank, it is sent to set method
|
24
|
+
def set(value)
|
25
|
+
value
|
26
|
+
end
|
27
|
+
|
28
|
+
# if value is blank?, trigger default
|
29
|
+
# for example set it to false for boolean type and [] for array type
|
30
|
+
def default
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
|
34
|
+
# default validation for any type
|
35
|
+
def validate(what)
|
36
|
+
true
|
37
|
+
end
|
38
|
+
|
39
|
+
### SAFE TO OVERLOAD: END
|
40
|
+
|
41
|
+
# set options
|
42
|
+
def initialize(opts={})
|
43
|
+
@type = self.class.to_s.split('::')[1].sub('Type','').downcase.to_sym
|
44
|
+
@opts = opts
|
45
|
+
@name = opts.delete(:name)
|
46
|
+
end
|
47
|
+
|
48
|
+
def check_type(type)
|
49
|
+
type_klass = "Typero::#{type.to_s.classify}Type"
|
50
|
+
(type_klass.constantize rescue false) ? true : false
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_value(instance)
|
54
|
+
# get current var value
|
55
|
+
value = instance.respond_to?('[]') ? instance[@name] : instance.instance_variable_get("@#{@name}")
|
56
|
+
if value.blank?
|
57
|
+
# if blank check for default
|
58
|
+
if @opts[:default]
|
59
|
+
@opts[:default].class.to_s == 'Proc' ? @opts[:default].call(instance) : @opts[:default]
|
60
|
+
else
|
61
|
+
return default
|
62
|
+
end
|
63
|
+
else
|
64
|
+
value
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def set_value(instance, value=nil)
|
69
|
+
if !value.blank?
|
70
|
+
# for user emails, once defined cant be overitten
|
71
|
+
if @opts[:protected] && get_value(instance) && get_value(instance) != value
|
72
|
+
raise TypeError, @opts[:protected].class == TrueClass ? "#{@name.capitalize} is allready defined and can't be overwritten." : @opts[:protected]
|
73
|
+
end
|
74
|
+
|
75
|
+
value = set(value)
|
76
|
+
|
77
|
+
# search for unique fields on set, say for email
|
78
|
+
# so it is not checked on save, it is checked on set
|
79
|
+
if @opts[:uniq]
|
80
|
+
filter = instance.class.select(:id).where("#{@name}=?", value)
|
81
|
+
filter = filter.where('id<>?', instance.id) if instance.id
|
82
|
+
raise TypeError, @opts[:uniq].class == TrueClass ? "Field #{@name} is uniqe and allready exists" : @opts[:uniq] if filter.first
|
83
|
+
end
|
84
|
+
|
85
|
+
min(value, @opts[:min]) if @opts[:min]
|
86
|
+
max(value, @opts[:max]) if @opts[:max]
|
87
|
+
|
88
|
+
validate(value)
|
89
|
+
elsif @opts[:req]
|
90
|
+
msg = @opts[:req].class == TrueClass ? "is required" : @opts[:req]
|
91
|
+
raise TypeError, msg
|
92
|
+
else
|
93
|
+
value = default
|
94
|
+
end
|
95
|
+
|
96
|
+
if instance.respond_to?('[]')
|
97
|
+
# save to hash by default
|
98
|
+
instance[@name] = value
|
99
|
+
else
|
100
|
+
# fallback to instance variable if no hash (plain class, not AR or Sequel)
|
101
|
+
instance.instance_variable_set("@#{@name}", value)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Typero
|
2
|
+
class ArrayType < Typero::Type
|
3
|
+
def default
|
4
|
+
[]
|
5
|
+
end
|
6
|
+
|
7
|
+
def set(value)
|
8
|
+
value = value.to_s.split(/\s*,\s*/) unless value.class.to_s.index('Array')
|
9
|
+
if type = @opts[:array_type]
|
10
|
+
check_type(type)
|
11
|
+
value.each { |el| Typero.validate!(el, type) }
|
12
|
+
end
|
13
|
+
value
|
14
|
+
end
|
15
|
+
|
16
|
+
def min(value, length)
|
17
|
+
raise TypeError, "Min array lenght is #{length} elements" if value.length < length
|
18
|
+
end
|
19
|
+
|
20
|
+
def max(value, length)
|
21
|
+
raise TypeError, "Max array lenght is #{length} elements" if value.length > length
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Typero
|
2
|
+
class EmailType < Typero::Type
|
3
|
+
def set(value)
|
4
|
+
value.downcase
|
5
|
+
end
|
6
|
+
|
7
|
+
def validate(value)
|
8
|
+
raise TypeError, 'not having at least 8 characters' unless value.to_s.length > 7
|
9
|
+
raise TypeError, 'missing @' unless value.include?('@')
|
10
|
+
raise TypeError, 'in wrong domain' unless value =~ /\.\w{2,4}$/
|
11
|
+
raise TypeError, 'in wrong format' unless value =~ /^[\w\-\.]+\@[\w\-\.]+$/i
|
12
|
+
true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Typero
|
2
|
+
class FloatType < Typero::Type
|
3
|
+
def set(value)
|
4
|
+
value.to_f
|
5
|
+
end
|
6
|
+
|
7
|
+
def min(value, length)
|
8
|
+
raise TypeError, "Min #{@type} lenght for #{@name} is #{length}, you have #{value}" if value.to_f < length
|
9
|
+
end
|
10
|
+
|
11
|
+
def max(value, length)
|
12
|
+
raise TypeError, "Max #{@type} length for #{@name} is #{length}, you have #{value}" if value.to_f > length
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
metadata
CHANGED
@@ -1,23 +1,36 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: typero
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dino Reic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-09-26 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Simple and fast ruby type system. Enforce types as Array, Email, Boolean
|
14
14
|
for ruby class instances
|
15
|
-
email: reic.
|
15
|
+
email: reic.dino@gmail.com
|
16
16
|
executables: []
|
17
17
|
extensions: []
|
18
18
|
extra_rdoc_files: []
|
19
19
|
files:
|
20
|
-
- lib/typero.rb
|
20
|
+
- "./lib/typero.rb"
|
21
|
+
- "./lib/typero/hash.rb"
|
22
|
+
- "./lib/typero/instance.rb"
|
23
|
+
- "./lib/typero/schema.rb"
|
24
|
+
- "./lib/typero/type.rb"
|
25
|
+
- "./lib/typero/type/array.rb"
|
26
|
+
- "./lib/typero/type/boolean.rb"
|
27
|
+
- "./lib/typero/type/email.rb"
|
28
|
+
- "./lib/typero/type/float.rb"
|
29
|
+
- "./lib/typero/type/hash.rb"
|
30
|
+
- "./lib/typero/type/integer.rb"
|
31
|
+
- "./lib/typero/type/label.rb"
|
32
|
+
- "./lib/typero/type/string.rb"
|
33
|
+
- "./lib/typero/type/url.rb"
|
21
34
|
homepage: http://rubygems.org/dux/typero
|
22
35
|
licenses:
|
23
36
|
- MIT
|