safrano 0.5.5 → 0.6.0
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/core_ext/Date/format.rb +47 -0
- data/lib/core_ext/DateTime/format.rb +54 -0
- data/lib/core_ext/Dir/iter.rb +7 -5
- data/lib/core_ext/Hash/transform.rb +14 -6
- data/lib/core_ext/Numeric/convert.rb +1 -1
- data/lib/core_ext/Time/format.rb +71 -0
- data/lib/core_ext/date.rb +5 -0
- data/lib/core_ext/datetime.rb +5 -0
- data/lib/core_ext/time.rb +5 -0
- data/lib/odata/attribute.rb +8 -6
- data/lib/odata/batch.rb +3 -3
- data/lib/odata/collection.rb +5 -5
- data/lib/odata/collection_filter.rb +3 -1
- data/lib/odata/collection_media.rb +4 -27
- data/lib/odata/collection_order.rb +1 -1
- data/lib/odata/common_logger.rb +5 -27
- data/lib/odata/complex_type.rb +19 -21
- data/lib/odata/edm/primitive_types.rb +14 -19
- data/lib/odata/entity.rb +12 -12
- data/lib/odata/error.rb +7 -7
- data/lib/odata/expand.rb +2 -2
- data/lib/odata/filter/base.rb +10 -1
- data/lib/odata/filter/error.rb +2 -2
- data/lib/odata/filter/parse.rb +16 -2
- data/lib/odata/filter/sequel.rb +31 -4
- data/lib/odata/filter/sequel_datetime_adapter.rb +21 -0
- data/lib/odata/filter/token.rb +18 -5
- data/lib/odata/filter/tree.rb +83 -9
- data/lib/odata/function_import.rb +11 -9
- data/lib/odata/model_ext.rb +26 -29
- data/lib/odata/request/json.rb +171 -0
- data/lib/odata/transition.rb +2 -2
- data/lib/odata/url_parameters.rb +3 -3
- data/lib/odata/walker.rb +1 -1
- data/lib/safrano/multipart.rb +1 -3
- data/lib/safrano/rack_app.rb +2 -14
- data/lib/safrano/rack_builder.rb +0 -15
- data/lib/safrano/request.rb +3 -3
- data/lib/safrano/response.rb +3 -3
- data/lib/safrano/service.rb +13 -5
- data/lib/safrano/type_mapping.rb +4 -4
- data/lib/safrano/version.rb +1 -2
- data/lib/safrano.rb +3 -0
- metadata +51 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 26b1634021c6ab2117b0b2fe4fb8c49242d4a045b6afafec604ef61e26c3bc48
|
4
|
+
data.tar.gz: 86adac4fb2ab8ad02d570f373325b7e1c4945941a01e2328fc50ff10c9460abd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c19b30f23c22127742d8c557a23feec6de75a91d20b1b8b0033fb85e4f1549e92de300e17cb3d80564f92ed0dcd81096b5b4aca1a268eba803b6bbd6a4c0a75c
|
7
|
+
data.tar.gz: ee3a9d73e9e1d5862cb1a699786e9f81c5a58d7937678b5a138eecae08ccc10e49248f70066ede55e270fb361744978ca4b5b9a75bbd6e62a2c4685e6fc2ae46
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Safrano
|
4
|
+
module CoreExt
|
5
|
+
module Date
|
6
|
+
module Format
|
7
|
+
# Date is a DateTime with time 00:00:00 thus the milliseconds are ALWAYS 000
|
8
|
+
# excepted when we get Date(0) = Epoch date
|
9
|
+
REGEX = /\/Date\((?:(-?\d+)000|0+)\)\//.freeze
|
10
|
+
# Input: /Date(86400000)/
|
11
|
+
# Match groups
|
12
|
+
# 1. 86400
|
13
|
+
# Input: /Date(0)/
|
14
|
+
# Match groups
|
15
|
+
# 1.
|
16
|
+
|
17
|
+
def from_edm_json(instr)
|
18
|
+
return unless (md = instr.match(REGEX))
|
19
|
+
|
20
|
+
if md[1].nil? # no offset relative to Epoch
|
21
|
+
::Date.new(1970, 1, 1).freeze
|
22
|
+
else
|
23
|
+
# parse as seconds since epoch
|
24
|
+
::Date.strptime(md[1], '%s')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
module CoreIncl
|
31
|
+
module Date
|
32
|
+
module Format
|
33
|
+
# https://www.odata.org/documentation/odata-version-2-0/json-format/
|
34
|
+
# Edm.DateTime
|
35
|
+
# "/Date(<ticks>["+" | "-" <offset>)/"
|
36
|
+
# <ticks> = number of milliseconds since midnight Jan 1, 1970
|
37
|
+
# <offset> = number of minutes to add or subtract
|
38
|
+
# https://stackoverflow.com/questions/10286204/what-is-the-right-json-date-format/10286228#10286228
|
39
|
+
def to_edm_json
|
40
|
+
# no offset
|
41
|
+
# --> %Q milliseconds since epoch
|
42
|
+
strftime('/Date(%Q)/')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Safrano
|
4
|
+
module CoreExt
|
5
|
+
module DateTime
|
6
|
+
module Format
|
7
|
+
REGEX = /\/Date\((-?\d+)(?:([-+])(\d+))?\)\//.freeze
|
8
|
+
# Input: /Date(120000+150)/
|
9
|
+
# Match groups
|
10
|
+
# 1. 120000
|
11
|
+
# 2. +
|
12
|
+
# 3. 150
|
13
|
+
|
14
|
+
def from_edm_json(instr)
|
15
|
+
return unless (md = instr.match(REGEX))
|
16
|
+
|
17
|
+
if md[3].nil? # no offset
|
18
|
+
::DateTime.strptime(md[1], '%Q')
|
19
|
+
else
|
20
|
+
# offset in hours / mins
|
21
|
+
off_h, off_m = md[3].to_i.divmod(60)
|
22
|
+
# DateTime.strptime("120000+2:30", '%Q%z') milliseconds since epoch with a z-offset
|
23
|
+
# --> #<DateTime: 1970-01-01T02:32:00+02:30 ((2440588j,120s,0n),+9000s,2299161j)>
|
24
|
+
::DateTime.strptime("#{md[1]}#{md[2]}#{off_h}:#{off_m}", '%Q%z')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
module CoreIncl
|
31
|
+
module DateTime
|
32
|
+
module Format
|
33
|
+
# https://www.odata.org/documentation/odata-version-2-0/json-format/
|
34
|
+
# Edm.DateTime
|
35
|
+
# "/Date(<ticks>["+" | "-" <offset>)/"
|
36
|
+
# <ticks> = number of milliseconds since midnight Jan 1, 1970
|
37
|
+
# <offset> = number of minutes to add or subtract
|
38
|
+
# https://stackoverflow.com/questions/10286204/what-is-the-right-json-date-format/10286228#10286228
|
39
|
+
def to_edm_json
|
40
|
+
if offset.zero?
|
41
|
+
# no offset
|
42
|
+
# --> %Q milliseconds since epoch
|
43
|
+
strftime('/Date(%Q)/')
|
44
|
+
else
|
45
|
+
# same as above with GMT offset in minutes
|
46
|
+
# DateTime offset is Rational ; fraction of hours per Day --> *24*60
|
47
|
+
min_off_s = (min_off = (offset * 60 * 24).to_i) > 0 ? "+#{min_off}" : min_off.to_s
|
48
|
+
"/Date(#{strftime('%Q')}#{min_off_s})/"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/core_ext/Dir/iter.rb
CHANGED
@@ -5,13 +5,15 @@ module Safrano
|
|
5
5
|
module CoreExt
|
6
6
|
module Dir
|
7
7
|
module Iter
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
unless ::Dir.respond_to? :each_child
|
9
|
+
def each_child(dir)
|
10
|
+
::Dir.foreach(dir) do |x|
|
11
|
+
next if (x == '.') || (x == '..')
|
11
12
|
|
12
|
-
|
13
|
+
yield x
|
14
|
+
end
|
13
15
|
end
|
14
|
-
end
|
16
|
+
end
|
15
17
|
end
|
16
18
|
end
|
17
19
|
end
|
@@ -5,15 +5,23 @@ module Safrano
|
|
5
5
|
module CoreIncl
|
6
6
|
module Hash
|
7
7
|
module Transform
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
unless method_defined? :transform_keys!
|
9
|
+
def transform_keys!
|
10
|
+
keys.each do |key|
|
11
|
+
self[yield(key)] = delete(key)
|
12
|
+
end
|
13
|
+
self
|
11
14
|
end
|
12
|
-
|
13
|
-
end unless method_defined? :transform_keys!
|
15
|
+
end
|
14
16
|
|
15
17
|
def symbolize_keys!
|
16
|
-
transform_keys!
|
18
|
+
transform_keys! do |key|
|
19
|
+
begin
|
20
|
+
key.to_sym
|
21
|
+
rescue StandardError
|
22
|
+
key
|
23
|
+
end
|
24
|
+
end
|
17
25
|
end
|
18
26
|
end
|
19
27
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Safrano
|
4
|
+
module CoreExt
|
5
|
+
module Time
|
6
|
+
module Format
|
7
|
+
REGEX = /\/Date\((-?\d+)(?:([-+])(\d+))?\)\//.freeze
|
8
|
+
# Input: /Date(120000+150)/
|
9
|
+
# Match groups
|
10
|
+
# 1. 120000
|
11
|
+
# 2. +
|
12
|
+
# 3. 150
|
13
|
+
|
14
|
+
def from_edm_json(instr)
|
15
|
+
return unless (md = instr.match(REGEX))
|
16
|
+
|
17
|
+
sec, milli = md[1].to_i.divmod(1000)
|
18
|
+
secm = milli.zero? ? sec : sec + Float(milli) / 1000
|
19
|
+
if md[3].nil? # no offset
|
20
|
+
# ::Time.at(sec, milli, :millisecond) # not supported in ruby 2.4
|
21
|
+
::Time.gm(1970, 1, 1) + secm
|
22
|
+
else
|
23
|
+
# offset in hours / mins
|
24
|
+
off_h, off_m = md[3].to_i.divmod(60)
|
25
|
+
# add leading 0 because Time.at is expecting "+HH:MM", "-HH:MM"
|
26
|
+
off_h = off_h < 10 ? "0#{off_h}" : off_h.to_s
|
27
|
+
off_m = off_m < 10 ? "0#{off_m}" : off_m.to_s
|
28
|
+
# Time.strptime("120000+2:30", '%Q%z') milliseconds since epoch with a z-offset
|
29
|
+
# --> #<DateTime: 1970-01-01T02:32:00+02:30 ((2440588j,120s,0n),+9000s,2299161j)>
|
30
|
+
# ::Time.at(sec, milli, :millisecond, in: "#{md[2]}#{off_h}:#{off_m}") # not supported in ruby 2.4
|
31
|
+
offset_str = "#{md[2]}#{off_h}:#{off_m}"
|
32
|
+
::Time.new(1970, 1, 1, 0, 0, 0, offset_str) + secm + ::Time.zone_offset(offset_str)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
module CoreIncl
|
40
|
+
module Time
|
41
|
+
module Format
|
42
|
+
# Welcome to Hell
|
43
|
+
# https://www.odata.org/documentation/odata-version-2-0/json-format/
|
44
|
+
# Edm.DateTime
|
45
|
+
# "/Date(<ticks>["+" | "-" <offset>)/"
|
46
|
+
# <ticks> = number of milliseconds since midnight Jan 1, 1970
|
47
|
+
# <offset> = number of minutes to add or subtract
|
48
|
+
# https://stackoverflow.com/questions/10286204/what-is-the-right-json-date-format/10286228#10286228
|
49
|
+
# also https://www.hanselman.com/blog/on-the-nightmare-that-is-json-dates-plus-jsonnet-and-aspnet-web-api
|
50
|
+
# and https://itecnote.com/tecnote/c-use-json-net-to-parse-json-date-of-format-dateepochtime-offset/
|
51
|
+
# https://docs.microsoft.com/de-de/dotnet/standard/datetime/system-text-json-support
|
52
|
+
# https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/stand-alone-json-serialization#datestimes-and-json
|
53
|
+
# https://blogs.sap.com/2017/01/05/date-and-time-in-sap-gateway-foundation/
|
54
|
+
def to_edm_json
|
55
|
+
if utc? || (gmt_offset == 0)
|
56
|
+
# no offset
|
57
|
+
# %s : seconds since unix epoch
|
58
|
+
# %L : milliseconds 000-999
|
59
|
+
# --> %S%L milliseconds since epoch
|
60
|
+
strftime('/Date(%s%L)/')
|
61
|
+
else
|
62
|
+
# same as above with GMT offset in minutes
|
63
|
+
|
64
|
+
min_off_s = (min_off = gmt_offset / 60) > 0 ? "+#{min_off}" : min_off.to_s
|
65
|
+
"/Date(#{strftime('%s%L')}#{min_off_s})/"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/odata/attribute.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'json'
|
4
|
-
require_relative '../safrano/core
|
5
|
-
require_relative './entity
|
4
|
+
require_relative '../safrano/core'
|
5
|
+
require_relative './entity'
|
6
6
|
|
7
7
|
module Safrano
|
8
8
|
# Represents a named and valued attribute of an Entity
|
@@ -18,12 +18,14 @@ module Safrano
|
|
18
18
|
def value
|
19
19
|
# WARNING ... this require more work to handle the timezones topci
|
20
20
|
# currently it is just set to make some minimal testcase work
|
21
|
+
# See also model_ext.rb
|
21
22
|
case (v = @entity.values[@name.to_sym])
|
23
|
+
when Date
|
24
|
+
v.to_edm_json
|
22
25
|
when Time
|
23
|
-
|
24
|
-
|
25
|
-
v.
|
26
|
-
|
26
|
+
v.to_edm_json
|
27
|
+
when DateTime
|
28
|
+
v.to_edm_json
|
27
29
|
else
|
28
30
|
v
|
29
31
|
end
|
data/lib/odata/batch.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../safrano/rack_app
|
4
|
-
require_relative '../safrano/core
|
3
|
+
require_relative '../safrano/rack_app'
|
4
|
+
require_relative '../safrano/core'
|
5
5
|
require 'rack/body_proxy'
|
6
|
-
require_relative './common_logger
|
6
|
+
require_relative './common_logger'
|
7
7
|
|
8
8
|
module Safrano
|
9
9
|
# Support for OData multipart $batch Requests
|
data/lib/odata/collection.rb
CHANGED
@@ -134,14 +134,14 @@ module Safrano
|
|
134
134
|
|
135
135
|
# on model class level we return the collection
|
136
136
|
def odata_get(req)
|
137
|
-
@params
|
137
|
+
@params ||= req.params
|
138
138
|
initialize_dataset
|
139
139
|
initialize_uparms
|
140
|
-
@uparms.check_all.if_valid
|
141
|
-
odata_get_apply_params.if_valid
|
140
|
+
@uparms.check_all.if_valid do |_ret|
|
141
|
+
odata_get_apply_params.if_valid do |_ret|
|
142
142
|
odata_get_output(req)
|
143
|
-
|
144
|
-
|
143
|
+
end
|
144
|
+
end.tap_error { |e| return e.odata_get(req) }.result
|
145
145
|
end
|
146
146
|
|
147
147
|
def odata_post(req)
|
@@ -143,8 +143,8 @@ module Safrano
|
|
143
143
|
# with directory Tree structure
|
144
144
|
|
145
145
|
class StaticTree < Static
|
146
|
-
SEP = '/00/'
|
147
|
-
VERS = '/v'
|
146
|
+
SEP = '/00/'
|
147
|
+
VERS = '/v'
|
148
148
|
|
149
149
|
def self.path_builder(ids)
|
150
150
|
ids.map { |id| id.to_s.chars.join('/') }.join(SEP) << VERS
|
@@ -276,7 +276,7 @@ module Safrano
|
|
276
276
|
|
277
277
|
media_handler.check_before_create(data: data,
|
278
278
|
entity: new_entity,
|
279
|
-
filename: filename).if_valid
|
279
|
+
filename: filename).if_valid do |_ret|
|
280
280
|
# to_one rels are create with FK data set on the parent entity
|
281
281
|
if parent
|
282
282
|
odata_create_save_entity_and_rel(req, new_entity, assoc, parent)
|
@@ -302,7 +302,7 @@ module Safrano
|
|
302
302
|
# Contract.valid([201, EMPTY_HASH, new_entity.to_odata_post_json(service: req.service)])
|
303
303
|
# TODO quirks array mode !
|
304
304
|
Contract.valid([201, EMPTY_HASH, new_entity.to_odata_create_json(request: req)])
|
305
|
-
|
305
|
+
end.tap_error { |e| return e.odata_get(req) }.result
|
306
306
|
|
307
307
|
else # TODO: other formats
|
308
308
|
415
|
@@ -311,26 +311,3 @@ module Safrano
|
|
311
311
|
end
|
312
312
|
end
|
313
313
|
end
|
314
|
-
|
315
|
-
# deprecated
|
316
|
-
# REMOVE 0.6
|
317
|
-
module OData
|
318
|
-
module Media
|
319
|
-
class Static < ::Safrano::Media::Static
|
320
|
-
def initialize(root: nil, mediaklass:)
|
321
|
-
::Safrano::Deprecation.deprecate('OData::Media::Static',
|
322
|
-
'Use Safrano::Media::Static instead')
|
323
|
-
|
324
|
-
super
|
325
|
-
end
|
326
|
-
end
|
327
|
-
class StaticTree < ::Safrano::Media::StaticTree
|
328
|
-
def initialize(root: nil, mediaklass:)
|
329
|
-
::Safrano::Deprecation.deprecate('OData::Media::StaticTree',
|
330
|
-
'Use Safrano::Media::StaticTree instead')
|
331
|
-
|
332
|
-
super
|
333
|
-
end
|
334
|
-
end
|
335
|
-
end
|
336
|
-
end
|
data/lib/odata/common_logger.rb
CHANGED
@@ -10,36 +10,14 @@ module Rack
|
|
10
10
|
# Handle https://github.com/rack/rack/pull/1526
|
11
11
|
# new in Rack 2.2.2 : Format has now 11 placeholders instead of 10
|
12
12
|
|
13
|
-
MSG_FUNC =
|
13
|
+
MSG_FUNC = case FORMAT.count('%')
|
14
|
+
when 10
|
14
15
|
lambda { |env, length, status, began_at|
|
15
|
-
FORMAT % [
|
16
|
-
env['HTTP_X_FORWARDED_FOR'] || env['REMOTE_ADDR'] || '-',
|
17
|
-
env['REMOTE_USER'] || '-',
|
18
|
-
Time.now.strftime('%d/%b/%Y:%H:%M:%S %z'),
|
19
|
-
env[REQUEST_METHOD],
|
20
|
-
env[SCRIPT_NAME] + env[PATH_INFO],
|
21
|
-
env[QUERY_STRING].empty? ? '' : "?#{env[QUERY_STRING]}",
|
22
|
-
env[SERVER_PROTOCOL],
|
23
|
-
status.to_s[0..3],
|
24
|
-
length,
|
25
|
-
Utils.clock_time - began_at
|
26
|
-
]
|
16
|
+
format(FORMAT, env['HTTP_X_FORWARDED_FOR'] || env['REMOTE_ADDR'] || '-', env['REMOTE_USER'] || '-', Time.now.strftime('%d/%b/%Y:%H:%M:%S %z'), env[REQUEST_METHOD], env[SCRIPT_NAME] + env[PATH_INFO], env[QUERY_STRING].empty? ? '' : "?#{env[QUERY_STRING]}", env[SERVER_PROTOCOL], status.to_s[0..3], length, Utils.clock_time - began_at)
|
27
17
|
}
|
28
|
-
|
18
|
+
when 11
|
29
19
|
lambda { |env, length, status, began_at|
|
30
|
-
FORMAT % [
|
31
|
-
env['HTTP_X_FORWARDED_FOR'] || env['REMOTE_ADDR'] || '-',
|
32
|
-
env['REMOTE_USER'] || '-',
|
33
|
-
Time.now.strftime('%d/%b/%Y:%H:%M:%S %z'),
|
34
|
-
env[REQUEST_METHOD],
|
35
|
-
env[SCRIPT_NAME],
|
36
|
-
env[PATH_INFO],
|
37
|
-
env[QUERY_STRING].empty? ? '' : "?#{env[QUERY_STRING]}",
|
38
|
-
env[SERVER_PROTOCOL],
|
39
|
-
status.to_s[0..3],
|
40
|
-
length,
|
41
|
-
Utils.clock_time - began_at
|
42
|
-
]
|
20
|
+
format(FORMAT, env['HTTP_X_FORWARDED_FOR'] || env['REMOTE_ADDR'] || '-', env['REMOTE_USER'] || '-', Time.now.strftime('%d/%b/%Y:%H:%M:%S %z'), env[REQUEST_METHOD], env[SCRIPT_NAME], env[PATH_INFO], env[QUERY_STRING].empty? ? '' : "?#{env[QUERY_STRING]}", env[SERVER_PROTOCOL], status.to_s[0..3], length, Utils.clock_time - began_at)
|
43
21
|
}
|
44
22
|
end
|
45
23
|
|
data/lib/odata/complex_type.rb
CHANGED
@@ -22,8 +22,8 @@ module Safrano
|
|
22
22
|
end
|
23
23
|
|
24
24
|
# we will have this on class and instance level for making things simpler first
|
25
|
-
|
26
|
-
|
25
|
+
class << self
|
26
|
+
attr_reader :klassmod
|
27
27
|
end
|
28
28
|
|
29
29
|
# return a subclass of ResultAsComplexType
|
@@ -88,8 +88,8 @@ module Safrano
|
|
88
88
|
# wrapper
|
89
89
|
# for OData Entity and Collections, return them directly
|
90
90
|
# for others, ie ComplexType, Prims etc, return the ResultDefinition-subclass wrapped result
|
91
|
-
def self.do_execute_func_result(result, _req,
|
92
|
-
|
91
|
+
def self.do_execute_func_result(result, _req, _apply_query_params = false)
|
92
|
+
new(result)
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
@@ -186,12 +186,12 @@ module Safrano
|
|
186
186
|
EMPTYH = {}.freeze
|
187
187
|
|
188
188
|
@namespace = nil
|
189
|
-
|
190
|
-
|
189
|
+
class << self
|
190
|
+
attr_reader :namespace
|
191
191
|
end
|
192
192
|
|
193
|
-
|
194
|
-
|
193
|
+
class << self
|
194
|
+
attr_reader :props
|
195
195
|
end
|
196
196
|
|
197
197
|
def type_name
|
@@ -214,11 +214,9 @@ module Safrano
|
|
214
214
|
expand_e = {}
|
215
215
|
|
216
216
|
template[:all_values] = EMPTYH
|
217
|
-
@props.each
|
218
|
-
if kl.respond_to? :default_template
|
219
|
-
|
220
|
-
end
|
221
|
-
}
|
217
|
+
@props.each do |prop, kl|
|
218
|
+
expand_e[prop] = kl.default_template if kl.respond_to? :default_template
|
219
|
+
end
|
222
220
|
template[:expand_e] = expand_e
|
223
221
|
template
|
224
222
|
end
|
@@ -228,7 +226,7 @@ module Safrano
|
|
228
226
|
end
|
229
227
|
|
230
228
|
def self.type_name
|
231
|
-
@namespace ? "#{@namespace}.#{self
|
229
|
+
@namespace ? "#{@namespace}.#{self}" : to_s
|
232
230
|
end
|
233
231
|
|
234
232
|
def initialize
|
@@ -240,13 +238,13 @@ module Safrano
|
|
240
238
|
def odata_h
|
241
239
|
ret = { METAK => { TYPEK => self.class.type_name } }
|
242
240
|
|
243
|
-
@values.each
|
241
|
+
@values.each do |k, v|
|
244
242
|
ret[k] = if v.respond_to? :odata_h
|
245
243
|
v.odata_h
|
246
244
|
else
|
247
245
|
v
|
248
246
|
end
|
249
|
-
|
247
|
+
end
|
250
248
|
ret
|
251
249
|
end
|
252
250
|
|
@@ -272,14 +270,14 @@ module Safrano
|
|
272
270
|
end
|
273
271
|
end
|
274
272
|
|
275
|
-
def
|
273
|
+
def self.ComplexType(**props)
|
276
274
|
Class.new(Safrano::ComplexType) do
|
277
275
|
@props = props
|
278
|
-
props.each
|
276
|
+
props.each do |a, _klassmod|
|
279
277
|
asym = a.to_sym
|
280
|
-
define_method(asym)
|
281
|
-
define_method("#{a}=")
|
282
|
-
|
278
|
+
define_method(asym) { @values[asym] }
|
279
|
+
define_method("#{a}=") { |val| @values[asym] = val }
|
280
|
+
end
|
283
281
|
define_method :initialize do |*p, **kwvals|
|
284
282
|
super()
|
285
283
|
p.zip(props.keys).each { |val, a| @values[a] = val } if p
|
@@ -42,8 +42,8 @@ module Safrano
|
|
42
42
|
metadata[:edm_type] = if (md = DB_TYPE_NUMDEC_RGX.match(props[:db_type]))
|
43
43
|
prec = md[4]
|
44
44
|
scale = md[6]
|
45
|
-
if
|
46
|
-
if
|
45
|
+
if scale && prec
|
46
|
+
if scale == '0' # dont force default scale to 0 like SQL standard
|
47
47
|
metadata[:edm_precision] = prec
|
48
48
|
"Edm.Decimal(#{prec})"
|
49
49
|
else
|
@@ -116,7 +116,6 @@ module Safrano
|
|
116
116
|
'Edm.Decimal'
|
117
117
|
when :blob
|
118
118
|
'Edm.Binary'
|
119
|
-
else
|
120
119
|
end
|
121
120
|
end
|
122
121
|
|
@@ -142,12 +141,12 @@ module Safrano
|
|
142
141
|
class Null < NilClass
|
143
142
|
extend OutputClassMethods
|
144
143
|
# nil --> null convertion is done by to_json
|
145
|
-
def self.odata_value(
|
144
|
+
def self.odata_value(_instance)
|
146
145
|
nil
|
147
146
|
end
|
148
147
|
|
149
148
|
def self.convert_from_urlparam(v)
|
150
|
-
return Contract::NOK unless
|
149
|
+
return Contract::NOK unless v == 'null'
|
151
150
|
|
152
151
|
Contract.valid(nil)
|
153
152
|
end
|
@@ -167,7 +166,7 @@ module Safrano
|
|
167
166
|
# or false([nil, false])
|
168
167
|
class Boolean < Object
|
169
168
|
extend OutputClassMethods
|
170
|
-
def
|
169
|
+
def self.odata_value(instance)
|
171
170
|
instance ? true : false
|
172
171
|
end
|
173
172
|
|
@@ -176,7 +175,7 @@ module Safrano
|
|
176
175
|
end
|
177
176
|
|
178
177
|
def self.convert_from_urlparam(v)
|
179
|
-
return Contract::NOK unless [
|
178
|
+
return Contract::NOK unless %w[true false].include?(v)
|
180
179
|
|
181
180
|
Contract.valid(v == 'true')
|
182
181
|
end
|
@@ -188,7 +187,7 @@ module Safrano
|
|
188
187
|
extend OutputClassMethods
|
189
188
|
|
190
189
|
def self.convert_from_urlparam(v)
|
191
|
-
return Contract::NOK unless (
|
190
|
+
return Contract::NOK unless (bytev = v.to_i) < 256
|
192
191
|
|
193
192
|
Contract.valid(bytev)
|
194
193
|
end
|
@@ -196,7 +195,7 @@ module Safrano
|
|
196
195
|
|
197
196
|
class DateTime < ::DateTime
|
198
197
|
extend OutputClassMethods
|
199
|
-
def
|
198
|
+
def self.odata_value(instance)
|
200
199
|
instance.to_datetime
|
201
200
|
end
|
202
201
|
|
@@ -205,11 +204,9 @@ module Safrano
|
|
205
204
|
end
|
206
205
|
|
207
206
|
def self.convert_from_urlparam(v)
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
return convertion_error(v)
|
212
|
-
end
|
207
|
+
Contract.valid(DateTime.parse(v))
|
208
|
+
rescue StandardError
|
209
|
+
convertion_error(v)
|
213
210
|
end
|
214
211
|
end
|
215
212
|
|
@@ -245,11 +242,9 @@ module Safrano
|
|
245
242
|
extend OutputClassMethods
|
246
243
|
|
247
244
|
def self.convert_from_urlparam(v)
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
return Contract::NOK
|
252
|
-
end
|
245
|
+
Contract.valid(v.to_f)
|
246
|
+
rescue StandardError
|
247
|
+
Contract::NOK
|
253
248
|
end
|
254
249
|
end
|
255
250
|
end
|