typero 0.2 → 0.2.1
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/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
|