typero 0.4.0 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.version +1 -1
- data/lib/adapters/sequel.rb +74 -0
- data/lib/typero.rb +92 -68
- data/lib/typero/type.rb +3 -10
- data/lib/typero/type/array.rb +12 -1
- data/lib/typero/type/boolean.rb +6 -0
- data/lib/typero/type/currency.rb +17 -0
- data/lib/typero/type/date.rb +6 -0
- data/lib/typero/type/datetime.rb +6 -0
- data/lib/typero/type/email.rb +6 -0
- data/lib/typero/type/float.rb +6 -0
- data/lib/typero/type/geography.rb +13 -0
- data/lib/typero/type/hash.rb +4 -0
- data/lib/typero/type/integer.rb +6 -0
- data/lib/typero/type/label.rb +7 -0
- data/lib/typero/type/oib.rb +7 -0
- data/lib/typero/type/point.rb +25 -0
- data/lib/typero/type/string.rb +7 -0
- data/lib/typero/type/text.rb +7 -0
- data/lib/typero/type/url.rb +6 -0
- metadata +10 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3abfc7ee1372098804789576ac4fb36dbfb33a2cce2e48cd2dda70b975a2a1f6
|
4
|
+
data.tar.gz: 9ed9618bde6dd268b39f516428c63c07a3aa86006323a0dd0b231a421e6a4c68
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ab235a93802052f17166cf1bda8a3cd75ee20def1c669c9b5ccf7bb4d7633ae2ddffec6cc01f57e3bf2c98aaf652731a1deb7c2450e658da76ae8092e3790a1
|
7
|
+
data.tar.gz: 4430507594bdecbb95aff494ed0e8dc1a71d22111abecafec19a801d3d4445d1a32dfe5fd861b330515d7b63ba0a9867d53e088e1c2a3d206b13cf9147a09cd1
|
data/.version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.2
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'typero'
|
4
|
+
|
5
|
+
module Sequel::Plugins::TyperoAttributes
|
6
|
+
module ClassMethods
|
7
|
+
def attributes opts={}, &block
|
8
|
+
instance_variable_set :@typero, Typero.new(&block)
|
9
|
+
|
10
|
+
# attributes migrate: true do ...
|
11
|
+
AutoMigrate.typero to_s.tableize.to_sym if opts[:migrate] && Lux.config.migrate
|
12
|
+
end
|
13
|
+
|
14
|
+
def typero
|
15
|
+
instance_variable_get :@typero
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module InstanceMethods
|
20
|
+
# calling typero! on any object will validate all fields
|
21
|
+
def typero! field_name=nil
|
22
|
+
typero = self.class.typero || return
|
23
|
+
|
24
|
+
typero.validate(self) do |name, err|
|
25
|
+
errors.add(name, err) unless (errors.on(name) || []).include?(err)
|
26
|
+
end
|
27
|
+
|
28
|
+
# this are rules unique to database, so we check them here
|
29
|
+
typero.rules.each do |field, rule|
|
30
|
+
# check uniqe fields
|
31
|
+
if rule[:unique]
|
32
|
+
id = self[:id] || 0
|
33
|
+
value = self[field]
|
34
|
+
|
35
|
+
# we only check if field is changed
|
36
|
+
if value.present? && column_changed?(field) && self.class.xwhere('LOWER(%s)=LOWER(?) and id<>?' % field, value, id).first
|
37
|
+
error = rule[:unique].class == TrueClass ? %[Value '"#{value}"' for #{field} allready exists] : rule[:unique]
|
38
|
+
errors.add(field, error) unless (errors.on(field) || []).include?(error)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# check protected fields
|
43
|
+
if rule[:protected] && self[:id]
|
44
|
+
if column_changed?(field)
|
45
|
+
error = rule[:protected].class == TrueClass ? "value once defined can't be overwritten." : rule[:protected]
|
46
|
+
errors.add(field, error) unless (errors.on(field) || []).include?(error)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# check single field if single field given
|
52
|
+
if field_name
|
53
|
+
raise ArgumentError.new 'Field :%s not found in %s' % [field_name, self] unless self[field_name]
|
54
|
+
return unless errors.on(field_name)
|
55
|
+
|
56
|
+
errors.on(field_name).join(', ')
|
57
|
+
end
|
58
|
+
|
59
|
+
true
|
60
|
+
end
|
61
|
+
|
62
|
+
def validate
|
63
|
+
typero!
|
64
|
+
super
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
module DatasetMethods
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
Sequel::Model.plugin :typero_attributes
|
74
|
+
|
data/lib/typero.rb
CHANGED
@@ -43,7 +43,7 @@ class Typero
|
|
43
43
|
# Typero.set(:label, 'Foo bar') -> "foo-bar"
|
44
44
|
def set type, value, opts={}
|
45
45
|
check = Typero::Type.load(type).new value, opts
|
46
|
-
check.
|
46
|
+
check.value
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
@@ -52,76 +52,11 @@ class Typero
|
|
52
52
|
# accepts dsl block to
|
53
53
|
def initialize hash={}, &block
|
54
54
|
@rules = {}
|
55
|
+
@db = []
|
55
56
|
hash.each { |k, v| set(k, v) }
|
56
57
|
instance_exec &block if block
|
57
58
|
end
|
58
59
|
|
59
|
-
# set :age, type: :integer -> integer :age
|
60
|
-
# email :email
|
61
|
-
# set :email, [:emails]
|
62
|
-
# email [:emails]
|
63
|
-
def method_missing name, *args, &block
|
64
|
-
field = args.shift
|
65
|
-
|
66
|
-
if field.class == Array
|
67
|
-
field = field.first
|
68
|
-
name = [name]
|
69
|
-
end
|
70
|
-
|
71
|
-
set field, type=name, *args
|
72
|
-
end
|
73
|
-
|
74
|
-
# coerce opts values
|
75
|
-
def parse_option opts
|
76
|
-
opts[:type] ||= 'string'
|
77
|
-
opts[:req] = opts.delete(:required) unless opts[:required].nil?
|
78
|
-
|
79
|
-
if opts[:type].is_a?(Array)
|
80
|
-
opts[:array_type] = opts[:type][0] if opts[:type][0]
|
81
|
-
opts[:type] = 'array'
|
82
|
-
end
|
83
|
-
|
84
|
-
opts[:type] = opts[:type].to_s.downcase
|
85
|
-
|
86
|
-
opts[:required] = opts[:req] unless opts[:req].nil?
|
87
|
-
opts[:unique] = opts[:uniq] unless opts[:uniq].nil?
|
88
|
-
opts[:description] = opts[:desc] unless opts[:desc].nil?
|
89
|
-
|
90
|
-
# allowed_names = [:req, :uniq, :protected, :type, :min, :max, :array_type, :default, :downcase, :desc, :label]
|
91
|
-
# opts.keys.each do |key|
|
92
|
-
# raise ArgumentError.new('%s is not allowed as typero option' % key) unless allowed_names.index(key)
|
93
|
-
# end
|
94
|
-
|
95
|
-
opts
|
96
|
-
end
|
97
|
-
|
98
|
-
# used in dsl to define value
|
99
|
-
def set field, type=String, opts={}
|
100
|
-
opts = type.is_a?(Hash) ? type : opts.merge(type: type)
|
101
|
-
|
102
|
-
opts[:type] ||= :string
|
103
|
-
klass = Typero::Type.load opts[:type]
|
104
|
-
@rules[field] = parse_option opts
|
105
|
-
end
|
106
|
-
|
107
|
-
def safe_type type
|
108
|
-
type.to_s.gsub(/[^\w]/,'').classify
|
109
|
-
end
|
110
|
-
|
111
|
-
# adds error to array or prefixes with field name
|
112
|
-
def add_error field, msg
|
113
|
-
if @errors[field]
|
114
|
-
@errors[field] += ', %s' % msg
|
115
|
-
else
|
116
|
-
if msg[0,1].downcase == msg[0,1]
|
117
|
-
field_name = field.to_s.sub(/_id$/,'').humanize
|
118
|
-
msg = '%s %s' % [field_name, msg]
|
119
|
-
end
|
120
|
-
|
121
|
-
@errors[field] = msg
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
60
|
# validates any instance object or object with hash variable interface
|
126
61
|
# it also coarces values
|
127
62
|
def validate instance
|
@@ -165,8 +100,97 @@ class Typero
|
|
165
100
|
errors = validate instance
|
166
101
|
errors.keys.length == 0
|
167
102
|
end
|
103
|
+
|
104
|
+
# returns field, db_type, db_opts
|
105
|
+
def db_schema
|
106
|
+
out = @rules.inject([]) do |total, (field, opts)|
|
107
|
+
type, opts = Typero::Type.load(opts[:type]).new(nil, opts).db_field
|
108
|
+
total << [type, field, opts]
|
109
|
+
end
|
110
|
+
|
111
|
+
out += @db if @db[0]
|
112
|
+
|
113
|
+
out
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
# adds error to array or prefixes with field name
|
119
|
+
def add_error field, msg
|
120
|
+
if @errors[field]
|
121
|
+
@errors[field] += ', %s' % msg
|
122
|
+
else
|
123
|
+
if msg[0,1].downcase == msg[0,1]
|
124
|
+
field_name = field.to_s.sub(/_id$/,'').humanize
|
125
|
+
msg = '%s %s' % [field_name, msg]
|
126
|
+
end
|
127
|
+
|
128
|
+
@errors[field] = msg
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# used in dsl to define value
|
133
|
+
def set field, type=String, opts={}
|
134
|
+
opts = type.is_a?(Hash) ? type : opts.merge(type: type)
|
135
|
+
opts[:type] ||= :string
|
136
|
+
opts[:req] = true if opts[:null].class == FalseClass
|
137
|
+
klass = Typero::Type.load opts[:type]
|
138
|
+
@rules[field] = parse_option opts
|
139
|
+
end
|
140
|
+
|
141
|
+
def safe_type type
|
142
|
+
type.to_s.gsub(/[^\w]/,'').classify
|
143
|
+
end
|
144
|
+
|
145
|
+
# coerce opts values
|
146
|
+
def parse_option opts
|
147
|
+
opts[:type] ||= 'string'
|
148
|
+
|
149
|
+
if opts[:type].is_a?(Array)
|
150
|
+
opts[:array_type] = opts[:type][0] if opts[:type][0]
|
151
|
+
opts[:type] = 'array'
|
152
|
+
end
|
153
|
+
|
154
|
+
opts[:type] = opts[:type].to_s.downcase
|
155
|
+
|
156
|
+
opts[:required] = opts.delete(:req) unless opts[:req].nil?
|
157
|
+
opts[:unique] = opts.delete(:uniq) unless opts[:uniq].nil?
|
158
|
+
opts[:description] = opts.delete(:desc) unless opts[:desc].nil?
|
159
|
+
|
160
|
+
opts
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
# pass values for db_schema only
|
165
|
+
# db :timestamps
|
166
|
+
# db :add_index, :code -> t.add_index :code
|
167
|
+
def db *args
|
168
|
+
@db.push args
|
169
|
+
end
|
170
|
+
|
171
|
+
# set :age, type: :integer -> integer :age
|
172
|
+
# email :email
|
173
|
+
# set :email, [:emails]
|
174
|
+
# email [:emails]
|
175
|
+
def method_missing name, *args, &block
|
176
|
+
field = args.shift
|
177
|
+
|
178
|
+
if field.class == Array
|
179
|
+
field = field.first
|
180
|
+
name = [name]
|
181
|
+
end
|
182
|
+
|
183
|
+
name = args.shift if name == :set
|
184
|
+
|
185
|
+
set field, type=name, *args
|
186
|
+
end
|
168
187
|
end
|
169
188
|
|
170
189
|
require_relative 'typero/type'
|
171
190
|
|
172
|
-
Dir['%s/typero/type/*.rb' %
|
191
|
+
Dir['%s/typero/type/*.rb' % __dir__].each do |file|
|
192
|
+
require file
|
193
|
+
end
|
194
|
+
|
195
|
+
# load Sequel adapter is Sequel is available
|
196
|
+
require_relative './adapters/sequel' if defined?(Sequel)
|
data/lib/typero/type.rb
CHANGED
@@ -9,28 +9,21 @@ class Typero::Type
|
|
9
9
|
|
10
10
|
###
|
11
11
|
|
12
|
-
def initialize
|
12
|
+
def initialize value, opts={}
|
13
13
|
@value = value
|
14
14
|
@opts = opts
|
15
15
|
end
|
16
16
|
|
17
17
|
# default validation for any type
|
18
|
-
def validate
|
18
|
+
def validate
|
19
19
|
true
|
20
20
|
end
|
21
21
|
|
22
|
+
# get error from option or the default one
|
22
23
|
def error_for name
|
23
24
|
@opts[name] || send(name)
|
24
25
|
end
|
25
26
|
|
26
|
-
def get
|
27
|
-
@value
|
28
|
-
end
|
29
|
-
|
30
|
-
def set
|
31
|
-
@value
|
32
|
-
end
|
33
|
-
|
34
27
|
def default
|
35
28
|
nil
|
36
29
|
end
|
data/lib/typero/type/array.rb
CHANGED
@@ -5,7 +5,10 @@ class Typero::ArrayType < Typero::Type
|
|
5
5
|
|
6
6
|
def set
|
7
7
|
unless @value.class.to_s.index('Array')
|
8
|
-
@value = @value.to_s.sub(/^\{/,'').sub(/\}$/,'')
|
8
|
+
@value = @value.to_s.sub(/^\{/,'').sub(/\}$/,'')
|
9
|
+
|
10
|
+
# split on new line and comma by default
|
11
|
+
@value = @value.split(/\s*[,\n]\s*/)
|
9
12
|
end
|
10
13
|
|
11
14
|
@value.uniq!
|
@@ -40,5 +43,13 @@ class Typero::ArrayType < Typero::Type
|
|
40
43
|
def value_in_list_error
|
41
44
|
'value in list'
|
42
45
|
end
|
46
|
+
|
47
|
+
def db_field
|
48
|
+
check = Typero::Type.load(@opts[:array_type]).new nil, {}
|
49
|
+
schema = check.db_field
|
50
|
+
schema[1] ||= {}
|
51
|
+
schema[1].merge! array: true
|
52
|
+
schema
|
53
|
+
end
|
43
54
|
end
|
44
55
|
|
data/lib/typero/type/boolean.rb
CHANGED
data/lib/typero/type/email.rb
CHANGED
data/lib/typero/type/float.rb
CHANGED
data/lib/typero/type/hash.rb
CHANGED
data/lib/typero/type/integer.rb
CHANGED
data/lib/typero/type/label.rb
CHANGED
data/lib/typero/type/oib.rb
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
class Typero::PointType < Typero::Type
|
2
|
+
def set
|
3
|
+
if @value.present?
|
4
|
+
if @value.include?('/@')
|
5
|
+
point = @value.split('/@', 2).last.split(',')
|
6
|
+
@value = [point[0], point[1]].join(',')
|
7
|
+
end
|
8
|
+
|
9
|
+
unless @value.include?('POINT')
|
10
|
+
point = @value.sub(/,\s*/, ' ')
|
11
|
+
@value = 'SRID=4326;POINT(%s)' % point
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def validate
|
17
|
+
raise TypeError, error_for(:unallowed_characters_error) unless @value =~ /^SRID=4326;POINT\(/
|
18
|
+
end
|
19
|
+
|
20
|
+
def db_field
|
21
|
+
[:geography, {}]
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
data/lib/typero/type/string.rb
CHANGED
data/lib/typero/type/url.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: typero
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dino Reic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-07-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fast_blank
|
@@ -32,17 +32,24 @@ extensions: []
|
|
32
32
|
extra_rdoc_files: []
|
33
33
|
files:
|
34
34
|
- "./.version"
|
35
|
+
- "./lib/adapters/sequel.rb"
|
35
36
|
- "./lib/typero.rb"
|
36
37
|
- "./lib/typero/type.rb"
|
37
38
|
- "./lib/typero/type/array.rb"
|
38
39
|
- "./lib/typero/type/boolean.rb"
|
40
|
+
- "./lib/typero/type/currency.rb"
|
41
|
+
- "./lib/typero/type/date.rb"
|
42
|
+
- "./lib/typero/type/datetime.rb"
|
39
43
|
- "./lib/typero/type/email.rb"
|
40
44
|
- "./lib/typero/type/float.rb"
|
45
|
+
- "./lib/typero/type/geography.rb"
|
41
46
|
- "./lib/typero/type/hash.rb"
|
42
47
|
- "./lib/typero/type/integer.rb"
|
43
48
|
- "./lib/typero/type/label.rb"
|
44
49
|
- "./lib/typero/type/oib.rb"
|
50
|
+
- "./lib/typero/type/point.rb"
|
45
51
|
- "./lib/typero/type/string.rb"
|
52
|
+
- "./lib/typero/type/text.rb"
|
46
53
|
- "./lib/typero/type/url.rb"
|
47
54
|
homepage: https://github.com/dux/typero
|
48
55
|
licenses:
|
@@ -63,8 +70,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
63
70
|
- !ruby/object:Gem::Version
|
64
71
|
version: '0'
|
65
72
|
requirements: []
|
66
|
-
|
67
|
-
rubygems_version: 2.7.5
|
73
|
+
rubygems_version: 3.0.3
|
68
74
|
signing_key:
|
69
75
|
specification_version: 4
|
70
76
|
summary: Ruby type system
|