typero 0.4.0 → 0.5.2
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/.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
|