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 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