safrano 0.5.1 → 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/lib/odata/collection.rb +9 -7
- data/lib/odata/complex_type.rb +129 -31
- data/lib/odata/entity.rb +6 -2
- data/lib/odata/function_import.rb +24 -25
- data/lib/odata/model_ext.rb +2 -2
- data/lib/odata/transition.rb +22 -2
- data/lib/odata/walker.rb +20 -2
- data/lib/safrano/request.rb +1 -0
- data/lib/safrano/service.rb +11 -2
- data/lib/safrano/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 00bf6cd3a561928000b8bf53bbc71f139b162f92adc229e625f010dc6f1ce3c7
|
4
|
+
data.tar.gz: bf154e1b55e4d32e4640d6c993566a45eae8a2bce44b23dd979a9946d3633dc7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b2fad0321b45bae50f3435b688b31f99d320cfa4f81f14867f64659faa0c4e8ece7bc4f1f7ecc2db2c7710c08f7726bb4d758bf5d09d487a54199afea50119a
|
7
|
+
data.tar.gz: b9a70b4a08fb7a2cc31df7e7637f635a42a85433660f5061f6897e1fb463496252c8d611fb1023e5f27202bbc478b58569d2ad42b1c3359db14e34c92f4ec35c
|
data/lib/odata/collection.rb
CHANGED
@@ -60,10 +60,13 @@ module Safrano
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def initialize_dataset(dtset = nil)
|
63
|
-
@cx = dtset || @modelk
|
63
|
+
@cx = @cx || dtset || @modelk
|
64
|
+
end
|
65
|
+
|
66
|
+
def initialize_uparms
|
64
67
|
@uparms = UrlParameters4Coll.new(@cx, @params)
|
65
68
|
end
|
66
|
-
|
69
|
+
|
67
70
|
def odata_get_apply_params
|
68
71
|
@uparms.apply_to_dataset(@cx).map_result! do |dataset|
|
69
72
|
@cx = dataset
|
@@ -131,9 +134,9 @@ module Safrano
|
|
131
134
|
|
132
135
|
# on model class level we return the collection
|
133
136
|
def odata_get(req)
|
134
|
-
@params = req.params
|
135
|
-
initialize_dataset
|
136
|
-
|
137
|
+
@params = @params || req.params
|
138
|
+
initialize_dataset
|
139
|
+
initialize_uparms
|
137
140
|
@uparms.check_all.if_valid { |_ret|
|
138
141
|
odata_get_apply_params.if_valid { |_ret|
|
139
142
|
odata_get_output(req)
|
@@ -170,8 +173,7 @@ module Safrano
|
|
170
173
|
end
|
171
174
|
|
172
175
|
def initialize_dataset(dtset = nil)
|
173
|
-
@cx = dtset || navigated_dataset
|
174
|
-
@uparms = UrlParameters4Coll.new(@cx, @params)
|
176
|
+
@cx = @cx || dtset || navigated_dataset
|
175
177
|
end
|
176
178
|
# redefinitions of the main methods for a navigated collection
|
177
179
|
# (eg. all Books of Author[2] is Author[2].Books.all )
|
data/lib/odata/complex_type.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
module Safrano
|
4
4
|
module FunctionImport
|
5
|
+
EMPTY_HASH = {}.freeze
|
5
6
|
class ResultDefinition
|
6
7
|
D = 'd'
|
7
8
|
DJ_OPEN = '{"d":'
|
@@ -11,33 +12,104 @@ module Safrano
|
|
11
12
|
VALUEK = 'value'
|
12
13
|
RESULTSK = 'results'
|
13
14
|
COLLECTION = 'Collection'
|
14
|
-
|
15
|
-
def
|
16
|
-
|
15
|
+
|
16
|
+
def allowed_transitions
|
17
|
+
[Safrano::TransitionEnd]
|
17
18
|
end
|
18
|
-
|
19
|
-
def
|
20
|
-
|
19
|
+
|
20
|
+
def transition_end(_match_result)
|
21
|
+
Safrano::Transition::RESULT_END
|
21
22
|
end
|
22
|
-
|
23
|
-
|
23
|
+
|
24
|
+
# we will have this on class and instance level for making things simpler first
|
25
|
+
def self.klassmod
|
26
|
+
@klassmod
|
27
|
+
end
|
28
|
+
|
29
|
+
# return a subclass of ResultAsComplexType
|
30
|
+
def self.asComplexType(klassmod)
|
31
|
+
Class.new(ResultAsComplexType) do
|
32
|
+
@klassmod = klassmod
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# return a subclass of ResultAsComplexType
|
37
|
+
def self.asComplexTypeColl(klassmod)
|
38
|
+
Class.new(ResultAsComplexTypeColl) do
|
39
|
+
@klassmod = klassmod
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.asPrimitiveType(klassmod)
|
44
|
+
Class.new(ResultAsPrimitiveType) do
|
45
|
+
@klassmod = klassmod
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.asPrimitiveTypeColl(klassmod)
|
50
|
+
Class.new(ResultAsPrimitiveTypeColl) do
|
51
|
+
@klassmod = klassmod
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.asEntity(klassmod)
|
56
|
+
Class.new(ResultAsEntity) do
|
57
|
+
@klassmod = klassmod
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.asEntityColl(klassmod)
|
62
|
+
Class.new(ResultAsEntityColl) do
|
63
|
+
@klassmod = klassmod
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def initialize(value)
|
68
|
+
@value = value
|
69
|
+
end
|
70
|
+
|
71
|
+
def odata_get(req)
|
72
|
+
[200, EMPTY_HASH, [to_odata_json(req)]]
|
73
|
+
end
|
74
|
+
def self.type_metadata
|
24
75
|
@klassmod.type_name
|
25
76
|
end
|
77
|
+
def type_metadata
|
78
|
+
self.class.type_metadata
|
79
|
+
end
|
80
|
+
|
81
|
+
# needed for ComplexType result
|
82
|
+
def to_odata_json(_req)
|
83
|
+
"#{DJ_OPEN}#{@value.odata_h.to_json}#{DJ_CLOSE}"
|
84
|
+
end
|
85
|
+
|
86
|
+
# wrapper
|
87
|
+
# for OData Entity and Collections, return them directly
|
88
|
+
# for others, ie ComplexType, Prims etc, return the ResultDefinition-subclass wrapped result
|
89
|
+
def self.do_execute_func_result(result, _req, apply_query_params=false)
|
90
|
+
self.new(result)
|
91
|
+
end
|
92
|
+
|
26
93
|
end
|
94
|
+
|
27
95
|
class ResultAsComplexType < ResultDefinition
|
96
|
+
def self.type_metadata
|
97
|
+
@klassmod.type_name
|
98
|
+
end
|
28
99
|
end
|
100
|
+
|
29
101
|
class ResultAsComplexTypeColl < ResultDefinition
|
30
|
-
def type_metadata
|
102
|
+
def self.type_metadata
|
31
103
|
"Collection(#{@klassmod.type_name})"
|
32
104
|
end
|
33
105
|
|
34
|
-
def to_odata_json(
|
106
|
+
def to_odata_json(req)
|
35
107
|
# "#{DJ_OPEN}#{{ RESULTSK => coll.map { |c| c.odata_h } }.to_json}#{DJ_CLOSE}"
|
36
|
-
template =
|
108
|
+
template = self.class.klassmod.output_template
|
37
109
|
# TODO: Error handling if database contains binary BLOB data that cant be
|
38
110
|
# interpreted as UTF-8 then JSON will fail here
|
39
111
|
|
40
|
-
innerh = req.service.get_coll_odata_h(array:
|
112
|
+
innerh = req.service.get_coll_odata_h(array: @value,
|
41
113
|
template: template)
|
42
114
|
|
43
115
|
innerj = innerh.to_json
|
@@ -45,43 +117,69 @@ module Safrano
|
|
45
117
|
"#{DJ_OPEN}#{innerj}#{DJ_CLOSE}"
|
46
118
|
end
|
47
119
|
end
|
120
|
+
|
48
121
|
class ResultAsEntity < ResultDefinition
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
to_odata_json(request: req)
|
53
|
-
end
|
122
|
+
|
123
|
+
def self.type_metadata
|
124
|
+
@klassmod.type_name
|
54
125
|
end
|
126
|
+
|
127
|
+
|
128
|
+
# wrapper
|
129
|
+
# for OData Entity return them directly
|
130
|
+
def self.do_execute_func_result(result, _req, apply_query_params=false)
|
131
|
+
# note: Sequel entities instances seem to be thread safe, so we can
|
132
|
+
# safely add request-dependant data (eg. req.params) there
|
133
|
+
apply_query_params ? result : result.inactive_query_params
|
134
|
+
end
|
135
|
+
|
55
136
|
end
|
137
|
+
|
56
138
|
class ResultAsEntityColl < ResultDefinition
|
57
|
-
|
139
|
+
|
140
|
+
def self.type_metadata
|
58
141
|
"Collection(#{@klassmod.type_name})"
|
59
142
|
end
|
60
|
-
|
61
|
-
|
143
|
+
|
144
|
+
# wrapper
|
145
|
+
# for OData Entity Collection return them directly
|
146
|
+
def self.do_execute_func_result(result, req, apply_query_params=false)
|
62
147
|
coll = Safrano::OData::Collection.new(@klassmod)
|
148
|
+
# instance_exec has other instance variables; @values would be nil in the block below
|
149
|
+
# need to pass a local copy
|
150
|
+
dtset = result
|
63
151
|
coll.instance_exec do
|
64
|
-
|
65
|
-
|
152
|
+
|
153
|
+
@params = apply_query_params ? req.params : EMPTY_HASH
|
154
|
+
initialize_dataset(dtset)
|
155
|
+
initialize_uparms
|
66
156
|
end
|
67
|
-
coll
|
157
|
+
coll
|
68
158
|
end
|
159
|
+
|
69
160
|
end
|
161
|
+
|
70
162
|
class ResultAsPrimitiveType < ResultDefinition
|
71
|
-
def
|
163
|
+
def self.type_metadata
|
164
|
+
@klassmod.type_name
|
165
|
+
end
|
166
|
+
|
167
|
+
def to_odata_json(_req)
|
72
168
|
{ D => { METAK => { TYPEK => type_metadata },
|
73
|
-
VALUEK =>
|
169
|
+
VALUEK => self.class.klassmod.odata_value(@value) } }.to_json
|
74
170
|
end
|
75
171
|
end
|
172
|
+
|
76
173
|
class ResultAsPrimitiveTypeColl < ResultDefinition
|
77
|
-
def type_metadata
|
174
|
+
def self.type_metadata
|
78
175
|
"Collection(#{@klassmod.type_name})"
|
79
176
|
end
|
80
177
|
|
81
|
-
def to_odata_json(
|
82
|
-
{ D => { METAK => { TYPEK => type_metadata },
|
83
|
-
RESULTSK =>
|
178
|
+
def to_odata_json(_req)
|
179
|
+
{ D => { METAK => { TYPEK => self.class.type_metadata },
|
180
|
+
RESULTSK => self.class.klassmod.odata_collection(@value) } }.to_json
|
84
181
|
end
|
182
|
+
|
85
183
|
end
|
86
184
|
end
|
87
185
|
|
@@ -157,11 +255,11 @@ module Safrano
|
|
157
255
|
end
|
158
256
|
|
159
257
|
def self.return_as_collection_descriptor
|
160
|
-
FunctionImport::
|
258
|
+
FunctionImport::ResultDefinition.asComplexTypeColl(self)
|
161
259
|
end
|
162
260
|
|
163
261
|
def self.return_as_instance_descriptor
|
164
|
-
FunctionImport::
|
262
|
+
FunctionImport::ResultDefinition.asComplexType(self)
|
165
263
|
end
|
166
264
|
|
167
265
|
# add metadata xml to the passed REXML schema object
|
data/lib/odata/entity.rb
CHANGED
@@ -125,7 +125,7 @@ module Safrano
|
|
125
125
|
end
|
126
126
|
|
127
127
|
def copy_request_infos(req)
|
128
|
-
@params = req.params
|
128
|
+
@params = @inactive_query_params ? EMPTY_HASH : req.params
|
129
129
|
@do_links = req.walker.do_links
|
130
130
|
@uparms = UrlParameters4Single.new(self, @params)
|
131
131
|
end
|
@@ -151,7 +151,11 @@ module Safrano
|
|
151
151
|
@uparms.check_all.tap_valid { return odata_get_output(req) }
|
152
152
|
.tap_error { |e| return e.odata_get(req) }
|
153
153
|
end
|
154
|
-
|
154
|
+
def inactive_query_params
|
155
|
+
@inactive_query_params = true
|
156
|
+
self # chaining
|
157
|
+
end
|
158
|
+
|
155
159
|
DELETE_REL_AND_ENTY = lambda do |entity, assoc, parent|
|
156
160
|
Safrano.remove_nav_relation(assoc, parent)
|
157
161
|
entity.destroy(transaction: false)
|
@@ -21,7 +21,7 @@ module Safrano
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def allowed_transitions
|
24
|
-
[Safrano::
|
24
|
+
[Safrano::TransitionExecuteFunc]
|
25
25
|
end
|
26
26
|
|
27
27
|
def input(**parmtypes)
|
@@ -42,7 +42,13 @@ module Safrano
|
|
42
42
|
end
|
43
43
|
self
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
|
+
def auto_query_parameters
|
47
|
+
@auto_query_params = true
|
48
|
+
self # chaining
|
49
|
+
end
|
50
|
+
alias auto_query_params auto_query_parameters
|
51
|
+
|
46
52
|
def return(klassmod, &proc)
|
47
53
|
raise('Please provide a code block') unless block_given?
|
48
54
|
|
@@ -51,7 +57,7 @@ module Safrano
|
|
51
57
|
else
|
52
58
|
# if it's neither a ComplexType nor a Model-Entity
|
53
59
|
# --> assume it is a Primitive
|
54
|
-
|
60
|
+
ResultDefinition.asPrimitiveType(klassmod)
|
55
61
|
end
|
56
62
|
@proc = proc
|
57
63
|
self
|
@@ -65,7 +71,8 @@ module Safrano
|
|
65
71
|
else
|
66
72
|
# if it's neither a ComplexType nor a Modle-Entity
|
67
73
|
# --> assume it is a Primitive
|
68
|
-
ResultAsPrimitiveTypeColl.new(klassmod)
|
74
|
+
# ResultAsPrimitiveTypeColl.new(klassmod)
|
75
|
+
ResultDefinition.asPrimitiveTypeColl(klassmod)
|
69
76
|
end
|
70
77
|
@proc = proc
|
71
78
|
self
|
@@ -135,33 +142,25 @@ module Safrano
|
|
135
142
|
end if @input
|
136
143
|
funky
|
137
144
|
end
|
138
|
-
|
139
|
-
def
|
145
|
+
|
146
|
+
def with_transition_validated(req)
|
140
147
|
# initialize_params
|
148
|
+
@params = req.params
|
141
149
|
return yield unless (@error = check_url_func_params)
|
142
150
|
|
143
|
-
@error
|
144
|
-
end
|
145
|
-
|
146
|
-
def to_odata_json(req)
|
147
|
-
result = @proc.call(**@funcparams)
|
148
|
-
@returning.to_odata_json(result, req)
|
151
|
+
[nil, :error, @error] if @error
|
149
152
|
end
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
@params = req.params
|
157
|
-
|
158
|
-
with_validated_get(req) do
|
159
|
-
odata_get_output(req)
|
153
|
+
|
154
|
+
|
155
|
+
def do_execute_func(req)
|
156
|
+
with_transition_validated(req) do
|
157
|
+
result = @proc.call(**@funcparams)
|
158
|
+
[@returning.do_execute_func_result(result, req, @auto_query_params), :run]
|
160
159
|
end
|
161
160
|
end
|
162
|
-
|
163
|
-
def
|
164
|
-
|
161
|
+
|
162
|
+
def transition_execute_func(_match_result)
|
163
|
+
[self, :run_with_execute_func]
|
165
164
|
end
|
166
165
|
end
|
167
166
|
end
|
data/lib/odata/model_ext.rb
CHANGED
@@ -81,11 +81,11 @@ module Safrano
|
|
81
81
|
end
|
82
82
|
|
83
83
|
def return_as_collection_descriptor
|
84
|
-
Safrano::FunctionImport::
|
84
|
+
Safrano::FunctionImport::ResultDefinition.asEntityColl(self)
|
85
85
|
end
|
86
86
|
|
87
87
|
def return_as_instance_descriptor
|
88
|
-
Safrano::FunctionImport::
|
88
|
+
Safrano::FunctionImport::ResultDefinition.asEntity(self)
|
89
89
|
end
|
90
90
|
|
91
91
|
def execute_deferred_iblock
|
data/lib/odata/transition.rb
CHANGED
@@ -6,7 +6,7 @@ require_relative 'error'
|
|
6
6
|
module Safrano
|
7
7
|
# represents a state transition when navigating/parsing the url path
|
8
8
|
# from left to right
|
9
|
-
class Transition
|
9
|
+
class Transition
|
10
10
|
attr_accessor :trans
|
11
11
|
attr_accessor :match_result
|
12
12
|
attr_accessor :rgx
|
@@ -52,8 +52,28 @@ module Safrano
|
|
52
52
|
ctx.method(@trans).call(@match_result)
|
53
53
|
end
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
|
+
#Transition that does not move/change the input
|
57
|
+
class InplaceTransition < Transition
|
58
|
+
def initialize(trans: )
|
59
|
+
@trans = trans
|
60
|
+
end
|
61
|
+
def do_match(str)
|
62
|
+
@str = str
|
63
|
+
end
|
64
|
+
def path_remain
|
65
|
+
@str
|
66
|
+
end
|
67
|
+
def path_done
|
68
|
+
EMPTYSTR
|
69
|
+
end
|
70
|
+
def do_transition(ctx)
|
71
|
+
ctx.method(@trans).call(@str)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
56
75
|
TransitionEnd = Transition.new('\A(\/?)\z', trans: 'transition_end')
|
76
|
+
TransitionExecuteFunc = InplaceTransition.new(trans: 'transition_execute_func')
|
57
77
|
TransitionMetadata = Transition.new('\A(\/\$metadata)(.*)',
|
58
78
|
trans: 'transition_metadata')
|
59
79
|
TransitionBatch = Transition.new('\A(\/\$batch)(.*)',
|
data/lib/odata/walker.rb
CHANGED
@@ -29,18 +29,24 @@ module Safrano
|
|
29
29
|
|
30
30
|
# are $links requested ?
|
31
31
|
attr_reader :do_links
|
32
|
+
|
33
|
+
attr_reader :request
|
32
34
|
|
33
35
|
NIL_SERVICE_FATAL = 'Walker is called with a nil service'
|
34
36
|
EMPTYSTR = ''
|
35
37
|
SLASH = '/'
|
36
38
|
|
37
|
-
def initialize(service, path, content_id_refs = nil)
|
39
|
+
def initialize(service, path, request, content_id_refs = nil )
|
38
40
|
raise NIL_SERVICE_FATAL unless service
|
39
41
|
|
40
42
|
path = URI.decode_www_form_component(path)
|
41
43
|
@context = service
|
42
44
|
@content_id_refs = content_id_refs
|
43
|
-
|
45
|
+
|
46
|
+
# needed because for function import we need access to the url parameters (req.params)
|
47
|
+
# who contains the functions params
|
48
|
+
@request = request
|
49
|
+
|
44
50
|
@contexts = [@context]
|
45
51
|
|
46
52
|
@path_start = @path_remain = if service
|
@@ -109,6 +115,16 @@ module Safrano
|
|
109
115
|
end
|
110
116
|
end
|
111
117
|
|
118
|
+
# execute function import with request parameters
|
119
|
+
# input: @context containt the function to exectute,
|
120
|
+
# @request.params should normally contain the params
|
121
|
+
# result: validate the params for the given function, execute the function and
|
122
|
+
# return it's result back into @context,
|
123
|
+
# and finaly set status :end (or error if anyting went wrong )
|
124
|
+
def do_run_with_execute_func
|
125
|
+
@context, @status, @error = @context.do_execute_func(@request)
|
126
|
+
end
|
127
|
+
|
112
128
|
# little hacks... depending on returned state, set some attributes
|
113
129
|
def state_mappings
|
114
130
|
case @status
|
@@ -137,6 +153,8 @@ module Safrano
|
|
137
153
|
# entity reference here and place it in @context
|
138
154
|
when :run_with_content_id
|
139
155
|
do_run_with_content_id
|
156
|
+
when :run_with_execute_func
|
157
|
+
do_run_with_execute_func
|
140
158
|
end
|
141
159
|
|
142
160
|
@contexts << @context
|
data/lib/safrano/request.rb
CHANGED
data/lib/safrano/service.rb
CHANGED
@@ -137,6 +137,7 @@ module Safrano
|
|
137
137
|
attr_accessor :relman
|
138
138
|
attr_accessor :complex_types
|
139
139
|
attr_accessor :function_imports
|
140
|
+
attr_accessor :function_import_keys
|
140
141
|
|
141
142
|
# Instance attributes for specialized Version specific Instances
|
142
143
|
attr_accessor :v1
|
@@ -155,6 +156,7 @@ module Safrano
|
|
155
156
|
@relman = Safrano::RelationManager.new
|
156
157
|
@complex_types = Set.new
|
157
158
|
@function_imports = {}
|
159
|
+
@function_import_keys = []
|
158
160
|
@cmap = {}
|
159
161
|
instance_eval(&block) if block_given?
|
160
162
|
end
|
@@ -239,6 +241,7 @@ module Safrano
|
|
239
241
|
other.batch_handler = @batch_handler
|
240
242
|
other.complex_types = @complex_types
|
241
243
|
other.function_imports = @function_imports
|
244
|
+
other.function_import_keys = @function_import_keys
|
242
245
|
other
|
243
246
|
end
|
244
247
|
|
@@ -322,6 +325,8 @@ module Safrano
|
|
322
325
|
def function_import(name)
|
323
326
|
funcimp = Safrano::FunctionImport(name)
|
324
327
|
@function_imports[name] = funcimp
|
328
|
+
@function_import_keys << name
|
329
|
+
set_funcimports_sorted
|
325
330
|
funcimp
|
326
331
|
end
|
327
332
|
|
@@ -338,7 +343,11 @@ module Safrano
|
|
338
343
|
@collections.sort_by! { |klass| klass.entity_set_name.size }.reverse! if @collections
|
339
344
|
@collections
|
340
345
|
end
|
341
|
-
|
346
|
+
|
347
|
+
# need to be sorted by size too
|
348
|
+
def set_funcimports_sorted
|
349
|
+
@function_import_keys.sort_by!{|k| k.size}.reverse!
|
350
|
+
end
|
342
351
|
# to be called at end of publishing block to ensure we get the right names
|
343
352
|
# and additionally build the list of valid attribute path's used
|
344
353
|
# for validation of $orderby or $filter params
|
@@ -401,7 +410,7 @@ module Safrano
|
|
401
410
|
end
|
402
411
|
|
403
412
|
def base_url_func_regexp
|
404
|
-
@
|
413
|
+
@function_import_keys.join('|')
|
405
414
|
end
|
406
415
|
|
407
416
|
def service
|
data/lib/safrano/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: safrano
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- oz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-06-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|