safrano 0.5.1 → 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/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
|