safrano 0.3.4 → 0.4.4
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/Dir/iter.rb +18 -0
- data/lib/core_ext/Hash/transform.rb +21 -0
- data/lib/core_ext/Integer/edm.rb +13 -0
- data/lib/core_ext/REXML/Document/output.rb +16 -0
- data/lib/core_ext/String/convert.rb +25 -0
- data/lib/core_ext/String/edm.rb +13 -0
- data/lib/core_ext/dir.rb +3 -0
- data/lib/core_ext/hash.rb +3 -0
- data/lib/core_ext/integer.rb +3 -0
- data/lib/core_ext/rexml.rb +3 -0
- data/lib/core_ext/string.rb +5 -0
- data/lib/odata/attribute.rb +15 -10
- data/lib/odata/batch.rb +17 -15
- data/lib/odata/collection.rb +141 -500
- data/lib/odata/collection_filter.rb +44 -37
- data/lib/odata/collection_media.rb +193 -43
- data/lib/odata/collection_order.rb +50 -37
- data/lib/odata/common_logger.rb +39 -12
- data/lib/odata/complex_type.rb +152 -0
- data/lib/odata/edm/primitive_types.rb +184 -0
- data/lib/odata/entity.rb +201 -176
- data/lib/odata/error.rb +186 -33
- data/lib/odata/expand.rb +126 -0
- data/lib/odata/filter/base.rb +69 -0
- data/lib/odata/filter/error.rb +55 -6
- data/lib/odata/filter/parse.rb +38 -36
- data/lib/odata/filter/sequel.rb +121 -67
- data/lib/odata/filter/sequel_function_adapter.rb +148 -0
- data/lib/odata/filter/token.rb +15 -11
- data/lib/odata/filter/tree.rb +110 -60
- data/lib/odata/function_import.rb +166 -0
- data/lib/odata/model_ext.rb +618 -0
- data/lib/odata/navigation_attribute.rb +50 -32
- data/lib/odata/relations.rb +7 -7
- data/lib/odata/select.rb +54 -0
- data/lib/{safrano_core.rb → odata/transition.rb} +14 -60
- data/lib/odata/url_parameters.rb +128 -37
- data/lib/odata/walker.rb +19 -11
- data/lib/safrano.rb +18 -28
- data/lib/safrano/contract.rb +143 -0
- data/lib/safrano/core.rb +43 -0
- data/lib/safrano/core_ext.rb +13 -0
- data/lib/safrano/deprecation.rb +73 -0
- data/lib/{multipart.rb → safrano/multipart.rb} +37 -41
- data/lib/safrano/rack_app.rb +175 -0
- data/lib/{odata_rack_builder.rb → safrano/rack_builder.rb} +18 -2
- data/lib/{request.rb → safrano/request.rb} +102 -50
- data/lib/{response.rb → safrano/response.rb} +5 -4
- data/lib/safrano/sequel_join_by_paths.rb +5 -0
- data/lib/{service.rb → safrano/service.rb} +257 -188
- data/lib/safrano/version.rb +5 -0
- data/lib/sequel/plugins/join_by_paths.rb +17 -29
- metadata +53 -17
- data/lib/rack_app.rb +0 -174
- data/lib/sequel_join_by_paths.rb +0 -5
- data/lib/version.rb +0 -4
@@ -1,31 +1,14 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'set'
|
4
4
|
require 'sequel'
|
5
5
|
|
6
|
-
|
7
|
-
class String
|
8
|
-
# thanks https://stackoverflow.com/questions/1448670/ruby-stringto-class
|
9
|
-
def constantize
|
10
|
-
names = split('::')
|
11
|
-
names.shift if names.empty? || names.first.empty?
|
12
|
-
|
13
|
-
const = Object
|
14
|
-
names.each do |name|
|
15
|
-
const = if const.const_defined?(name)
|
16
|
-
const.const_get(name)
|
17
|
-
else
|
18
|
-
const.const_missing(name)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
const
|
22
|
-
end
|
23
|
-
end
|
6
|
+
require 'safrano/core_ext'
|
24
7
|
|
25
8
|
class PathNode < String
|
26
|
-
attr_reader :table_name
|
27
9
|
attr_accessor :model_class
|
28
10
|
attr_accessor :path_str
|
11
|
+
|
29
12
|
def initialize(str, start_model)
|
30
13
|
super(str)
|
31
14
|
@start_model = start_model
|
@@ -80,14 +63,14 @@ class QPath
|
|
80
63
|
path_nodes = []
|
81
64
|
start_node.path_str = path_str
|
82
65
|
nodes = [start_node]
|
83
|
-
nodes.concat
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
66
|
+
nodes.concat(@qpath.split('/').map { |nstr| @start_model.create_path_node(nstr) })
|
67
|
+
return unless nodes.size > 1
|
68
|
+
|
69
|
+
nodes[0...-1].each_with_index do |node, i|
|
70
|
+
nodes[i + 1].set_model_class_by_parent_model(node.model_class)
|
71
|
+
path_nodes << nodes[i + 1]
|
72
|
+
nodes[i + 1].path_str = path_nodes.join('/')
|
73
|
+
@segments << [node, nodes[i + 1]]
|
91
74
|
end
|
92
75
|
end
|
93
76
|
end
|
@@ -96,13 +79,15 @@ class JoinByPathsHelper < Set
|
|
96
79
|
attr_reader :result
|
97
80
|
attr_reader :start_model
|
98
81
|
|
82
|
+
EMPTY_ARRAY = [].freeze
|
83
|
+
|
99
84
|
def initialize(smodel)
|
100
85
|
super()
|
101
86
|
@start_model = smodel
|
102
87
|
end
|
103
88
|
|
104
89
|
def build_unique_join_segments
|
105
|
-
return (@result =
|
90
|
+
return (@result = EMPTY_ARRAY) if empty?
|
106
91
|
|
107
92
|
maxlen = map(&:size).max
|
108
93
|
iset = nil
|
@@ -118,6 +103,7 @@ class JoinByPathsHelper < Set
|
|
118
103
|
jseg.map do |seg|
|
119
104
|
leftm = seg.first.model_class
|
120
105
|
assoc = leftm.association_reflection(seg.last.to_sym)
|
106
|
+
|
121
107
|
rightm = seg.last.model_class
|
122
108
|
# cf. documentation in sequel/model/associations.rb
|
123
109
|
case assoc[:type]
|
@@ -205,6 +191,7 @@ module Sequel
|
|
205
191
|
module ClassMethods
|
206
192
|
attr_reader :aliases_sym
|
207
193
|
attr_reader :alias_cnt
|
194
|
+
|
208
195
|
Plugins.inherited_instance_variables(self,
|
209
196
|
:@aliases_sym => :dup,
|
210
197
|
:@alias_cnt => :dup)
|
@@ -231,6 +218,7 @@ module Sequel
|
|
231
218
|
|
232
219
|
module DatasetMethods
|
233
220
|
attr_reader :join_helper
|
221
|
+
|
234
222
|
def join_by_paths(*pathlist)
|
235
223
|
model.join_by_paths_helper(*pathlist).dataset
|
236
224
|
end
|
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.
|
4
|
+
version: 0.4.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- oz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-10-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '5.15'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rfc2047
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: rake
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,13 +108,23 @@ dependencies:
|
|
94
108
|
- - "~>"
|
95
109
|
- !ruby/object:Gem::Version
|
96
110
|
version: '0.51'
|
97
|
-
description: Safrano is an OData server
|
98
|
-
email:
|
111
|
+
description: Safrano is an OData server library based on Ruby, Rack and Sequel.
|
112
|
+
email: dev@aithscel.eu
|
99
113
|
executables: []
|
100
114
|
extensions: []
|
101
115
|
extra_rdoc_files: []
|
102
116
|
files:
|
103
|
-
- lib/
|
117
|
+
- lib/core_ext/Dir/iter.rb
|
118
|
+
- lib/core_ext/Hash/transform.rb
|
119
|
+
- lib/core_ext/Integer/edm.rb
|
120
|
+
- lib/core_ext/REXML/Document/output.rb
|
121
|
+
- lib/core_ext/String/convert.rb
|
122
|
+
- lib/core_ext/String/edm.rb
|
123
|
+
- lib/core_ext/dir.rb
|
124
|
+
- lib/core_ext/hash.rb
|
125
|
+
- lib/core_ext/integer.rb
|
126
|
+
- lib/core_ext/rexml.rb
|
127
|
+
- lib/core_ext/string.rb
|
104
128
|
- lib/odata/attribute.rb
|
105
129
|
- lib/odata/batch.rb
|
106
130
|
- lib/odata/collection.rb
|
@@ -108,27 +132,40 @@ files:
|
|
108
132
|
- lib/odata/collection_media.rb
|
109
133
|
- lib/odata/collection_order.rb
|
110
134
|
- lib/odata/common_logger.rb
|
135
|
+
- lib/odata/complex_type.rb
|
136
|
+
- lib/odata/edm/primitive_types.rb
|
111
137
|
- lib/odata/entity.rb
|
112
138
|
- lib/odata/error.rb
|
139
|
+
- lib/odata/expand.rb
|
140
|
+
- lib/odata/filter/base.rb
|
113
141
|
- lib/odata/filter/error.rb
|
114
142
|
- lib/odata/filter/parse.rb
|
115
143
|
- lib/odata/filter/sequel.rb
|
144
|
+
- lib/odata/filter/sequel_function_adapter.rb
|
116
145
|
- lib/odata/filter/token.rb
|
117
146
|
- lib/odata/filter/tree.rb
|
147
|
+
- lib/odata/function_import.rb
|
148
|
+
- lib/odata/model_ext.rb
|
118
149
|
- lib/odata/navigation_attribute.rb
|
119
150
|
- lib/odata/relations.rb
|
151
|
+
- lib/odata/select.rb
|
152
|
+
- lib/odata/transition.rb
|
120
153
|
- lib/odata/url_parameters.rb
|
121
154
|
- lib/odata/walker.rb
|
122
|
-
- lib/odata_rack_builder.rb
|
123
|
-
- lib/rack_app.rb
|
124
|
-
- lib/request.rb
|
125
|
-
- lib/response.rb
|
126
155
|
- lib/safrano.rb
|
127
|
-
- lib/
|
156
|
+
- lib/safrano/contract.rb
|
157
|
+
- lib/safrano/core.rb
|
158
|
+
- lib/safrano/core_ext.rb
|
159
|
+
- lib/safrano/deprecation.rb
|
160
|
+
- lib/safrano/multipart.rb
|
161
|
+
- lib/safrano/rack_app.rb
|
162
|
+
- lib/safrano/rack_builder.rb
|
163
|
+
- lib/safrano/request.rb
|
164
|
+
- lib/safrano/response.rb
|
165
|
+
- lib/safrano/sequel_join_by_paths.rb
|
166
|
+
- lib/safrano/service.rb
|
167
|
+
- lib/safrano/version.rb
|
128
168
|
- lib/sequel/plugins/join_by_paths.rb
|
129
|
-
- lib/sequel_join_by_paths.rb
|
130
|
-
- lib/service.rb
|
131
|
-
- lib/version.rb
|
132
169
|
homepage: https://gitlab.com/dm0da/safrano
|
133
170
|
licenses:
|
134
171
|
- MIT
|
@@ -152,9 +189,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
152
189
|
- !ruby/object:Gem::Version
|
153
190
|
version: '0'
|
154
191
|
requirements: []
|
155
|
-
|
156
|
-
rubygems_version: 2.7.6.2
|
192
|
+
rubygems_version: 3.1.4
|
157
193
|
signing_key:
|
158
194
|
specification_version: 4
|
159
|
-
summary: Safrano is a Ruby
|
195
|
+
summary: Safrano is a Ruby OData server library based on Sequel and Rack
|
160
196
|
test_files: []
|
data/lib/rack_app.rb
DELETED
@@ -1,174 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'rack'
|
4
|
-
require_relative 'odata/walker.rb'
|
5
|
-
require_relative 'request.rb'
|
6
|
-
require_relative 'response.rb'
|
7
|
-
|
8
|
-
module OData
|
9
|
-
# handle GET PUT etc
|
10
|
-
module MethodHandlers
|
11
|
-
def odata_options
|
12
|
-
# cf. stackoverflow.com/questions/22924678/sinatra-delete-response-headers
|
13
|
-
|
14
|
-
x = if @walker.status == :end
|
15
|
-
headers.delete('Content-Type')
|
16
|
-
@response.headers.delete('Content-Type')
|
17
|
-
[200, {}, '']
|
18
|
-
else
|
19
|
-
odata_error
|
20
|
-
end
|
21
|
-
@response.headers['Content-Type'] = ''
|
22
|
-
x
|
23
|
-
end
|
24
|
-
|
25
|
-
def odata_error
|
26
|
-
return @walker.error.odata_get(@request) unless @walker.error.nil?
|
27
|
-
|
28
|
-
# this is too critical; raise a real Exception
|
29
|
-
raise 'Walker construction failed with a unknown Error '
|
30
|
-
end
|
31
|
-
|
32
|
-
def odata_delete
|
33
|
-
if @walker.status == :end
|
34
|
-
@walker.end_context.odata_delete(@request)
|
35
|
-
else
|
36
|
-
odata_error
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def odata_put
|
41
|
-
if @walker.status == :end
|
42
|
-
@walker.end_context.odata_put(@request)
|
43
|
-
else
|
44
|
-
odata_error
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def odata_patch
|
49
|
-
if @walker.status == :end
|
50
|
-
@walker.end_context.odata_patch(@request)
|
51
|
-
else
|
52
|
-
odata_error
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def odata_get
|
57
|
-
if @walker.status == :end
|
58
|
-
@walker.end_context.odata_get(@request)
|
59
|
-
else
|
60
|
-
odata_error
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def odata_post
|
65
|
-
if @walker.status == :end
|
66
|
-
@walker.end_context.odata_post(@request)
|
67
|
-
else
|
68
|
-
odata_error
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def odata_head
|
73
|
-
[200, {}, ['']]
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
# the main Rack server app. Source: the Rack docu/examples and partly
|
78
|
-
# inspired from Sinatra
|
79
|
-
class ServerApp
|
80
|
-
METHODS_REGEXP = Regexp.new('HEAD|OPTIONS|GET|POST|PATCH|MERGE|PUT|DELETE')
|
81
|
-
include MethodHandlers
|
82
|
-
def before
|
83
|
-
headers 'Cache-Control' => 'no-cache'
|
84
|
-
headers 'Expires' => '-1'
|
85
|
-
headers 'Pragma' => 'no-cache'
|
86
|
-
|
87
|
-
@request.service_base = self.class.get_service_base
|
88
|
-
|
89
|
-
neg_error = @request.negotiate_service_version
|
90
|
-
|
91
|
-
raise RuntimeError if neg_error
|
92
|
-
|
93
|
-
return false unless @request.service
|
94
|
-
|
95
|
-
headers 'DataServiceVersion' => @request.service.data_service_version
|
96
|
-
end
|
97
|
-
|
98
|
-
# dispatch for all methods requiring parsing of the path
|
99
|
-
# with walker (ie. allmost all excepted HEAD)
|
100
|
-
def dispatch_with_walker
|
101
|
-
@walker = @request.create_odata_walker
|
102
|
-
case @request.request_method
|
103
|
-
when 'GET'
|
104
|
-
odata_get
|
105
|
-
when 'POST'
|
106
|
-
odata_post
|
107
|
-
when 'DELETE'
|
108
|
-
odata_delete
|
109
|
-
when 'OPTIONS'
|
110
|
-
odata_options
|
111
|
-
when 'PUT'
|
112
|
-
odata_put
|
113
|
-
when 'PATCH', 'MERGE'
|
114
|
-
odata_patch
|
115
|
-
else
|
116
|
-
raise Error
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
def dispatch
|
121
|
-
req_ret = if @request.request_method !~ METHODS_REGEXP
|
122
|
-
[404, {}, ['Did you get lost?']]
|
123
|
-
elsif @request.request_method == 'HEAD'
|
124
|
-
odata_head
|
125
|
-
else
|
126
|
-
dispatch_with_walker
|
127
|
-
end
|
128
|
-
@response.status, rsph, @response.body = req_ret
|
129
|
-
headers rsph
|
130
|
-
end
|
131
|
-
|
132
|
-
def call(env)
|
133
|
-
@request = OData::Request.new(env)
|
134
|
-
@response = OData::Response.new
|
135
|
-
|
136
|
-
before
|
137
|
-
|
138
|
-
dispatch
|
139
|
-
|
140
|
-
@response.finish
|
141
|
-
end
|
142
|
-
|
143
|
-
# Set multiple response headers with Hash.
|
144
|
-
def headers(hash = nil)
|
145
|
-
@response.headers.merge! hash if hash
|
146
|
-
@response.headers
|
147
|
-
end
|
148
|
-
|
149
|
-
def self.enable_batch
|
150
|
-
@service_base.enable_batch
|
151
|
-
end
|
152
|
-
|
153
|
-
def self.path_prefix(path_pr)
|
154
|
-
@service_base.path_prefix path_pr
|
155
|
-
end
|
156
|
-
|
157
|
-
def self.get_service_base
|
158
|
-
@service_base
|
159
|
-
end
|
160
|
-
|
161
|
-
def self.set_servicebase(sbase)
|
162
|
-
@service_base = sbase
|
163
|
-
@service_base.enable_v1_service
|
164
|
-
@service_base.enable_v2_service
|
165
|
-
end
|
166
|
-
|
167
|
-
def self.publish_service(&block)
|
168
|
-
sbase = OData::ServiceBase.new
|
169
|
-
sbase.instance_eval(&block) if block_given?
|
170
|
-
sbase.finalize_publishing
|
171
|
-
set_servicebase(sbase)
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
data/lib/sequel_join_by_paths.rb
DELETED
data/lib/version.rb
DELETED