safrano 0.5.3 → 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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/lib/core_ext/Date/format.rb +47 -0
  3. data/lib/core_ext/DateTime/format.rb +54 -0
  4. data/lib/core_ext/Dir/iter.rb +7 -5
  5. data/lib/core_ext/Hash/transform.rb +14 -6
  6. data/lib/core_ext/Numeric/convert.rb +25 -0
  7. data/lib/core_ext/Time/format.rb +71 -0
  8. data/lib/core_ext/date.rb +5 -0
  9. data/lib/core_ext/datetime.rb +5 -0
  10. data/lib/core_ext/numeric.rb +3 -0
  11. data/lib/core_ext/time.rb +5 -0
  12. data/lib/odata/attribute.rb +8 -6
  13. data/lib/odata/batch.rb +3 -3
  14. data/lib/odata/collection.rb +9 -9
  15. data/lib/odata/collection_filter.rb +3 -1
  16. data/lib/odata/collection_media.rb +4 -27
  17. data/lib/odata/collection_order.rb +1 -1
  18. data/lib/odata/common_logger.rb +5 -27
  19. data/lib/odata/complex_type.rb +61 -67
  20. data/lib/odata/edm/primitive_types.rb +110 -42
  21. data/lib/odata/entity.rb +14 -47
  22. data/lib/odata/error.rb +7 -7
  23. data/lib/odata/expand.rb +2 -2
  24. data/lib/odata/filter/base.rb +10 -1
  25. data/lib/odata/filter/error.rb +2 -2
  26. data/lib/odata/filter/parse.rb +16 -2
  27. data/lib/odata/filter/sequel.rb +31 -4
  28. data/lib/odata/filter/sequel_datetime_adapter.rb +21 -0
  29. data/lib/odata/filter/token.rb +18 -5
  30. data/lib/odata/filter/tree.rb +83 -9
  31. data/lib/odata/function_import.rb +19 -18
  32. data/lib/odata/model_ext.rb +96 -38
  33. data/lib/odata/request/json.rb +171 -0
  34. data/lib/odata/transition.rb +13 -9
  35. data/lib/odata/url_parameters.rb +3 -3
  36. data/lib/odata/walker.rb +9 -9
  37. data/lib/safrano/multipart.rb +1 -3
  38. data/lib/safrano/rack_app.rb +2 -14
  39. data/lib/safrano/rack_builder.rb +0 -15
  40. data/lib/safrano/request.rb +3 -3
  41. data/lib/safrano/response.rb +3 -3
  42. data/lib/safrano/service.rb +43 -12
  43. data/lib/safrano/type_mapping.rb +149 -0
  44. data/lib/safrano/version.rb +1 -2
  45. data/lib/safrano.rb +3 -0
  46. metadata +54 -15
@@ -12,153 +12,148 @@ module Safrano
12
12
  VALUEK = 'value'
13
13
  RESULTSK = 'results'
14
14
  COLLECTION = 'Collection'
15
-
15
+
16
16
  def allowed_transitions
17
17
  [Safrano::TransitionEnd]
18
18
  end
19
-
19
+
20
20
  def transition_end(_match_result)
21
21
  Safrano::Transition::RESULT_END
22
22
  end
23
-
23
+
24
24
  # we will have this on class and instance level for making things simpler first
25
- def self.klassmod
26
- @klassmod
25
+ class << self
26
+ attr_reader :klassmod
27
27
  end
28
-
28
+
29
29
  # return a subclass of ResultAsComplexType
30
30
  def self.asComplexType(klassmod)
31
31
  Class.new(ResultAsComplexType) do
32
32
  @klassmod = klassmod
33
33
  end
34
34
  end
35
-
35
+
36
36
  # return a subclass of ResultAsComplexType
37
37
  def self.asComplexTypeColl(klassmod)
38
38
  Class.new(ResultAsComplexTypeColl) do
39
39
  @klassmod = klassmod
40
40
  end
41
41
  end
42
-
42
+
43
43
  def self.asPrimitiveType(klassmod)
44
44
  Class.new(ResultAsPrimitiveType) do
45
45
  @klassmod = klassmod
46
46
  end
47
47
  end
48
-
48
+
49
49
  def self.asPrimitiveTypeColl(klassmod)
50
50
  Class.new(ResultAsPrimitiveTypeColl) do
51
51
  @klassmod = klassmod
52
52
  end
53
- end
54
-
53
+ end
54
+
55
55
  def self.asEntity(klassmod)
56
56
  Class.new(ResultAsEntity) do
57
57
  @klassmod = klassmod
58
58
  end
59
59
  end
60
-
60
+
61
61
  def self.asEntityColl(klassmod)
62
62
  Class.new(ResultAsEntityColl) do
63
63
  @klassmod = klassmod
64
64
  end
65
65
  end
66
-
66
+
67
67
  def initialize(value)
68
68
  @value = value
69
69
  end
70
-
70
+
71
71
  def odata_get(req)
72
72
  [200, EMPTY_HASH, [to_odata_json(req)]]
73
73
  end
74
+
74
75
  def self.type_metadata
75
76
  @klassmod.type_name
76
77
  end
78
+
77
79
  def type_metadata
78
80
  self.class.type_metadata
79
81
  end
80
-
82
+
81
83
  # needed for ComplexType result
82
84
  def to_odata_json(_req)
83
85
  "#{DJ_OPEN}#{@value.odata_h.to_json}#{DJ_CLOSE}"
84
- end
85
-
86
- # wrapper
86
+ end
87
+
88
+ # wrapper
87
89
  # for OData Entity and Collections, return them directly
88
90
  # 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
+ def self.do_execute_func_result(result, _req, _apply_query_params = false)
92
+ new(result)
91
93
  end
92
-
93
94
  end
94
-
95
+
95
96
  class ResultAsComplexType < ResultDefinition
96
97
  def self.type_metadata
97
98
  @klassmod.type_name
98
99
  end
99
100
  end
100
-
101
+
101
102
  class ResultAsComplexTypeColl < ResultDefinition
102
103
  def self.type_metadata
103
104
  "Collection(#{@klassmod.type_name})"
104
105
  end
105
106
 
106
107
  def to_odata_json(req)
107
- # "#{DJ_OPEN}#{{ RESULTSK => coll.map { |c| c.odata_h } }.to_json}#{DJ_CLOSE}"
108
+ # "#{DJ_OPEN}#{{ RESULTSK => coll.map { |c| c.odata_h } }.to_json}#{DJ_CLOSE}"
108
109
  template = self.class.klassmod.output_template
109
110
  # TODO: Error handling if database contains binary BLOB data that cant be
110
111
  # interpreted as UTF-8 then JSON will fail here
111
112
 
112
113
  innerh = req.service.get_coll_odata_h(array: @value,
113
114
  template: template)
114
-
115
+
115
116
  innerj = innerh.to_json
116
117
 
117
118
  "#{DJ_OPEN}#{innerj}#{DJ_CLOSE}"
118
119
  end
119
120
  end
120
-
121
+
121
122
  class ResultAsEntity < ResultDefinition
122
-
123
123
  def self.type_metadata
124
124
  @klassmod.type_name
125
125
  end
126
126
 
127
-
128
- # wrapper
127
+ # wrapper
129
128
  # 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
129
+ def self.do_execute_func_result(result, _req, apply_query_params = false)
130
+ # note: Sequel entities instances seem to be thread safe, so we can
132
131
  # safely add request-dependant data (eg. req.params) there
133
132
  apply_query_params ? result : result.inactive_query_params
134
133
  end
135
-
136
134
  end
137
-
135
+
138
136
  class ResultAsEntityColl < ResultDefinition
139
-
140
137
  def self.type_metadata
141
138
  "Collection(#{@klassmod.type_name})"
142
139
  end
143
-
144
- # wrapper
140
+
141
+ # wrapper
145
142
  # for OData Entity Collection return them directly
146
- def self.do_execute_func_result(result, req, apply_query_params=false)
143
+ def self.do_execute_func_result(result, req, apply_query_params = false)
147
144
  coll = Safrano::OData::Collection.new(@klassmod)
148
145
  # instance_exec has other instance variables; @values would be nil in the block below
149
146
  # need to pass a local copy
150
147
  dtset = result
151
148
  coll.instance_exec do
152
-
153
- @params = apply_query_params ? req.params : EMPTY_HASH
149
+ @params = apply_query_params ? req.params : EMPTY_HASH
154
150
  initialize_dataset(dtset)
155
151
  initialize_uparms
156
152
  end
157
153
  coll
158
154
  end
159
-
160
155
  end
161
-
156
+
162
157
  class ResultAsPrimitiveType < ResultDefinition
163
158
  def self.type_metadata
164
159
  @klassmod.type_name
@@ -169,7 +164,7 @@ module Safrano
169
164
  VALUEK => self.class.klassmod.odata_value(@value) } }.to_json
170
165
  end
171
166
  end
172
-
167
+
173
168
  class ResultAsPrimitiveTypeColl < ResultDefinition
174
169
  def self.type_metadata
175
170
  "Collection(#{@klassmod.type_name})"
@@ -179,7 +174,6 @@ module Safrano
179
174
  { D => { METAK => { TYPEK => self.class.type_metadata },
180
175
  RESULTSK => self.class.klassmod.odata_collection(@value) } }.to_json
181
176
  end
182
-
183
177
  end
184
178
  end
185
179
 
@@ -188,51 +182,51 @@ module Safrano
188
182
  # with added OData functionality
189
183
  class ComplexType
190
184
  attr_reader :values
185
+
191
186
  EMPTYH = {}.freeze
192
-
187
+
193
188
  @namespace = nil
194
- def self.namespace
195
- @namespace
189
+ class << self
190
+ attr_reader :namespace
196
191
  end
197
192
 
198
- def self.props
199
- @props
193
+ class << self
194
+ attr_reader :props
200
195
  end
201
-
196
+
202
197
  def type_name
203
198
  self.class.type_name
204
199
  end
205
-
200
+
206
201
  def metadata_h
207
202
  { type: type_name }
208
203
  end
209
-
204
+
210
205
  def casted_values
211
206
  # MVP... TODO: handle time mappings like in Entity models
212
207
  values
213
208
  end
214
-
209
+
215
210
  # needed for nested json output
216
211
  # this is a simpler version of model_ext#output_template
217
212
  def self.default_template
218
213
  template = {}
219
214
  expand_e = {}
220
-
215
+
221
216
  template[:all_values] = EMPTYH
222
- @props.each { |prop, kl|
223
- if kl.respond_to? :default_template
224
- expand_e[prop] = kl.default_template
225
- end
226
- }
217
+ @props.each do |prop, kl|
218
+ expand_e[prop] = kl.default_template if kl.respond_to? :default_template
219
+ end
227
220
  template[:expand_e] = expand_e
228
221
  template
229
222
  end
230
-
223
+
231
224
  def self.output_template
232
225
  default_template
233
226
  end
227
+
234
228
  def self.type_name
235
- @namespace ? "#{@namespace}.#{self.to_s}" : self.to_s
229
+ @namespace ? "#{@namespace}.#{self}" : to_s
236
230
  end
237
231
 
238
232
  def initialize
@@ -244,13 +238,13 @@ module Safrano
244
238
  def odata_h
245
239
  ret = { METAK => { TYPEK => self.class.type_name } }
246
240
 
247
- @values.each { |k, v|
241
+ @values.each do |k, v|
248
242
  ret[k] = if v.respond_to? :odata_h
249
243
  v.odata_h
250
244
  else
251
245
  v
252
246
  end
253
- }
247
+ end
254
248
  ret
255
249
  end
256
250
 
@@ -276,14 +270,14 @@ module Safrano
276
270
  end
277
271
  end
278
272
 
279
- def Safrano.ComplexType(**props)
273
+ def self.ComplexType(**props)
280
274
  Class.new(Safrano::ComplexType) do
281
275
  @props = props
282
- props.each { |a, klassmod|
276
+ props.each do |a, _klassmod|
283
277
  asym = a.to_sym
284
- define_method(asym) do @values[asym] end
285
- define_method("#{a}=") do |val| @values[asym] = val end
286
- }
278
+ define_method(asym) { @values[asym] }
279
+ define_method("#{a}=") { |val| @values[asym] = val }
280
+ end
287
281
  define_method :initialize do |*p, **kwvals|
288
282
  super()
289
283
  p.zip(props.keys).each { |val, a| @values[a] = val } if p
@@ -15,36 +15,108 @@ module Safrano
15
15
  # Classes specifying generic types that Sequel will convert to
16
16
  # database-specific types.
17
17
  DB_TYPE_STRING_RGX = /\ACHAR\s*\(\d+\)\z/.freeze
18
-
18
+ DB_TYPE_NUMDEC_RGX = /\A(NUMERIC|DECIMAL)\s*(\(\s*((\d+)\s*(,\s*(\d+))?)\s*\))?\s*\z/i.freeze
19
+ # thank you rubular
20
+ # Test String: DECIMAL (55,2 )
21
+ # Match groups
22
+ # 1 DECIMAL
23
+ # 2 (55,2 )
24
+ # 3 55,2
25
+ # 4 55
26
+ # 5 ,2
27
+ # 6 2
28
+
29
+ DB_TYPE_FLOATP_RGX = /\A\s*(FLOAT)\s*(\(\s*(\d+)\s*\))?\s*\z/i.freeze
30
+
31
+ # Note: "char" (quoted!) is postgresql's byte type
32
+ DB_TYPE_INTLIKE_RGX = /\A\s*(smallserial|smallint|integer|int2|int4|int8|int|mediumint|bigint|serial|bigserial|tinyint)\s*/i.freeze
19
33
  # used in $metadata
20
34
  # cf. Sequel Database column_schema_default_to_ruby_value
21
35
  # schema_column_type
22
36
  # https://www.odata.org/documentation/odata-version-2-0/overview/
23
- def self.default_edm_type(ruby_type:, db_type: )
24
- case ruby_type
25
- when :integer
26
- 'Edm.Int32'
27
- when :string
28
- 'Edm.String'
29
- when :date
30
- 'Edm.DateTime'
31
- when :datetime
32
- 'Edm.DateTime'
33
- when :time
34
- 'Edm.Time'
35
- when :boolean
36
- 'Edm.Boolean'
37
- when :float
38
- 'Edm.Double'
39
- when :decimal
40
- 'Edm.Decimal'
41
- when :blob
42
- 'Edm.Binary'
43
- else # try with db_type:
44
- if ( db_type =~ /\ANUMERIC/ )
45
- 'Edm.Decimal'
46
- end
47
- end
37
+
38
+ # type mappings are hard, especially between "Standards" like SQL and OData V2 (might be a bit better in V4 ?)
39
+ # this is all best effort/try to make it work logic
40
+ def self.add_edm_types(metadata, props)
41
+ # try num/dec with db_type:
42
+ metadata[:edm_type] = if (md = DB_TYPE_NUMDEC_RGX.match(props[:db_type]))
43
+ prec = md[4]
44
+ scale = md[6]
45
+ if scale && prec
46
+ if scale == '0' # dont force default scale to 0 like SQL standard
47
+ metadata[:edm_precision] = prec
48
+ "Edm.Decimal(#{prec})"
49
+ else
50
+ # we have precision and scale
51
+ metadata[:edm_scale] = scale
52
+ metadata[:edm_precision] = prec
53
+ "Edm.Decimal(#{prec},#{scale})"
54
+ end
55
+ elsif prec
56
+ # we have precision only
57
+ metadata[:edm_precision] = prec
58
+ "Edm.Decimal(#{prec})"
59
+ else
60
+ 'Edm.Decimal'
61
+ end
62
+ end
63
+ return if metadata[:edm_type]
64
+
65
+ # try float(prec) with db_type:
66
+ metadata[:edm_type] = if (md = DB_TYPE_FLOATP_RGX.match(props[:db_type]))
67
+ # FLOAT( 22) match groups
68
+ # 1 FLOAT
69
+ # 2 (22 )
70
+ # 3 22
71
+
72
+ if (prec = md[3])
73
+ # we have precision only
74
+ metadata[:edm_precision] = prec
75
+ 'Edm.Double'
76
+ end
77
+ end
78
+ return if metadata[:edm_type]
79
+
80
+ # try int-like with db_type:
81
+ # smallint|int|integer|bigint|serial|bigserial
82
+ metadata[:edm_type] = if (md = DB_TYPE_INTLIKE_RGX.match(props[:db_type]))
83
+
84
+ if (itype = md[1])
85
+ case itype.downcase
86
+ when 'smallint', 'int2', 'smallserial'
87
+ 'Edm.Int16'
88
+ when 'int', 'integer', 'serial', 'mediumint', 'int4'
89
+ 'Edm.Int32'
90
+ when 'bigint', 'bigserial', 'int8'
91
+ 'Edm.Int64'
92
+ when 'tinyint'
93
+ 'Edm.Byte'
94
+ end
95
+ end
96
+ end
97
+ return if metadata[:edm_type]
98
+
99
+ # try with Sequel(ruby) type
100
+ metadata[:edm_type] = case props[:type]
101
+ when :integer
102
+ 'Edm.Int32'
103
+ when :string
104
+ 'Edm.String'
105
+ when :date
106
+ 'Edm.DateTime'
107
+ when :datetime
108
+ 'Edm.DateTime'
109
+ when :time
110
+ 'Edm.Time'
111
+ when :boolean
112
+ 'Edm.Boolean'
113
+ when :float
114
+ 'Edm.Double'
115
+ when :decimal
116
+ 'Edm.Decimal'
117
+ when :blob
118
+ 'Edm.Binary'
119
+ end
48
120
  end
49
121
 
50
122
  # use Edm twice so that we can do include Safrano::Edm and then
@@ -69,12 +141,12 @@ module Safrano
69
141
  class Null < NilClass
70
142
  extend OutputClassMethods
71
143
  # nil --> null convertion is done by to_json
72
- def self.odata_value(instance)
144
+ def self.odata_value(_instance)
73
145
  nil
74
146
  end
75
147
 
76
148
  def self.convert_from_urlparam(v)
77
- return Contract::NOK unless (v == 'null')
149
+ return Contract::NOK unless v == 'null'
78
150
 
79
151
  Contract.valid(nil)
80
152
  end
@@ -94,7 +166,7 @@ module Safrano
94
166
  # or false([nil, false])
95
167
  class Boolean < Object
96
168
  extend OutputClassMethods
97
- def Boolean.odata_value(instance)
169
+ def self.odata_value(instance)
98
170
  instance ? true : false
99
171
  end
100
172
 
@@ -103,7 +175,7 @@ module Safrano
103
175
  end
104
176
 
105
177
  def self.convert_from_urlparam(v)
106
- return Contract::NOK unless ['true', 'false'].include?(v)
178
+ return Contract::NOK unless %w[true false].include?(v)
107
179
 
108
180
  Contract.valid(v == 'true')
109
181
  end
@@ -115,7 +187,7 @@ module Safrano
115
187
  extend OutputClassMethods
116
188
 
117
189
  def self.convert_from_urlparam(v)
118
- return Contract::NOK unless ((bytev = v.to_i) < 256)
190
+ return Contract::NOK unless (bytev = v.to_i) < 256
119
191
 
120
192
  Contract.valid(bytev)
121
193
  end
@@ -123,7 +195,7 @@ module Safrano
123
195
 
124
196
  class DateTime < ::DateTime
125
197
  extend OutputClassMethods
126
- def DateTime.odata_value(instance)
198
+ def self.odata_value(instance)
127
199
  instance.to_datetime
128
200
  end
129
201
 
@@ -132,11 +204,9 @@ module Safrano
132
204
  end
133
205
 
134
206
  def self.convert_from_urlparam(v)
135
- begin
136
- Contract.valid(DateTime.parse(v))
137
- rescue
138
- return convertion_error(v)
139
- end
207
+ Contract.valid(DateTime.parse(v))
208
+ rescue StandardError
209
+ convertion_error(v)
140
210
  end
141
211
  end
142
212
 
@@ -172,11 +242,9 @@ module Safrano
172
242
  extend OutputClassMethods
173
243
 
174
244
  def self.convert_from_urlparam(v)
175
- begin
176
- Contract.valid(v.to_f)
177
- rescue
178
- return Contract::NOK
179
- end
245
+ Contract.valid(v.to_f)
246
+ rescue StandardError
247
+ Contract::NOK
180
248
  end
181
249
  end
182
250
  end
data/lib/odata/entity.rb CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  require 'json'
4
4
  require 'rexml/document'
5
- require 'safrano.rb'
6
- require 'odata/model_ext.rb' # required for self.class.entity_type_name ??
5
+ require 'safrano'
6
+ require 'odata/model_ext' # required for self.class.entity_type_name ??
7
7
  require_relative 'navigation_attribute'
8
8
 
9
9
  module Safrano
@@ -86,9 +86,9 @@ module Safrano
86
86
  "#{self.class.uri}#{@odata_pk}"
87
87
  end
88
88
 
89
- D = 'd'.freeze
90
- DJ_OPEN = '{"d":'.freeze
91
- DJ_CLOSE = '}'.freeze
89
+ D = 'd'
90
+ DJ_OPEN = '{"d":'
91
+ DJ_CLOSE = '}'
92
92
 
93
93
  # Json formatter for a single entity (probably OData V1/V2 like)
94
94
  def to_odata_json(request:)
@@ -151,11 +151,12 @@ 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
155
  def inactive_query_params
155
156
  @inactive_query_params = true
156
157
  self # chaining
157
158
  end
158
-
159
+
159
160
  DELETE_REL_AND_ENTY = lambda do |entity, assoc, parent|
160
161
  Safrano.remove_nav_relation(assoc, parent)
161
162
  entity.destroy(transaction: false)
@@ -175,7 +176,7 @@ module Safrano
175
176
  destroy(transaction: false)
176
177
  end
177
178
  rescue StandardError => e
178
- raise SequelAdapterError.new(e)
179
+ raise SequelAdapterError, e
179
180
  end
180
181
 
181
182
  # TODO: differentiate between POST/PUT/PATCH/MERGE
@@ -202,7 +203,7 @@ module Safrano
202
203
  if req.walker.media_value
203
204
  odata_media_value_put(req)
204
205
  elsif req.accept?(APPJSON)
205
- data = JSON.parse(req.body.read)
206
+ data = Safrano::OData::JSON.parse_one(req.body.read, self.class)
206
207
  data.delete('__metadata')
207
208
 
208
209
  if req.in_changeset
@@ -219,7 +220,7 @@ module Safrano
219
220
  end
220
221
 
221
222
  def odata_patch(req)
222
- req.with_parsed_data do |data|
223
+ req.with_parsed_data(self.class) do |data|
223
224
  data.delete('__metadata')
224
225
 
225
226
  # validate payload column names
@@ -310,40 +311,6 @@ module Safrano
310
311
  end
311
312
  end
312
313
 
313
- module MappingBeforeOutput
314
- # needed for proper datetime or Decimal output
315
- def casted_values(cols = nil)
316
- vals = case cols
317
- when nil
318
- # we need to dup the model values as we need to change it before passing to_json,
319
- # but we dont want to interfere with Sequel's owned data
320
- # (eg because then in worst case it could happen that we write back changed values to DB)
321
- values_for_odata.dup
322
- else
323
- selected_values_for_odata(cols)
324
- end
325
- # TODO better design (perf/ do more during startup and less during request runtime )
326
- # TODO replace the quick and dirty BigDecimal hack with something better
327
- self.class.decimal_cols.each { |dc| vals[dc] = BigDecimal(vals[dc].to_s).to_s('F') if vals.key?(dc) }
328
-
329
- self.class.time_cols.each { |tc| vals[tc] = vals[tc]&.iso8601 if vals.key?(tc) }
330
- vals
331
- end
332
- end
333
- module NoMappingBeforeOutput
334
- # current model does not have eg. Time fields--> no special mapping, just to_json is fine
335
- # --> we can use directly the model.values (values_for_odata) withoud dup'ing it as we dont
336
- # need to change it, just output as is
337
- def casted_values(cols = nil)
338
- case cols
339
- when nil
340
- values_for_odata
341
- else
342
- selected_values_for_odata(cols)
343
- end
344
- end
345
- end
346
-
347
314
  module MediaEntity
348
315
  # media entity metadata for json h
349
316
  def metadata_h
@@ -434,9 +401,9 @@ module Safrano
434
401
  include Entity
435
402
  def pk_uri
436
403
  pku = +''
437
- self.class.odata_upk_parts.each_with_index { |upart, i|
404
+ self.class.odata_upk_parts.each_with_index do |upart, i|
438
405
  pku = "#{pku}#{upart}#{pk[i]}"
439
- }
406
+ end
440
407
  pku
441
408
  end
442
409
 
@@ -452,7 +419,7 @@ module Safrano
452
419
  module EntityCreateStandardOutput
453
420
  # Json formatter for a create entity POST call / Standard version; return as json object
454
421
  def to_odata_create_json(request:)
455
- # TODO Perf: reduce method call overhead
422
+ # TODO: Perf: reduce method call overhead
456
423
  # we added this redirection for readability and flexibility
457
424
  to_odata_json(request: request)
458
425
  end
@@ -461,7 +428,7 @@ module Safrano
461
428
  module EntityCreateArrayOutput
462
429
  # Json formatter for a create entity POST call Array version
463
430
  def to_odata_create_json(request:)
464
- # TODO Perf: reduce method call overhead
431
+ # TODO: Perf: reduce method call overhead
465
432
  # we added this redirection for readability and flexibility
466
433
  to_odata_array_json(request: request)
467
434
  end