frodo 0.10.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 (153) hide show
  1. checksums.yaml +7 -0
  2. data/.autotest +2 -0
  3. data/.circleci/config.yml +54 -0
  4. data/.gitignore +24 -0
  5. data/.gitlab-ci.yml +9 -0
  6. data/.rspec +2 -0
  7. data/.ruby-gemset +1 -0
  8. data/.ruby-version +1 -0
  9. data/.travis.yml +75 -0
  10. data/CHANGELOG.md +163 -0
  11. data/Gemfile +4 -0
  12. data/LICENSE.txt +23 -0
  13. data/README.md +479 -0
  14. data/Rakefile +7 -0
  15. data/TODO.md +55 -0
  16. data/frodo.gemspec +39 -0
  17. data/images/frodo.jpg +0 -0
  18. data/lib/frodo/abstract_client.rb +11 -0
  19. data/lib/frodo/client.rb +6 -0
  20. data/lib/frodo/concerns/api.rb +292 -0
  21. data/lib/frodo/concerns/authentication.rb +32 -0
  22. data/lib/frodo/concerns/base.rb +84 -0
  23. data/lib/frodo/concerns/caching.rb +26 -0
  24. data/lib/frodo/concerns/connection.rb +79 -0
  25. data/lib/frodo/concerns/verbs.rb +68 -0
  26. data/lib/frodo/config.rb +143 -0
  27. data/lib/frodo/entity.rb +335 -0
  28. data/lib/frodo/entity_container.rb +75 -0
  29. data/lib/frodo/entity_set.rb +131 -0
  30. data/lib/frodo/errors.rb +70 -0
  31. data/lib/frodo/middleware/authentication/token.rb +13 -0
  32. data/lib/frodo/middleware/authentication.rb +87 -0
  33. data/lib/frodo/middleware/authorization.rb +18 -0
  34. data/lib/frodo/middleware/caching.rb +30 -0
  35. data/lib/frodo/middleware/custom_headers.rb +14 -0
  36. data/lib/frodo/middleware/gzip.rb +33 -0
  37. data/lib/frodo/middleware/instance_url.rb +20 -0
  38. data/lib/frodo/middleware/logger.rb +42 -0
  39. data/lib/frodo/middleware/multipart.rb +64 -0
  40. data/lib/frodo/middleware/odata_headers.rb +13 -0
  41. data/lib/frodo/middleware/raise_error.rb +47 -0
  42. data/lib/frodo/middleware.rb +33 -0
  43. data/lib/frodo/navigation_property/proxy.rb +80 -0
  44. data/lib/frodo/navigation_property.rb +29 -0
  45. data/lib/frodo/properties/binary.rb +50 -0
  46. data/lib/frodo/properties/boolean.rb +37 -0
  47. data/lib/frodo/properties/collection.rb +50 -0
  48. data/lib/frodo/properties/complex.rb +114 -0
  49. data/lib/frodo/properties/date.rb +27 -0
  50. data/lib/frodo/properties/date_time.rb +83 -0
  51. data/lib/frodo/properties/date_time_offset.rb +17 -0
  52. data/lib/frodo/properties/decimal.rb +54 -0
  53. data/lib/frodo/properties/enum.rb +62 -0
  54. data/lib/frodo/properties/float.rb +67 -0
  55. data/lib/frodo/properties/geography/base.rb +162 -0
  56. data/lib/frodo/properties/geography/line_string.rb +33 -0
  57. data/lib/frodo/properties/geography/point.rb +31 -0
  58. data/lib/frodo/properties/geography/polygon.rb +38 -0
  59. data/lib/frodo/properties/geography.rb +13 -0
  60. data/lib/frodo/properties/guid.rb +17 -0
  61. data/lib/frodo/properties/integer.rb +107 -0
  62. data/lib/frodo/properties/number.rb +14 -0
  63. data/lib/frodo/properties/string.rb +72 -0
  64. data/lib/frodo/properties/time.rb +40 -0
  65. data/lib/frodo/properties/time_of_day.rb +27 -0
  66. data/lib/frodo/properties.rb +32 -0
  67. data/lib/frodo/property.rb +139 -0
  68. data/lib/frodo/property_registry.rb +41 -0
  69. data/lib/frodo/query/criteria/comparison_operators.rb +49 -0
  70. data/lib/frodo/query/criteria/date_functions.rb +61 -0
  71. data/lib/frodo/query/criteria/geography_functions.rb +21 -0
  72. data/lib/frodo/query/criteria/lambda_operators.rb +27 -0
  73. data/lib/frodo/query/criteria/string_functions.rb +40 -0
  74. data/lib/frodo/query/criteria.rb +92 -0
  75. data/lib/frodo/query/in_batches.rb +58 -0
  76. data/lib/frodo/query.rb +221 -0
  77. data/lib/frodo/railtie.rb +19 -0
  78. data/lib/frodo/schema/complex_type.rb +79 -0
  79. data/lib/frodo/schema/enum_type.rb +95 -0
  80. data/lib/frodo/schema.rb +164 -0
  81. data/lib/frodo/service.rb +199 -0
  82. data/lib/frodo/service_registry.rb +52 -0
  83. data/lib/frodo/version.rb +3 -0
  84. data/lib/frodo.rb +67 -0
  85. data/spec/fixtures/auth_success_response.json +11 -0
  86. data/spec/fixtures/error.json +11 -0
  87. data/spec/fixtures/files/entity_to_xml.xml +18 -0
  88. data/spec/fixtures/files/error.xml +5 -0
  89. data/spec/fixtures/files/metadata.xml +150 -0
  90. data/spec/fixtures/files/metadata_with_error.xml +157 -0
  91. data/spec/fixtures/files/product_0.json +10 -0
  92. data/spec/fixtures/files/product_0.xml +28 -0
  93. data/spec/fixtures/files/products.json +106 -0
  94. data/spec/fixtures/files/products.xml +308 -0
  95. data/spec/fixtures/files/supplier_0.json +26 -0
  96. data/spec/fixtures/files/supplier_0.xml +32 -0
  97. data/spec/fixtures/leads.json +923 -0
  98. data/spec/fixtures/refresh_error_response.json +8 -0
  99. data/spec/frodo/abstract_client_spec.rb +13 -0
  100. data/spec/frodo/client_spec.rb +57 -0
  101. data/spec/frodo/concerns/authentication_spec.rb +79 -0
  102. data/spec/frodo/concerns/base_spec.rb +68 -0
  103. data/spec/frodo/concerns/caching_spec.rb +40 -0
  104. data/spec/frodo/concerns/connection_spec.rb +65 -0
  105. data/spec/frodo/config_spec.rb +127 -0
  106. data/spec/frodo/entity/shared_examples.rb +83 -0
  107. data/spec/frodo/entity_container_spec.rb +38 -0
  108. data/spec/frodo/entity_set_spec.rb +169 -0
  109. data/spec/frodo/entity_spec.rb +153 -0
  110. data/spec/frodo/errors_spec.rb +48 -0
  111. data/spec/frodo/middleware/authentication/token_spec.rb +87 -0
  112. data/spec/frodo/middleware/authentication_spec.rb +83 -0
  113. data/spec/frodo/middleware/authorization_spec.rb +17 -0
  114. data/spec/frodo/middleware/custom_headers_spec.rb +21 -0
  115. data/spec/frodo/middleware/gzip_spec.rb +68 -0
  116. data/spec/frodo/middleware/instance_url_spec.rb +27 -0
  117. data/spec/frodo/middleware/logger_spec.rb +21 -0
  118. data/spec/frodo/middleware/odata_headers_spec.rb +15 -0
  119. data/spec/frodo/middleware/raise_error_spec.rb +66 -0
  120. data/spec/frodo/navigation_property/proxy_spec.rb +46 -0
  121. data/spec/frodo/navigation_property_spec.rb +55 -0
  122. data/spec/frodo/properties/binary_spec.rb +50 -0
  123. data/spec/frodo/properties/boolean_spec.rb +72 -0
  124. data/spec/frodo/properties/collection_spec.rb +44 -0
  125. data/spec/frodo/properties/date_spec.rb +23 -0
  126. data/spec/frodo/properties/date_time_offset_spec.rb +30 -0
  127. data/spec/frodo/properties/date_time_spec.rb +23 -0
  128. data/spec/frodo/properties/decimal_spec.rb +50 -0
  129. data/spec/frodo/properties/float_spec.rb +45 -0
  130. data/spec/frodo/properties/geography/line_string_spec.rb +33 -0
  131. data/spec/frodo/properties/geography/point_spec.rb +29 -0
  132. data/spec/frodo/properties/geography/polygon_spec.rb +55 -0
  133. data/spec/frodo/properties/geography/shared_examples.rb +72 -0
  134. data/spec/frodo/properties/guid_spec.rb +17 -0
  135. data/spec/frodo/properties/integer_spec.rb +58 -0
  136. data/spec/frodo/properties/string_spec.rb +46 -0
  137. data/spec/frodo/properties/time_of_day_spec.rb +23 -0
  138. data/spec/frodo/properties/time_spec.rb +15 -0
  139. data/spec/frodo/property_registry_spec.rb +16 -0
  140. data/spec/frodo/property_spec.rb +71 -0
  141. data/spec/frodo/query/criteria_spec.rb +229 -0
  142. data/spec/frodo/query_spec.rb +156 -0
  143. data/spec/frodo/schema/complex_type_spec.rb +97 -0
  144. data/spec/frodo/schema/enum_type_spec.rb +112 -0
  145. data/spec/frodo/schema_spec.rb +113 -0
  146. data/spec/frodo/service_registry_spec.rb +19 -0
  147. data/spec/frodo/service_spec.rb +153 -0
  148. data/spec/frodo/usage_example_spec.rb +161 -0
  149. data/spec/spec_helper.rb +35 -0
  150. data/spec/support/coverage.rb +2 -0
  151. data/spec/support/fixture_helpers.rb +14 -0
  152. data/spec/support/middleware.rb +19 -0
  153. metadata +479 -0
@@ -0,0 +1,164 @@
1
+ require 'frodo/schema/complex_type'
2
+ require 'frodo/schema/enum_type'
3
+
4
+ module Frodo
5
+ class Schema
6
+ # The schema's parent service
7
+ attr_reader :service
8
+ # The schema's metadata (i.e its XML definition)
9
+ attr_reader :metadata
10
+
11
+ # Creates a new schema.
12
+ #
13
+ # @param schema_definition [Nokogiri::XML] The schema's XML definition
14
+ # @param service [Frodo::Service] The schema's parent service
15
+ def initialize(schema_definition, service)
16
+ @metadata = schema_definition
17
+ @service = service
18
+ end
19
+
20
+ # Returns the schema's `Namespace` attribute (mandatory).
21
+ # @return [String]
22
+ def namespace
23
+ @namespace ||= metadata.attributes['Namespace'].value
24
+ end
25
+
26
+ # Returns a list of actions defined by the schema.
27
+ # @return [Array<String>]
28
+ def actions
29
+ @actions ||= metadata.xpath('//Action').map do |action|
30
+ action.attributes['Name'].value
31
+ end
32
+ end
33
+
34
+ # Returns a list of entities defined by the schema.
35
+ # @return [Array<String>]
36
+ def entity_types
37
+ @entity_types ||= metadata.xpath('//EntityType').map do |entity|
38
+ entity.attributes['Name'].value
39
+ end
40
+ end
41
+
42
+ # Returns a list of `ComplexType`s defined by the schema.
43
+ # @return [Hash<String, Frodo::Schema::ComplexType>]
44
+ def complex_types
45
+ @complex_types ||= metadata.xpath('//ComplexType').map do |entity|
46
+ [
47
+ entity.attributes['Name'].value,
48
+ ComplexType.new(entity, self)
49
+ ]
50
+ end.to_h
51
+ end
52
+
53
+ # Returns a list of EnumTypes defined by the schema.
54
+ # @return [Hash<String, Frodo::Schema::EnumType>]
55
+ def enum_types
56
+ @enum_types ||= metadata.xpath('//EnumType').map do |entity|
57
+ [
58
+ entity.attributes['Name'].value,
59
+ EnumType.new(entity, self)
60
+ ]
61
+ end.to_h
62
+ end
63
+
64
+ # Returns a list of functions defined by the schema.
65
+ # @return [Array<String>]
66
+ def functions
67
+ @functions ||= metadata.xpath('//Function').map do |function|
68
+ function.attributes['Name'].value
69
+ end
70
+ end
71
+
72
+ # Returns a list of type definitions defined by the schema.
73
+ # @return [Array<String>]
74
+ def type_definitions
75
+ @typedefs ||= metadata.xpath('//TypeDefinition').map do |typedef|
76
+ typedef.attributes['Name'].value
77
+ end
78
+ end
79
+
80
+ # Returns a hash for finding an association through an entity type's defined
81
+ # NavigationProperty elements.
82
+ # @return [Hash<Hash<Frodo::NavigationProperty>>]
83
+ def navigation_properties
84
+ @navigation_properties ||= metadata.xpath('//EntityType').map do |entity_type_def|
85
+ [
86
+ entity_type_def.attributes['Name'].value,
87
+ entity_type_def.xpath('./NavigationProperty').map do |nav_property_def|
88
+ [
89
+ nav_property_def.attributes['Name'].value,
90
+ ::Frodo::NavigationProperty.build(nav_property_def)
91
+ ]
92
+ end.to_h
93
+ ]
94
+ end.to_h
95
+ end
96
+
97
+ # Get the property type for an entity from metadata.
98
+ #
99
+ # @param entity_name [to_s] the name of the relevant entity
100
+ # @param property_name [to_s] the property name needed
101
+ # @return [String] the name of the property's type
102
+ def get_property_type(entity_name, property_name)
103
+ metadata.xpath("//EntityType[@Name='#{entity_name}']/Property[@Name='#{property_name}']").first.attributes['Type'].value
104
+ end
105
+
106
+ # Get the primary key for the supplied Entity.
107
+ #
108
+ # @param entity_name [to_s]
109
+ # @return [String]
110
+ def primary_key_for(entity_name)
111
+ metadata.xpath("//EntityType[@Name='#{entity_name}']/Key/PropertyRef").first.attributes['Name'].value
112
+ end
113
+
114
+ # Get the list of properties and their various options for the supplied
115
+ # Entity name.
116
+ # @param entity_name [to_s]
117
+ # @return [Hash]
118
+ # @api private
119
+ def properties_for_entity(entity_name)
120
+ type_definition = metadata.xpath("//EntityType[@Name='#{entity_name}']").first
121
+
122
+ raise ArgumentError, "Unknown EntityType: #{entity_name}" if type_definition.nil?
123
+ properties_to_return = {}
124
+
125
+ parent_properties = if base_type = type_definition.attributes['BaseType']
126
+ parent_type = base_type.value.split('.').last
127
+ properties_for_entity(parent_type)
128
+ else
129
+ {}
130
+ end
131
+
132
+ type_definition.xpath('./Property').each do |property_xml|
133
+ property_name, property = process_property_from_xml(property_xml)
134
+ properties_to_return[property_name] = property
135
+ end
136
+ parent_properties.merge!(properties_to_return)
137
+ end
138
+
139
+ private
140
+
141
+ def process_property_from_xml(property_xml)
142
+ property_name = property_xml.attributes['Name'].value
143
+ property_type = property_xml.attributes['Type'].value
144
+ property_options = { service: service }
145
+
146
+ property_type, value_type = property_type.split(/\(|\)/)
147
+ if property_type == 'Collection'
148
+ klass = ::Frodo::Properties::Collection
149
+ property_options.merge(value_type: value_type)
150
+ else
151
+ klass = ::Frodo::PropertyRegistry[property_type]
152
+ end
153
+
154
+ if klass.nil?
155
+ raise RuntimeError, "Unknown property type: #{property_type}"
156
+ else
157
+ property_options[:allows_nil] = false if property_xml.attributes['Nullable'] == 'false'
158
+ property = klass.new(property_name, nil, property_options)
159
+ end
160
+
161
+ return [property_name, property]
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,199 @@
1
+
2
+ module Frodo
3
+ # Encapsulates the basic details and functionality needed to interact with an
4
+ # Frodo service.
5
+ class Service
6
+ # The Frodo Service's URL
7
+ attr_reader :service_url
8
+ # Service options
9
+ attr_reader :options
10
+
11
+
12
+ # Opens the service based on the requested URL and adds the service to
13
+ # {Frodo::Registry}
14
+ #
15
+ # @param service_url [String]
16
+ # The URL to the Frodo service
17
+ # @param options [Hash] options to pass to the service
18
+ # @return [Frodo::Service] an instance of the service
19
+ def initialize(service_url, options = {}, &block)
20
+ @options = default_options.merge(options)
21
+ @service_url = service_url
22
+
23
+ Frodo::ServiceRegistry.add(self)
24
+ register_custom_types
25
+ end
26
+
27
+ # Returns user supplied name for service, or its URL
28
+ # @return [String]
29
+ def name
30
+ @name ||= options[:name] || service_url
31
+ end
32
+
33
+ # Returns the service's metadata URL.
34
+ # @return [String]
35
+ def metadata_url
36
+ "#{service_url}/$metadata"
37
+ end
38
+
39
+ # Returns the service's metadata definition.
40
+ # @return [Nokogiri::XML]
41
+ def metadata
42
+ @metadata ||= lambda { read_metadata }.call
43
+ end
44
+
45
+ # Returns all of the service's schemas.
46
+ # @return Hash<String, Frodo::Schema>
47
+ def schemas
48
+ @schemas ||= metadata.xpath('//Schema').map do |schema_xml|
49
+ [
50
+ schema_xml.attributes['Namespace'].value,
51
+ Schema.new(schema_xml, self)
52
+ ]
53
+ end.to_h
54
+ end
55
+
56
+ # Returns the service's EntityContainer (singleton)
57
+ # @return Frodo::EntityContainer
58
+ def entity_container
59
+ @entity_container ||= EntityContainer.new(self)
60
+ end
61
+
62
+ # Returns a hash of EntitySet names and their respective EntityType names
63
+ # @return Hash<String, String>
64
+ def entity_sets
65
+ entity_container.entity_sets
66
+ end
67
+
68
+ # Retrieves the EntitySet associated with a specific EntityType by name
69
+ #
70
+ # @param entity_set_name [to_s] the name of the EntitySet desired
71
+ # @return [Frodo::EntitySet] an Frodo::EntitySet to query
72
+ def [](entity_set_name)
73
+ entity_container[entity_set_name]
74
+ end
75
+
76
+ # Returns the default namespace, that is, the namespace of the schema
77
+ # that contains the service's EntityContainer.
78
+ # @return [String]
79
+ def namespace
80
+ entity_container.namespace
81
+ end
82
+
83
+ # Returns a list of `EntityType`s exposed by the service
84
+ # @return Array<String>
85
+ def entity_types
86
+ @entity_types ||= schemas.map do |namespace, schema|
87
+ schema.entity_types.map do |entity_type|
88
+ "#{namespace}.#{entity_type}"
89
+ end
90
+ end.flatten
91
+ end
92
+
93
+ # Returns a list of `ComplexType`s used by the service.
94
+ # @return [Hash<String, Frodo::Schema::ComplexType>]
95
+ def complex_types
96
+ @complex_types ||= schemas.map do |namespace, schema|
97
+ schema.complex_types.map do |name, complex_type|
98
+ [ "#{namespace}.#{name}", complex_type ]
99
+ end.to_h
100
+ end.reduce({}, :merge)
101
+ end
102
+
103
+ # Returns a list of `EnumType`s used by the service
104
+ # @return [Hash<String, Frodo::Schema::EnumType>]
105
+ def enum_types
106
+ @enum_types ||= schemas.map do |namespace, schema|
107
+ schema.enum_types.map do |name, enum_type|
108
+ [ "#{namespace}.#{name}", enum_type ]
109
+ end.to_h
110
+ end.reduce({}, :merge)
111
+ end
112
+
113
+ # Returns a more compact inspection of the service object
114
+ def inspect
115
+ "#<#{self.class.name}:#{self.object_id} name='#{name}' service_url='#{self.service_url}'>"
116
+ end
117
+
118
+ # Get the property type for an entity from metadata.
119
+ #
120
+ # @param entity_name [to_s] the fully qualified entity name
121
+ # @param property_name [to_s] the property name needed
122
+ # @return [String] the name of the property's type
123
+ def get_property_type(entity_name, property_name)
124
+ namespace, _, entity_name = entity_name.rpartition('.')
125
+ raise ArgumentError, 'Namespace missing' if namespace.nil? || namespace.empty?
126
+ schemas[namespace].get_property_type(entity_name, property_name)
127
+ end
128
+
129
+ # Get the primary key for the supplied Entity.
130
+ #
131
+ # @param entity_name [to_s] The fully qualified entity name
132
+ # @return [String]
133
+ def primary_key_for(entity_name)
134
+ namespace, _, entity_name = entity_name.rpartition('.')
135
+ raise ArgumentError, 'Namespace missing' if namespace.nil? || namespace.empty?
136
+ schemas[namespace].primary_key_for(entity_name)
137
+ end
138
+
139
+ # Get the list of properties and their various options for the supplied
140
+ # Entity name.
141
+ # @param entity_name [to_s]
142
+ # @return [Hash]
143
+ # @api private
144
+ def properties_for_entity(entity_name)
145
+ namespace, _, entity_name = entity_name.rpartition('.')
146
+ raise ArgumentError, 'Namespace missing' if namespace.nil? || namespace.empty?
147
+ schemas[namespace].properties_for_entity(entity_name)
148
+ end
149
+
150
+ # Returns the logger instance used by the service.
151
+ # When Ruby on Rails has been detected, the service will
152
+ # use `Rails.logger`. The log level will NOT be changed.
153
+ #
154
+ # When no Rails has been detected, a default logger will
155
+ # be used that logs to STDOUT with the log level supplied
156
+ # via options, or the default log level if none was given.
157
+ # @return [Logger]
158
+ def logger
159
+ @logger ||= options[:logger] || if defined?(Rails)
160
+ Rails.logger
161
+ else
162
+ default_logger
163
+ end
164
+ end
165
+
166
+ private
167
+
168
+ def default_options
169
+ {
170
+ strict: true # strict property validation
171
+ }
172
+ end
173
+
174
+ def default_logger
175
+ Frodo.configuration.logger if Frodo.log?
176
+ end
177
+
178
+ def read_metadata
179
+ # From file, good for debugging
180
+ if options[:metadata_file]
181
+ data = File.read(options[:metadata_file])
182
+ ::Nokogiri::XML(data).remove_namespaces!
183
+ elsif options[:metadata_document]
184
+ data = options[:metadata_document]
185
+ ::Nokogiri::XML(data).remove_namespaces!
186
+ end
187
+ end
188
+
189
+ def register_custom_types
190
+ complex_types.each do |name, type|
191
+ ::Frodo::PropertyRegistry.add(name, type.property_class)
192
+ end
193
+
194
+ enum_types.each do |name, type|
195
+ ::Frodo::PropertyRegistry.add(name, type.property_class)
196
+ end
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,52 @@
1
+ require 'singleton'
2
+
3
+ module Frodo
4
+ # Provides a registry for keeping track of multiple Frodo::Service instances
5
+ class ServiceRegistry
6
+ include Singleton
7
+
8
+ # Add a service to the Registry
9
+ #
10
+ # @param service [Frodo::Service] service to add to the registry
11
+ def add(service)
12
+ initialize_instance_variables
13
+ @services << service if service.is_a?(Frodo::Service) && !@services.include?(service)
14
+ @services_by_name[service.name] = @services.find_index(service)
15
+ @services_by_url[service.service_url] = @services.find_index(service)
16
+ end
17
+
18
+ # Lookup a service by URL or name
19
+ #
20
+ # @param lookup_key [String] the URL or name to lookup
21
+ # @return [Frodo::Service, nil] the Frodo::Service or nil
22
+ def [](lookup_key)
23
+ initialize_instance_variables
24
+ index = @services_by_name[lookup_key] || @services_by_url[lookup_key]
25
+ index.nil? ? nil : @services[index]
26
+ end
27
+
28
+ # (see #add)
29
+ def self.add(service)
30
+ Frodo::ServiceRegistry.instance.add(service)
31
+ end
32
+
33
+ # (see #[])
34
+ def self.[](lookup_key)
35
+ Frodo::ServiceRegistry.instance[lookup_key]
36
+ end
37
+
38
+ private
39
+
40
+ def initialize_instance_variables
41
+ @services ||= []
42
+ @services_by_name ||= {}
43
+ @services_by_url ||= {}
44
+ end
45
+
46
+ def flush
47
+ @services = []
48
+ @services_by_name = {}
49
+ @services_by_url = {}
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,3 @@
1
+ module Frodo
2
+ VERSION = '0.10.0'
3
+ end
data/lib/frodo.rb ADDED
@@ -0,0 +1,67 @@
1
+ require 'uri'
2
+ require 'date'
3
+ require 'time'
4
+ require 'bigdecimal'
5
+ require 'nokogiri'
6
+ require 'faraday'
7
+ require 'logger'
8
+ require 'andand'
9
+ require 'json'
10
+ require 'faraday_middleware'
11
+
12
+ require 'frodo/concerns/api'
13
+ require 'frodo/concerns/authentication'
14
+ require 'frodo/concerns/base'
15
+ require 'frodo/concerns/caching'
16
+ require 'frodo/concerns/connection'
17
+ require 'frodo/concerns/verbs'
18
+
19
+
20
+ require 'frodo/middleware'
21
+ require 'frodo/middleware/authentication'
22
+ require 'frodo/middleware/authentication/token'
23
+ require 'frodo/middleware/authorization'
24
+ require 'frodo/middleware/caching'
25
+ require 'frodo/middleware/custom_headers'
26
+ require 'frodo/middleware/gzip'
27
+ require 'frodo/middleware/instance_url'
28
+ require 'frodo/middleware/logger'
29
+ require 'frodo/middleware/odata_headers'
30
+ require 'frodo/middleware/raise_error'
31
+ require 'frodo/middleware/multipart'
32
+ require 'frodo/abstract_client'
33
+ require 'frodo/client'
34
+ require 'frodo/config'
35
+
36
+ require 'frodo/version'
37
+ require 'frodo/errors'
38
+ require 'frodo/property_registry'
39
+ require 'frodo/property'
40
+ require 'frodo/properties'
41
+ require 'frodo/navigation_property'
42
+ require 'frodo/entity'
43
+ require 'frodo/entity_container'
44
+ require 'frodo/entity_set'
45
+ require 'frodo/query'
46
+ require 'frodo/schema'
47
+ require 'frodo/service'
48
+ require 'frodo/service_registry'
49
+
50
+ require 'frodo/railtie' if defined?(::Rails)
51
+
52
+ # The Frodo gem provides a convenient way to interact with OData V4 services from
53
+ # Ruby. Please look to the {file:README.md README} for how to get started using
54
+ # the Frodo gem.
55
+ module Frodo
56
+ Error = Class.new(StandardError)
57
+ ServerError = Class.new(Error)
58
+ AuthenticationError = Class.new(Error)
59
+ UnauthorizedError = Class.new(Error)
60
+ APIVersionError = Class.new(Error)
61
+
62
+ class << self
63
+ def new(*args, &block)
64
+ Frodo::Client.new(*args, &block)
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,11 @@
1
+ {
2
+ "token_type": "Bearer",
3
+ "scope": "user_impersonation",
4
+ "expires_in": "3599",
5
+ "ext_expires_in": "3599",
6
+ "expires_on": "1552430212",
7
+ "not_before": "1552426312",
8
+ "resource": "https://emmanueltest.crm.dynamics.com",
9
+ "access_token": "gfEzf4azkWZMTjlay7usiSWhc0eOLNkKMw",
10
+ "refresh_token": "QswqIkdHSdbyvbDFuLwHNAoU1QgAA"
11
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "error": {
3
+ "code": "0x8006088a",
4
+ "message": "Resource not found for the segment 'leadsss'.",
5
+ "innererror": {
6
+ "message": "Resource not found for the segment 'leadsss'.",
7
+ "type": "Microsoft.OData.UriParser.ODataUnrecognizedPathException",
8
+ "stacktrace": " at Microsoft.OData.UriParser.ODataPathParser.CreateDynamicPathSegment(ODataPathSegment previous, String identifier, String parenthesisExpression)rn at Microsoft.OData.UriParser.ODataPathParser.CreateFirstSegment(String segmentText)rn at Microsoft.OData.UriParser.ODataPathParser.ParsePath(ICollection`1 segments)rn at Microsoft.OData.UriParser.ODataPathFactory.BindPath(ICollection`1 segments, ODataUriParserConfiguration configuration)rn at Microsoft.OData.UriParser.ODataUriParser.Initialize()rn at System.Web.OData.Routing.DefaultODataPathHandler.Parse(String serviceRoot, String odataPath, IServiceProvider requestContainer, Boolean template)rn at System.Web.OData.Routing.DefaultODataPathHandler.Parse(String serviceRoot, String odataPath, IServiceProvider requestContainer)rn at Microsoft.Crm.Extensibility.ODataV4.Routing.CrmODataPathHandler.Parse(String serviceRoot, String odataPath, IServiceProvider requestContainer)"
9
+ }
10
+ }
11
+ }
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0"?>
2
+ <entry xmlns="http://www.w3.org/2005/Atom" xmlns:data="http://docs.oasis-open.org/odata/ns/data" xmlns:metadata="http://docs.oasis-open.org/odata/ns/metadata" xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml" xml:base="http://services.odata.org/V4/OData/OData.svc">
3
+ <category term="ODataDemo.Product" scheme="http://docs.oasis-open.org/odata/ns/scheme"/>
4
+ <author>
5
+ <name/>
6
+ </author>
7
+ <content type="application/xml">
8
+ <metadata:properties>
9
+ <data:Name metadata:type="Edm.String">Bread</data:Name>
10
+ <data:Description metadata:type="Edm.String">Whole grain bread</data:Description>
11
+ <data:ReleaseDate metadata:type="Edm.DateTimeOffset">1992-01-01T00:00:00Z</data:ReleaseDate>
12
+ <data:DiscontinuedDate metadata:type="Edm.DateTimeOffset" metadata:null="true"/>
13
+ <data:Rating metadata:type="Edm.Int16">4</data:Rating>
14
+ <data:Price metadata:type="Edm.Double">2.5</data:Price>
15
+ <data:ProductStatus metadata:type="ODataDemo.ProductStatus" metadata:null="true"/>
16
+ </metadata:properties>
17
+ </content>
18
+ </entry>
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <m:error xmlns:m="http://docs.oasis-open.org/odata/ns/metadata">
3
+ <m:code />
4
+ <m:message>Resource not found for the segment 'Products'.</m:message>
5
+ </m:error>