odata4 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +90 -9
- data/lib/odata4.rb +2 -0
- data/lib/odata4/complex_type.rb +8 -5
- data/lib/odata4/entity.rb +16 -11
- data/lib/odata4/entity_container.rb +75 -0
- data/lib/odata4/entity_set.rb +0 -1
- data/lib/odata4/enum_type.rb +3 -3
- data/lib/odata4/enum_type/property.rb +1 -1
- data/lib/odata4/navigation_property/proxy.rb +5 -1
- data/lib/odata4/properties/binary.rb +2 -2
- data/lib/odata4/properties/boolean.rb +1 -1
- data/lib/odata4/properties/date_time.rb +1 -1
- data/lib/odata4/properties/decimal.rb +2 -2
- data/lib/odata4/properties/number.rb +2 -2
- data/lib/odata4/properties/string.rb +2 -2
- data/lib/odata4/properties/time.rb +1 -1
- data/lib/odata4/property.rb +29 -8
- data/lib/odata4/schema.rb +146 -0
- data/lib/odata4/service.rb +74 -98
- data/lib/odata4/version.rb +1 -1
- data/odata4.gemspec +11 -11
- data/spec/odata4/complex_type_spec.rb +1 -21
- data/spec/odata4/entity_container_spec.rb +38 -0
- data/spec/odata4/entity_set_spec.rb +2 -2
- data/spec/odata4/enum_type_spec.rb +17 -39
- data/spec/odata4/properties/decimal_spec.rb +37 -10
- data/spec/odata4/property_spec.rb +57 -18
- data/spec/odata4/query/result_spec.rb +1 -1
- data/spec/odata4/query_spec.rb +7 -4
- data/spec/odata4/schema_spec.rb +97 -0
- data/spec/odata4/service_spec.rb +87 -37
- data/spec/odata4/usage_example_spec.rb +22 -22
- metadata +30 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e28c4147df950462c72f8824c2868601941872c5
|
4
|
+
data.tar.gz: 8044f114aaa10c09719c3d3e5743f5f5c96de9d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c10b8c4859b7f2acdbf33d5258f12e43970d24061f558afac558be6212a955e4c5b5118720de78e74ae22231f7bf5479a137591082a0568aee13f5a325350788
|
7
|
+
data.tar.gz: 8d73fc1f5877df150a21a28ca10871582e58657f0419726fadb1d2c514c62d09517ff1f7eb2d1559bd49d6aea8fb50435e7280bedd60ed174a9528c26d926f05
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 0.8.0
|
4
|
+
|
5
|
+
* [New Feature] Support for multiple schemas
|
6
|
+
* [Breaking] `Service#complex_types`, `Service#entity_types`,
|
7
|
+
`Service#enum_types` and `Service#entity_sets` now return fully qualified
|
8
|
+
type names
|
9
|
+
* [New Feature] Optional lenient property validation
|
10
|
+
* [Fixed] Incorrect URL representation for Decimal properties
|
11
|
+
|
3
12
|
## 0.7.0
|
4
13
|
|
5
14
|
Major rewrite
|
data/README.md
CHANGED
@@ -18,7 +18,7 @@ If you need a gem to integration with OData Version 3, you can use James Thompso
|
|
18
18
|
|
19
19
|
Add this line to your application's `Gemfile`:
|
20
20
|
|
21
|
-
gem 'odata4'
|
21
|
+
gem 'odata4'
|
22
22
|
|
23
23
|
And then execute:
|
24
24
|
|
@@ -40,14 +40,14 @@ The nice thing about `OData4::Service` is that it automatically registers with t
|
|
40
40
|
To create an `OData4::Service` simply provide the location of a service endpoint to it like this:
|
41
41
|
|
42
42
|
```ruby
|
43
|
-
OData4::Service.open('http://services.odata.org/V4/OData/OData.
|
43
|
+
OData4::Service.open('http://services.odata.org/V4/OData/OData.svc')
|
44
44
|
```
|
45
45
|
|
46
46
|
You may also provide an options hash after the URL.
|
47
47
|
It is suggested that you supply a name for the service via this hash like so:
|
48
48
|
|
49
49
|
```ruby
|
50
|
-
OData4::Service.open('http://services.odata.org/V4/OData/OData.
|
50
|
+
OData4::Service.open('http://services.odata.org/V4/OData/OData.svc', name: 'ODataDemo')
|
51
51
|
```
|
52
52
|
|
53
53
|
This one call will setup the service and allow for the discovery of everything the other parts of the OData4 gem need to function.
|
@@ -57,7 +57,7 @@ Both of these methods are available on instances and will allow for lookup in th
|
|
57
57
|
Using either the service URL or the name provided as an option when creating an `OData4::Service` will allow for quick lookup in the `OData4::ServiceRegistry` like such:
|
58
58
|
|
59
59
|
```ruby
|
60
|
-
OData4::ServiceRegistry['http://services.odata.org/V4/OData/OData.
|
60
|
+
OData4::ServiceRegistry['http://services.odata.org/V4/OData/OData.svc']
|
61
61
|
OData4::ServiceRegistry['ODataDemo']
|
62
62
|
```
|
63
63
|
|
@@ -65,6 +65,61 @@ Both of the above calls would retrieve the same service from the registry.
|
|
65
65
|
At the moment there is no protection against name collisions provided in `OData4::ServiceRegistry`.
|
66
66
|
So, looking up services by their service URL is the most exact method, but lookup by name is provided for convenience.
|
67
67
|
|
68
|
+
### Exploring a Service
|
69
|
+
|
70
|
+
Once instantiated, you can request various information about the service, such as the names and types of entity sets it exposes, or the names of the entity types (and custom datatypes) it defines.
|
71
|
+
|
72
|
+
For example:
|
73
|
+
|
74
|
+
Get a list of available entity types
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
service.entity_types
|
78
|
+
# => [
|
79
|
+
# "ODataDemo.Product",
|
80
|
+
# "ODataDemo.FeaturedProduct",
|
81
|
+
# "ODataDemo.ProductDetail",
|
82
|
+
# "ODataDemo.Category",
|
83
|
+
# "ODataDemo.Supplier",
|
84
|
+
# "ODataDemo.Person",
|
85
|
+
# "ODataDemo.Customer",
|
86
|
+
# "ODataDemo.Employee",
|
87
|
+
# "ODataDemo.PersonDetail",
|
88
|
+
# "ODataDemo.Advertisement"
|
89
|
+
# ]
|
90
|
+
```
|
91
|
+
|
92
|
+
Get a list of entity sets
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
service.entity_sets
|
96
|
+
# => {
|
97
|
+
# "Products" => "ODataDemo.Product",
|
98
|
+
# "ProductDetails" => "ODataDemo.ProductDetail",
|
99
|
+
# "Categories" => "ODataDemo.Category",
|
100
|
+
# "Suppliers" => "ODataDemo.Supplier",
|
101
|
+
# "Persons" => "ODataDemo.Person",
|
102
|
+
# "PersonDetails" => "ODataDemo.PersonDetail",
|
103
|
+
# "Advertisements" => "ODataDemo.Advertisement"
|
104
|
+
# }
|
105
|
+
```
|
106
|
+
|
107
|
+
Get a list of complex types
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
service.complex_types
|
111
|
+
# => ["ODataDemo.Address"]
|
112
|
+
```
|
113
|
+
|
114
|
+
Get a list of enum types
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
service.enum_types
|
118
|
+
# => ["ODataDemo.ProductStatus"]
|
119
|
+
```
|
120
|
+
|
121
|
+
For more examples, refer to [usage_example_specs.rb](spec/odata4/usage_example_specs.rb).
|
122
|
+
|
68
123
|
### Authentication
|
69
124
|
|
70
125
|
When authenticating with your service you can set parameters to the Typhoeus gem which uses libcurl.
|
@@ -73,7 +128,7 @@ Use the **:typhoeus** option to set your authentication.
|
|
73
128
|
For example using **ntlm** authentication:
|
74
129
|
|
75
130
|
```ruby
|
76
|
-
conn = OData4::Service.open('http://services.odata.org/V4/OData/OData.
|
131
|
+
conn = OData4::Service.open('http://services.odata.org/V4/OData/OData.svc', {
|
77
132
|
name: 'ODataDemo',
|
78
133
|
typhoeus: {
|
79
134
|
username: 'username',
|
@@ -95,7 +150,7 @@ You can speed your load time by forcing the service to load the metadata from a
|
|
95
150
|
This is only recommended for testing purposes, as the metadata file can change.
|
96
151
|
|
97
152
|
```ruby
|
98
|
-
conn = OData4::Service.open('http://services.odata.org/V4/OData/OData.
|
153
|
+
conn = OData4::Service.open('http://services.odata.org/V4/OData/OData.svc', {
|
99
154
|
name: 'ODataDemo',
|
100
155
|
metadata_file: "metadata.xml",
|
101
156
|
})
|
@@ -106,7 +161,7 @@ This is only recommended for testing purposes, as the metadata file can change.
|
|
106
161
|
You can set the headers with the **:typhoeus** param like so:
|
107
162
|
|
108
163
|
```ruby
|
109
|
-
conn = OData4::Service.open('http://services.odata.org/V4/OData/OData.
|
164
|
+
conn = OData4::Service.open('http://services.odata.org/V4/OData/OData.svc', {
|
110
165
|
name: 'ODataDemo',
|
111
166
|
typhoeus: {
|
112
167
|
headers: {
|
@@ -123,7 +178,7 @@ Under normal circumstances you should never need to worry about an `OData4::Enti
|
|
123
178
|
For example, to get an `OData4::EntitySet` for the products in the ODataDemo service simply access the entity set through the service like this:
|
124
179
|
|
125
180
|
```ruby
|
126
|
-
service = OData4::Service.open('http://services.odata.org/V4/OData/OData.
|
181
|
+
service = OData4::Service.open('http://services.odata.org/V4/OData/OData.svc')
|
127
182
|
products = service['ProductsSet'] # => OData4::EntitySet
|
128
183
|
```
|
129
184
|
|
@@ -172,7 +227,7 @@ The first entity object returns a single entity object.
|
|
172
227
|
#### Find a certain Entity
|
173
228
|
|
174
229
|
```ruby
|
175
|
-
service['ProductsSet']['<
|
230
|
+
service['ProductsSet']['<primary key of entity>']
|
176
231
|
```
|
177
232
|
|
178
233
|
With certain navigation properties expanded (i.e. eagerly loaded):
|
@@ -239,6 +294,21 @@ or, you can get a hold of the property class instance using
|
|
239
294
|
|
240
295
|
This will parse and instantiate the property if it hasn't done so yet.
|
241
296
|
|
297
|
+
##### Lenient Property Validation
|
298
|
+
|
299
|
+
By default, we use strict property validation, meaning that any property validation errors in the data will raise an exception.
|
300
|
+
However, you may encounter OData implementations in the wild that break the specs in strange and surprising ways (shocking, I know!).
|
301
|
+
|
302
|
+
Since it's often better to get *some* data instead of nothing at all, you can optionally make the property validation lenient.
|
303
|
+
Simply add `strict: false` to the service constructor options.
|
304
|
+
In this mode, any property validation error will log a warning instead of raising an exception. The corresponding property value will be `nil` (even if the property is declared as not allowing NULL values).
|
305
|
+
|
306
|
+
```ruby
|
307
|
+
service = OData4::Service.open('http://services.odata.org/V4/OData/OData.svc', strict: false)
|
308
|
+
# -- alternatively, for an existing service instance --
|
309
|
+
service.options[:strict] = false
|
310
|
+
```
|
311
|
+
|
242
312
|
### Queries
|
243
313
|
|
244
314
|
`OData4::Query` instances form the base for finding specific entities within an `OData4::EntitySet`.
|
@@ -266,6 +336,17 @@ You should refer to the published RubyDocs for full details on the various capab
|
|
266
336
|
* [OData4::Query](http://rubydoc.info/github/wrstudios/odata4/master/OData4/Query)
|
267
337
|
* [OData4::Query::Criteria](http://rubydoc.info/github/wrstudios/odata4/master/OData4/Query/Criteria)
|
268
338
|
|
339
|
+
## To Do
|
340
|
+
|
341
|
+
[x] ~Lenient property validation~
|
342
|
+
[ ] Write support (create/update/delete)
|
343
|
+
[ ] Support for invoking [Operations][odata-ops] (Functions/Actions)
|
344
|
+
[ ] [Property facets][odata-facets]
|
345
|
+
[ ] Annotations
|
346
|
+
|
347
|
+
[odata-facets]: http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part3-csdl/odata-v4.0-errata03-os-part3-csdl-complete.html#_Toc453752528
|
348
|
+
[odata-ops]: http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Toc453752307
|
349
|
+
|
269
350
|
## Contributing
|
270
351
|
|
271
352
|
1. Fork it (`https://github.com/[my-github-username]/odata/fork`)
|
data/lib/odata4.rb
CHANGED
@@ -19,11 +19,13 @@ require 'odata4/navigation_property'
|
|
19
19
|
require 'odata4/complex_type'
|
20
20
|
require 'odata4/enum_type'
|
21
21
|
require 'odata4/entity'
|
22
|
+
require 'odata4/entity_container'
|
22
23
|
require 'odata4/entity_set'
|
23
24
|
require 'odata4/query/criteria'
|
24
25
|
require 'odata4/query/result'
|
25
26
|
require 'odata4/query/in_batches'
|
26
27
|
require 'odata4/query'
|
28
|
+
require 'odata4/schema'
|
27
29
|
require 'odata4/service'
|
28
30
|
require 'odata4/service_registry'
|
29
31
|
|
data/lib/odata4/complex_type.rb
CHANGED
@@ -9,10 +9,9 @@ module OData4
|
|
9
9
|
# Creates a new ComplexType based on the supplied options.
|
10
10
|
# @param type_xml [Nokogiri::XML::Element]
|
11
11
|
# @param service [OData4::Service]
|
12
|
-
|
13
|
-
def initialize(type_definition, service)
|
12
|
+
def initialize(type_definition, schema)
|
14
13
|
@type_definition = type_definition
|
15
|
-
@
|
14
|
+
@schema = schema
|
16
15
|
end
|
17
16
|
|
18
17
|
# The name of the ComplexType
|
@@ -58,8 +57,12 @@ module OData4
|
|
58
57
|
|
59
58
|
private
|
60
59
|
|
60
|
+
def schema
|
61
|
+
@schema
|
62
|
+
end
|
63
|
+
|
61
64
|
def service
|
62
|
-
@service
|
65
|
+
@schema.service
|
63
66
|
end
|
64
67
|
|
65
68
|
def type_definition
|
@@ -68,7 +71,7 @@ module OData4
|
|
68
71
|
|
69
72
|
def collect_properties
|
70
73
|
Hash[type_definition.xpath('./Property').map do |property_xml|
|
71
|
-
property_name, property =
|
74
|
+
property_name, property = schema.send(:process_property_from_xml, property_xml)
|
72
75
|
[property_name, property]
|
73
76
|
end]
|
74
77
|
end
|
data/lib/odata4/entity.rb
CHANGED
@@ -7,8 +7,6 @@ module OData4
|
|
7
7
|
class Entity
|
8
8
|
# The Entity type name
|
9
9
|
attr_reader :type
|
10
|
-
# The OData4::Service's namespace
|
11
|
-
attr_reader :namespace
|
12
10
|
# The OData4::Service's identifying name
|
13
11
|
attr_reader :service_name
|
14
12
|
# The entity set this entity belongs to
|
@@ -31,7 +29,6 @@ module OData4
|
|
31
29
|
def initialize(options = {})
|
32
30
|
@id = options[:id]
|
33
31
|
@type = options[:type]
|
34
|
-
@namespace = options[:namespace]
|
35
32
|
@service_name = options[:service_name]
|
36
33
|
@entity_set = options[:entity_set]
|
37
34
|
@context = options[:context]
|
@@ -39,10 +36,14 @@ module OData4
|
|
39
36
|
@errors = []
|
40
37
|
end
|
41
38
|
|
39
|
+
def namespace
|
40
|
+
@namespace ||= type.rpartition('.').first
|
41
|
+
end
|
42
|
+
|
42
43
|
# Returns name of Entity from Service specified type.
|
43
44
|
# @return [String]
|
44
45
|
def name
|
45
|
-
@name ||= type.
|
46
|
+
@name ||= type.split('.').last
|
46
47
|
end
|
47
48
|
|
48
49
|
# Returns context URL for this entity
|
@@ -110,7 +111,7 @@ module OData4
|
|
110
111
|
# Links to other OData4 entitites
|
111
112
|
# @return [Hash]
|
112
113
|
def links
|
113
|
-
@links ||=
|
114
|
+
@links ||= schema.navigation_properties[name].map do |nav_name, details|
|
114
115
|
[
|
115
116
|
nav_name,
|
116
117
|
{ type: details.nav_type, href: "#{id}/#{nav_name}" }
|
@@ -125,7 +126,7 @@ module OData4
|
|
125
126
|
def self.with_properties(new_properties = {}, options = {})
|
126
127
|
entity = OData4::Entity.new(options)
|
127
128
|
entity.instance_eval do
|
128
|
-
service.properties_for_entity(
|
129
|
+
service.properties_for_entity(type).each do |property_name, instance|
|
129
130
|
set_property(property_name, instance)
|
130
131
|
end
|
131
132
|
|
@@ -213,7 +214,7 @@ module OData4
|
|
213
214
|
# Returns the primary key for the Entity.
|
214
215
|
# @return [String]
|
215
216
|
def primary_key
|
216
|
-
|
217
|
+
schema.primary_key_for(name)
|
217
218
|
end
|
218
219
|
|
219
220
|
def is_new?
|
@@ -228,16 +229,20 @@ module OData4
|
|
228
229
|
@service ||= OData4::ServiceRegistry[service_name]
|
229
230
|
end
|
230
231
|
|
232
|
+
def schema
|
233
|
+
@schema ||= service.schemas[namespace]
|
234
|
+
end
|
235
|
+
|
231
236
|
private
|
232
237
|
|
233
238
|
def instantiate_property(property_name, value_xml)
|
234
|
-
value_type =
|
239
|
+
value_type = schema.get_property_type(name, property_name)
|
235
240
|
klass = ::OData4::PropertyRegistry[value_type]
|
236
241
|
|
237
242
|
if klass.nil?
|
238
243
|
raise RuntimeError, "Unknown property type: #{value_type}"
|
239
244
|
else
|
240
|
-
klass.from_xml(value_xml)
|
245
|
+
klass.from_xml(value_xml, service: service)
|
241
246
|
end
|
242
247
|
end
|
243
248
|
|
@@ -280,7 +285,7 @@ module OData4
|
|
280
285
|
def self.process_links(entity, xml_doc)
|
281
286
|
entity.instance_eval do
|
282
287
|
new_links = instance_variable_get(:@links) || {}
|
283
|
-
|
288
|
+
schema.navigation_properties[name].each do |nav_name, details|
|
284
289
|
xml_doc.xpath("./link[@title='#{nav_name}']").each do |node|
|
285
290
|
next if node.attributes['type'].nil?
|
286
291
|
next unless node.attributes['type'].value =~ /^application\/atom\+xml;type=(feed|entry)$/i
|
@@ -304,7 +309,7 @@ module OData4
|
|
304
309
|
def self.process_metadata(entity, metadata)
|
305
310
|
entity.instance_eval do
|
306
311
|
new_links = instance_variable_get(:@links) || {}
|
307
|
-
|
312
|
+
schema.navigation_properties[name].each do |nav_name, details|
|
308
313
|
href = metadata["#{nav_name}@odata.navigationLink"]
|
309
314
|
next if href.nil?
|
310
315
|
new_links[nav_name] = {
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module OData4
|
2
|
+
#
|
3
|
+
class EntityContainer
|
4
|
+
# The EntityContainer's parent service
|
5
|
+
attr_reader :service
|
6
|
+
# The EntityContainer's metadata
|
7
|
+
attr_reader :metadata
|
8
|
+
|
9
|
+
# Creates a new EntityContainer
|
10
|
+
# @param service [OData4::Service] The entity container's parent service
|
11
|
+
def initialize(service)
|
12
|
+
@metadata = service.metadata.xpath('//EntityContainer').first
|
13
|
+
@service = service
|
14
|
+
end
|
15
|
+
|
16
|
+
# The EntityContainer's surrounding Schema
|
17
|
+
# @return [Nokogiri::XML]
|
18
|
+
def schema
|
19
|
+
@schema ||= metadata.ancestors('Schema').first
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns the EntityContainer's namespace.
|
23
|
+
# @return [String]
|
24
|
+
def namespace
|
25
|
+
@namespace ||= schema.attributes['Namespace'].value
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns the EntityContainer's name.
|
29
|
+
# @return [String]
|
30
|
+
def name
|
31
|
+
@name ||= metadata.attributes['Name'].value
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns a hash of EntitySet names and their respective EntityTypes.
|
35
|
+
# @return [Hash<String, String>]
|
36
|
+
def entity_sets
|
37
|
+
@entity_sets ||= metadata.xpath('//EntitySet').map do |entity|
|
38
|
+
[
|
39
|
+
entity.attributes['Name'].value,
|
40
|
+
entity.attributes['EntityType'].value
|
41
|
+
]
|
42
|
+
end.to_h
|
43
|
+
end
|
44
|
+
|
45
|
+
# Retrieves the EntitySet associated with a specific EntityType by name
|
46
|
+
#
|
47
|
+
# @param entity_set_name [to_s] the name of the EntitySet desired
|
48
|
+
# @return [OData4::EntitySet] an OData4::EntitySet to query
|
49
|
+
def [](entity_set_name)
|
50
|
+
xpath_query = "//EntitySet[@Name='#{entity_set_name}']"
|
51
|
+
entity_set_node = metadata.xpath(xpath_query).first
|
52
|
+
raise ArgumentError, "Unknown Entity Set: #{entity_set_name}" if entity_set_node.nil?
|
53
|
+
entity_type = entity_set_node.attributes['EntityType'].value
|
54
|
+
OData4::EntitySet.new(
|
55
|
+
name: entity_set_name,
|
56
|
+
namespace: namespace,
|
57
|
+
type: entity_type,
|
58
|
+
service_name: service.name,
|
59
|
+
container: name
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
def singletons
|
64
|
+
# TODO return singletons exposed by this EntityContainer
|
65
|
+
end
|
66
|
+
|
67
|
+
def actions
|
68
|
+
# TODO return action imports exposed by this EntityContainer
|
69
|
+
end
|
70
|
+
|
71
|
+
def functions
|
72
|
+
# TODO return function imports exposed by this EntityContainer
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/odata4/entity_set.rb
CHANGED
data/lib/odata4/enum_type.rb
CHANGED
@@ -8,9 +8,9 @@ module OData4
|
|
8
8
|
# @param type_xml [Nokogiri::XML::Element]
|
9
9
|
# @param service [OData4::Service]
|
10
10
|
# @return [self]
|
11
|
-
def initialize(type_definition,
|
11
|
+
def initialize(type_definition, schema)
|
12
12
|
@type_definition = type_definition
|
13
|
-
@
|
13
|
+
@schema = schema
|
14
14
|
end
|
15
15
|
|
16
16
|
# The name of the EnumType
|
@@ -71,7 +71,7 @@ module OData4
|
|
71
71
|
private
|
72
72
|
|
73
73
|
def service
|
74
|
-
@service
|
74
|
+
@schema.service
|
75
75
|
end
|
76
76
|
|
77
77
|
def type_definition
|