Module: Safrano
- Includes:
- XMLNS
- Included in:
- ServiceBase
- Defined in:
- lib/odata/error.rb,
lib/odata/batch.rb,
lib/odata/entity.rb,
lib/odata/expand.rb,
lib/odata/select.rb,
lib/odata/walker.rb,
lib/safrano/core.rb,
lib/odata/attribute.rb,
lib/odata/model_ext.rb,
lib/odata/relations.rb,
lib/safrano/request.rb,
lib/safrano/service.rb,
lib/safrano/service.rb,
lib/safrano/service.rb,
lib/safrano/version.rb,
lib/odata/collection.rb,
lib/odata/transition.rb,
lib/safrano/contract.rb,
lib/safrano/rack_app.rb,
lib/safrano/response.rb,
lib/core_ext/Dir/iter.rb,
lib/odata/filter/base.rb,
lib/odata/filter/tree.rb,
lib/odata/complex_type.rb,
lib/odata/filter/error.rb,
lib/odata/filter/parse.rb,
lib/odata/filter/token.rb,
lib/odata/request/json.rb,
lib/core_ext/String/edm.rb,
lib/odata/filter/sequel.rb,
lib/safrano/deprecation.rb,
lib/core_ext/Date/format.rb,
lib/core_ext/Integer/edm.rb,
lib/core_ext/Time/format.rb,
lib/odata/url_parameters.rb,
lib/safrano/type_mapping.rb,
lib/odata/function_import.rb,
lib/odata/collection_media.rb,
lib/odata/collection_order.rb,
lib/core_ext/Hash/transform.rb,
lib/core_ext/String/convert.rb,
lib/odata/collection_filter.rb,
lib/core_ext/DateTime/format.rb,
lib/core_ext/Numeric/convert.rb,
lib/odata/edm/primitive_types.rb,
lib/odata/navigation_attribute.rb,
lib/core_ext/MatchData/matchlen.rb,
lib/core_ext/REXML/Document/output.rb,
lib/odata/filter/sequel_datetime_adapter.rb,
lib/odata/filter/sequel_function_adapter.rb
Overview
mach_length for ruby < 3.0
Defined Under Namespace
Modules: API, Batch, Contract, CoreExt, CoreIncl, Deprecation, Edm, Entity, EntityBase, EntityClassBase, EntityClassMedia, EntityClassMultiPK, EntityClassNonMedia, EntityClassSinglePK, EntityCreateArrayOutput, EntityCreateStandardOutput, EntityMultiPK, EntitySinglePK, ErrorClass, ErrorInstance, ExpandHandler, Filter, FunctionImport, Media, MediaEntity, MethodHandlers, NavigationInfo, NonMediaEntity, OData, PKUriWithFunc, PKUriWithoutFunc, RFC2047, Transitions, XJSON, XMLNS Classes: AlreadyExistsUnprocessableError, Attribute, AttributeTypeMapping, BadRequestEmptyMediaUpload, BadRequestError, BadRequestExpandInvalidPath, BadRequestFailedChangeSet, BadRequestFilterParseError, BadRequestInlineCountParamError, BadRequestInvalidAttribPath, BadRequestNonMediaValue, BadRequestOrderParseError, BadRequestSelectInvalidProps, BadRequestSequelAdapterError, BatchNotImplementedError, ComplexType, ErrorNotFound, ErrorNotFoundSegment, Expand, ExpandBase, FilterBase, FilterByParse, FilterFunctionNotImplementedError, FilterParseError, FilterParseErrorWrongColumnName, FilterParseWrappedError, FilterUnknownFunctionError, InplaceTransition, InplaceTransitionResult, MultiExpand, MultiOrder, NilNavigationAttribute, NotImplementedError, Order, OrderBase, Relation, RelationManager, Request, Response, RgxFixedTypeMapping, RgxTypeMapping, RgxTypeMapping1Par, RgxTypeMapping2Par, RubyStandardErrorException, Select, SelectBase, SequelAdapterError, SequelExceptionError, ServerApp, ServerError, ServerTransitionError, ServiceBase, ServiceMeta, ServiceOperationError, ServiceOperationParameterError, ServiceOperationParameterMissing, ServiceV1, ServiceV2, Transition, TransitionResult, TypeMapping, UnprocessableEntityError, UrlParameters4Coll, UrlParameters4Single, UrlParametersBase, VersionNotImplementedError, Walker
Constant Summary collapse
- EMPTY_ARRAY =
frozen empty Array/Hash to reduce unncecessary object creation
[].freeze
- EMPTY_HASH =
{}.freeze
- EMPTY_HASH_IN_ARY =
[EMPTY_HASH].freeze
- EMPTY_STRING =
''
- ARY_204_EMPTY_HASH_ARY =
[204, EMPTY_HASH, EMPTY_ARRAY].freeze
- SPACE =
' '
- COMMA =
','
- CONTENT_TYPE =
some prominent constants… probably already defined elsewhere eg in Rack but lets KISS
'content-type'
- CONTENT_LENGTH =
'content-length'
- LOCATION =
'location'
- TEXTPLAIN_UTF8 =
'text/plain;charset=utf-8'
- APPJSON =
'application/json'
- APPXML =
'application/xml'
- MP_MIXED =
'multipart/mixed'
- APPXML_UTF8 =
'application/xml;charset=utf-8'
- APPATOMXML_UTF8 =
'application/atomsvc+xml;charset=utf-8'
- APPJSON_UTF8 =
'application/json;charset=utf-8'
- CT_JSON =
{ CONTENT_TYPE => APPJSON_UTF8 }.freeze
- CT_TEXT =
{ CONTENT_TYPE => TEXTPLAIN_UTF8 }.freeze
- CT_ATOMXML =
{ CONTENT_TYPE => APPATOMXML_UTF8 }.freeze
- CT_APPXML =
{ CONTENT_TYPE => APPXML_UTF8 }.freeze
- METADATA_K =
these modules have all methods related to expand/defered output preparation and will be included in Service class
'__metadata'
- EMPTYH =
{}.freeze
- MAX_DATASERVICE_VERSION =
'2'
- MIN_DATASERVICE_VERSION =
'1'
- CV_MAX_DATASERVICE_VERSION =
Contract.valid(MAX_DATASERVICE_VERSION).freeze
- CV_MIN_DATASERVICE_VERSION =
Contract.valid(MIN_DATASERVICE_VERSION).freeze
- TRAILING_SLASH_RGX =
%r{/\z}.freeze
- LEADING_SLASH_RGX =
%r{\A/}.freeze
- GENERIC_415_RESP =
[415, {}, ['']].freeze
- VERSION =
'0.8.2'
- TransitionEnd =
Transition.new('\A(\/?)\z', trans: :transition_end)
- TransitionExecuteFunc =
InplaceTransition.new(trans: :transition_execute_func)
- TransitionMetadata =
Transition.new('\A(\/\$metadata)(.*)', trans: :transition_metadata)
- TransitionBatch =
Transition.new('\A(\/\$batch)(.*)', trans: :transition_batch)
- TransitionContentId =
Transition.new('\A(\/\$(\d+))(.*)', trans: :transition_content_id, remain_idx: 3)
- TransitionCount =
Transition.new('(\A\/\$count)(.*)\z', trans: :transition_count)
- TransitionValue =
Transition.new('(\A\/\$value)(.*)\z', trans: :transition_value)
- TransitionLinks =
Transition.new('(\A\/\$links)(.*)\z', trans: :transition_links)
- DB_TYPE_STRING_RGX =
TODO: use Sequel GENERIC_TYPES: –> Constants GENERIC_TYPES = %w’String Integer Float Numeric BigDecimal Date DateTime Time File TrueClass FalseClass’.freeze Classes specifying generic types that Sequel will convert to database-specific types.
/\ACHAR\s*\(\d+\)\z/.freeze
- DB_TYPE_NUMDEC_RGX =
/\A(NUMERIC|DECIMAL)\s*(\(\s*((\d+)\s*(,\s*(\d+))?)\s*\))?\s*\z/i.freeze
- DB_TYPE_GUID_RGX =
thank you rubular Test String: DECIMAL (55,2 ) Match groups 1 DECIMAL 2 (55,2 ) 3 55,2 4 55 5 ,2 6 2
/\A\s*(uuid)\s*\z/i.freeze
- DB_TYPE_FLOATP_RGX =
/\A\s*(FLOAT)\s*(\(\s*(\d+)\s*\))?\s*\z/i.freeze
- DB_TYPE_INTLIKE_RGX =
Note: “char” (quoted!) is postgresql’s byte type
/\A\s*(smallserial|smallint|integer|int2|int4|int8|int|mediumint|bigint|serial|bigserial|tinyint)\s*/i.freeze
- RUBY_TY_EDM_TY_MAP =
type mappings are hard, especially between “Standards” like SQL and OData V2 (might be a bit better in V4 ?) this is all best effort/try to make it work logic
{ integer: 'Edm.Int32', string: 'Edm.String', date: 'Edm.DateTime', datetime: 'Edm.DateTime', time: 'Edm.Time', boolean: 'Edm.Boolean', float: 'Edm.Double', decimal: 'Edm.Decimal', blob: 'Edm.Binary' }.freeze
- DB_TY_EDM_TY_MAP =
{ 'smallint' => 'Edm.Int16', 'int2' => 'Edm.Int16', 'smallserial' => 'Edm.Int16', 'int' => 'Edm.Int32', 'integer' => 'Edm.Int32', 'serial' => 'Edm.Int32', 'mediumint' => 'Edm.Int32', 'int4' => 'Edm.Int32', 'bigint' => 'Edm.Int64', 'bigserial' => 'Edm.Int64', 'int8' => 'Edm.Int64', 'tinyint' => 'Edm.Byte' }.freeze
Constants included from XMLNS
XMLNS::MSFT_ADO, XMLNS::MSFT_ADO_2007_EDMX, XMLNS::MSFT_ADO_2007_META, XMLNS::MSFT_ADO_2009_EDM, XMLNS::W3_2005_ATOM, XMLNS::W3_2007_APP
Instance Attribute Summary collapse
-
#allowed_transitions ⇒ Object
Returns the value of attribute allowed_transitions.
Class Method Summary collapse
- .add_edm_types(metadata, props) ⇒ Object
- .ComplexType(**props) ⇒ Object
-
.create_nav_relation(child, assoc, parent) ⇒ Object
link newly created entities(child) to an existing parent by following the association_reflection rules.
- .FunctionImport(name) ⇒ Object
-
.remove_nav_relation(assoc, parent) ⇒ Object
remove the relation between entity and parent by clearing the FK field(s) (if allowed).
-
.with_error(result) {|err| ... } ⇒ Object
used in function import error handling.
Instance Attribute Details
#allowed_transitions ⇒ Object
Returns the value of attribute allowed_transitions.
201 202 203 |
# File 'lib/odata/transition.rb', line 201 def allowed_transitions @allowed_transitions end |
Class Method Details
.add_edm_types(metadata, props) ⇒ Object
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/odata/edm/primitive_types.rb', line 63 def self.add_edm_types(, props) # try num/dec with db_type: [:edm_type] = if (md = DB_TYPE_NUMDEC_RGX.match(props[:db_type])) prec = md[4] scale = md[6] if scale && prec if scale == '0' # dont force default scale to 0 like SQL standard [:edm_precision] = prec "Edm.Decimal(#{prec})" else # we have precision and scale [:edm_scale] = scale [:edm_precision] = prec "Edm.Decimal(#{prec},#{scale})" end elsif prec # we have precision only [:edm_precision] = prec "Edm.Decimal(#{prec})" else 'Edm.Decimal' end end return if [:edm_type] # try float(prec) with db_type: [:edm_type] = if (md = DB_TYPE_FLOATP_RGX.match(props[:db_type])) # FLOAT( 22) match groups # 1 FLOAT # 2 (22 ) # 3 22 if (prec = md[3]) # we have precision only [:edm_precision] = prec 'Edm.Double' end end return if [:edm_type] # try int-like with db_type: # smallint|int|integer|bigint|serial|bigserial [:edm_type] = if (md = DB_TYPE_INTLIKE_RGX.match(props[:db_type])) if (itype = md[1]) DB_TY_EDM_TY_MAP[itype.downcase] end end return if [:edm_type] # try Guid with db_type: [:edm_type] = if DB_TYPE_GUID_RGX.match(props[:db_type]) 'Edm.Guid' end return if [:edm_type] # try with Sequel(ruby) type [:edm_type] = RUBY_TY_EDM_TY_MAP[props[:type]] end |
.ComplexType(**props) ⇒ Object
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 |
# File 'lib/odata/complex_type.rb', line 273 def self.ComplexType(**props) Class.new(Safrano::ComplexType) do @props = props props.each do |a, _klassmod| asym = a.to_sym define_method(asym) { @values[asym] } define_method("#{a}=") { |val| @values[asym] = val } end define_method :initialize do |*p, **kwvals| super() p.zip(props.keys).each { |val, a| @values[a] = val } if p kwvals.each { |a, val| @values[a] = val if props.key?(a) } if kwvals end end end |
.create_nav_relation(child, assoc, parent) ⇒ Object
link newly created entities(child) to an existing parent by following the association_reflection rules
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/odata/navigation_attribute.rb', line 28 def self.create_nav_relation(child, assoc, parent) return unless assoc # Note: this coding shares some bits from our sequel/plugins/join_by_paths, # method build_unique_join_segments # eventually there is an opportunity to have more reusable code here case assoc[:type] when :one_to_many, :one_to_one # sets the FK values in child to corresponding related parent key-values # thus creating the "link" between the new entity and the parent # if a FK value is already set (not nil/NULL) then only check the # consistency with the corresponding parent key-value # If the FK value and the parent key value are different, then it's a # a Bad Request error leftm = assoc[:model] # should be same as parent.class lks = [leftm.primary_key].flatten rks = [assoc[:key]].flatten join_cond = rks.zip(lks).to_h join_cond.each do |rk, lk| if child.values[rk] # FK in new entity from payload not nil, only check consistency # with the parent - id(s) # if (child.values[rk] != parent.pk_hash[lk]) # error... # TODO # end else # we can set the FK value, thus creating the "link" child.set(rk => parent.pk_hash[lk]) end end when :many_to_one # sets the FK values in parent to corresponding related child key-values # thus creating the "link" between the new entity and the parent # Per design, this can only be called when the FK value is nil # from NilNavigationAttribute.odata_post lks = [assoc[:key]].flatten rks = [child.class.primary_key].flatten join_cond = rks.zip(lks).to_h join_cond.each do |rk, lk| if parent.values[lk] # FK in parent not nil, only check consistency # with the child - id(s) # if parent.values[lk] != child.pk_hash[rk] # error... # TODO # end else # we can set the FK value, thus creating the "link" parent.set(lk => child.pk_hash[rk]) end end end end |
.FunctionImport(name) ⇒ Object
8 9 10 |
# File 'lib/odata/function_import.rb', line 8 def self.FunctionImport(name) FunctionImport::Function.new(name) end |
.remove_nav_relation(assoc, parent) ⇒ Object
remove the relation between entity and parent by clearing the FK field(s) (if allowed)
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/odata/navigation_attribute.rb', line 10 def self.remove_nav_relation(assoc, parent) return unless assoc return unless assoc[:type] == :many_to_one # removes/clear the FK values in parent # thus deleting the "link" between the entity and the parent # Note: This is called if we have to delete the child--> can only be # done after removing the FK in parent (if allowed!) lks = [assoc[:key]].flatten lks.each do |lk| parent.set(lk => nil) parent.save(transaction: false) end end |
.with_error(result) {|err| ... } ⇒ Object
used in function import error handling. cf. func import / do_execute_func
60 61 62 63 64 |
# File 'lib/odata/error.rb', line 60 def self.with_error(result) return unless result.respond_to?(:error) && (err = result.error) yield err end |