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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 92cf598bbfb6f6b241b3f9d54e74ff8354f1a31c
4
- data.tar.gz: 7d87b59b9fdee781f18ffebee6bfc161b81791a1
3
+ metadata.gz: 486d7ae19f1e96968faec9db6c8b37f99f8d24d7
4
+ data.tar.gz: de030fc9d1d929f6a8bfd8b8699dcd6ebc544051
5
5
  SHA512:
6
- metadata.gz: 56d648431f62c1a64e47ac39f70e0cb305bef0ff261fae06d476b5d8abb20a3e03e59dccb217f19b265469738b0097f343ff908c35a60f307e47608f9bb838f8
7
- data.tar.gz: 0339f991c56ca2690c74041e2559ac9501fedf3b5d85b5e88d11406fe3029e97ffbb697f1e1198c7e3df669c7928f81704f7c5b56d8d8446d1ff74bacec6098b
6
+ metadata.gz: 8612e66e0904743bedc0aa646f40004b4b82707b3cf74f3858d2588c223ccc9ac57c4a407b6f1ec3d5c2d7bcb31d26a9fd49477ec3c3c99e55bb3d52293498f8
7
+ data.tar.gz: ecd369fa535014e651faea154e010f23d5eaef43924a359692aef03a540ffb474235677991377cd131c03a3b99caa1cb59781fdd05a818acf404578bbc95e782
@@ -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','')}" }
@@ -0,0 +1,16 @@
1
+ module Typero
2
+
3
+ # adds hash interface to models
4
+ module Hash
5
+ def [](k)
6
+ @attrs ||= {}
7
+ @attrs[k]
8
+ end
9
+
10
+ def []=(k,v)
11
+ @attrs ||= {}
12
+ @attrs[k] = v
13
+ end
14
+ end
15
+
16
+ end
@@ -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
@@ -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,13 @@
1
+ module Typero
2
+ class BooleanType < Typero::Type
3
+ def default
4
+ false
5
+ end
6
+
7
+ def set(value)
8
+ value = false if [0, '0', 'false'].index(value)
9
+ !!value
10
+ end
11
+ end
12
+ end
13
+
@@ -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
+
@@ -0,0 +1,8 @@
1
+ module Typero
2
+ class HashType < Typero::Type
3
+ def default
4
+ {}
5
+ end
6
+ end
7
+ end
8
+
@@ -0,0 +1,8 @@
1
+ module Typero
2
+ class IntegerType < Typero::Type
3
+ def set(value)
4
+ value.to_i
5
+ end
6
+ end
7
+ end
8
+
@@ -0,0 +1,13 @@
1
+ module Typero
2
+ class LabelType < Typero::Type
3
+ def set(value)
4
+ value.to_s.gsub(/[^\w\-]/,'')[0,30].downcase
5
+ end
6
+
7
+ def validate(value)
8
+ raise TypeError, "having unallowed characters" unless value =~ /^[\w\-]+$/
9
+ true
10
+ end
11
+ end
12
+ end
13
+
@@ -0,0 +1,10 @@
1
+ module Typero
2
+ class StringType < Typero::Type
3
+ def set(value)
4
+ value = value.to_s
5
+ value = value.downcase if @opts[:downcase]
6
+ value
7
+ end
8
+ end
9
+ end
10
+
@@ -0,0 +1,9 @@
1
+ module Typero
2
+ class UrlType < Typero::Type
3
+ def validate(value)
4
+ raise TypeError, 'not starting with http' unless value =~ /^https?:\/\/./
5
+ true
6
+ end
7
+ end
8
+ end
9
+
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: '0.2'
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-10-09 00:00:00.000000000 Z
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.din@gmail.com
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