ruby_odata 0.1.4 → 0.1.5
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.
- data/.travis.yml +2 -2
- data/CHANGELOG.md +8 -0
- data/features/error_handling.feature +1 -2
- data/lib/ruby_odata/class_builder.rb +11 -7
- data/lib/ruby_odata/exceptions.rb +7 -0
- data/lib/ruby_odata/property_metadata.rb +2 -0
- data/lib/ruby_odata/query_builder.rb +27 -0
- data/lib/ruby_odata/service.rb +59 -7
- data/lib/ruby_odata/version.rb +1 -1
- data/spec/fixtures/int64_ids/edmx_boat_service.xml +19 -0
- data/spec/fixtures/int64_ids/edmx_car_service.xml +21 -0
- data/spec/fixtures/int64_ids/result_boats.xml +26 -0
- data/spec/fixtures/int64_ids/result_cars.xml +28 -0
- data/spec/fixtures/sample_service/result_select_categories_expand.xml +268 -0
- data/spec/fixtures/sample_service/result_select_categories_no_property.xml +6 -0
- data/spec/fixtures/sample_service/result_select_categories_travsing_no_expand.xml +6 -0
- data/spec/fixtures/sample_service/result_select_products_name_price.xml +92 -0
- data/spec/property_metadata_spec.rb +8 -8
- data/spec/query_builder_spec.rb +60 -2
- data/spec/revised_service_spec.rb +95 -6
- data/spec/service_spec.rb +80 -3
- metadata +245 -218
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -136,3 +136,11 @@
|
|
136
136
|
* Updated the [VCR](https://github.com/myronmarston/vcr) and [WebMock](https://github.com/bblimke/webmock) gems to the latest versions (used for testing)
|
137
137
|
* Specified activesupport ~> 3.0 (in gemfiles/ruby187) for Ruby 1.8.7 as activesupport 4 doesn't support Ruby < 1.9.3
|
138
138
|
|
139
|
+
## 0.1.5
|
140
|
+
* **BREAKING CHANGES**
|
141
|
+
* Previously if the OData service threw an exception, ruby_odata threw a generic error with the message that would start with "HTTP Error XXX: ". Instead of the message, the Error that is thrown is an `OData::ServiceError`. It has an `http_code` property on it, thus, the message is now just the text from the OData error without the "HTTP Error XXX: " prefix. This could potentially cause you problems if you were sniffing error messages for the HTTP error code.
|
142
|
+
|
143
|
+
* New Features
|
144
|
+
* Added the ability to query the OData service using the [$select system query option](http://www.odata.org/documentation/odata-v2-documentation/uri-conventions/#48_Select_System_Query_Option_select)
|
145
|
+
* Support for Int64 keys ([issue 39](https://github.com/visoft/ruby_odata/issues/39) and [issue 40](https://github.com/visoft/ruby_odata/pull/40), thanks [@nasali](https://github.com/nasali))
|
146
|
+
* New property `is_key` added to `PropertyMetadata` in order to determine the key properties for the class (found in the service's `class_metadata` collection)
|
@@ -10,5 +10,4 @@ Background:
|
|
10
10
|
|
11
11
|
Scenario: Violate a data type conversion (empty string to decimal)
|
12
12
|
Given I call "AddToProducts" on the service with a new "Product" object with Price: ""
|
13
|
-
When I save changes it should throw an exception with message containing "
|
14
|
-
|
13
|
+
When I save changes it should throw an exception with message containing "Error encountered in converting the value"
|
@@ -76,7 +76,7 @@ module OData
|
|
76
76
|
end
|
77
77
|
end
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
def add_methods(klass)
|
81
81
|
# Add metadata methods
|
82
82
|
klass.send :define_method, :__metadata do
|
@@ -158,20 +158,20 @@ module OData
|
|
158
158
|
instance_variable_set("@#{method_name}", value)
|
159
159
|
end
|
160
160
|
end
|
161
|
-
|
161
|
+
|
162
162
|
# Add an id method pulling out the id from the uri (mainly for Pickle support)
|
163
163
|
klass.send :define_method, :id do
|
164
164
|
metadata = self.__metadata
|
165
165
|
id = nil
|
166
|
-
if metadata && metadata[:uri] =~ /\((\d+)
|
166
|
+
if metadata && metadata[:uri] =~ /\((\d+)L?\)$/
|
167
167
|
id = $~[1]
|
168
168
|
end
|
169
169
|
return (true if Integer(id) rescue false) ? id.to_i : id
|
170
170
|
end
|
171
|
-
|
171
|
+
|
172
172
|
# Override equals
|
173
173
|
klass.send :define_method, :== do |other|
|
174
|
-
self.class == other.class &&
|
174
|
+
self.class == other.class &&
|
175
175
|
self.id == other.id &&
|
176
176
|
self.__metadata == other.__metadata
|
177
177
|
end
|
@@ -195,14 +195,18 @@ module OData
|
|
195
195
|
klass.send :define_singleton_method, 'properties' do
|
196
196
|
context.class_metadata[klass.to_s] || {}
|
197
197
|
end
|
198
|
-
|
198
|
+
|
199
199
|
# Finds a single model by ID
|
200
200
|
klass.send :define_singleton_method, 'first' do |id|
|
201
201
|
return nil if id.nil?
|
202
202
|
# TODO: Instead of just pluralizing the klass name, use the actual collection name
|
203
203
|
collection = klass.to_s.pluralize
|
204
204
|
context.send "#{collection}", id
|
205
|
-
|
205
|
+
begin
|
206
|
+
results = context.execute
|
207
|
+
rescue OData::ServiceError => e
|
208
|
+
return nil
|
209
|
+
end
|
206
210
|
results.count == 0 ? nil : results.first
|
207
211
|
end
|
208
212
|
end
|
@@ -1,4 +1,11 @@
|
|
1
1
|
module OData
|
2
2
|
# Raised when a user attempts to do something that is not supported
|
3
3
|
class NotSupportedError < StandardError; end
|
4
|
+
# Raised when the service returns an error
|
5
|
+
class ServiceError < StandardError
|
6
|
+
attr_reader :http_code
|
7
|
+
def initialize(code)
|
8
|
+
@http_code = code
|
9
|
+
end
|
10
|
+
end
|
4
11
|
end
|
@@ -15,6 +15,8 @@ module OData
|
|
15
15
|
attr_reader :nav_prop
|
16
16
|
# Applies only to navigation properties; the association corresponding to the property
|
17
17
|
attr_accessor :association
|
18
|
+
# Applies to the primary key(s)
|
19
|
+
attr_accessor :is_key
|
18
20
|
|
19
21
|
# Creates a new instance of the Class Property class
|
20
22
|
#
|
@@ -18,6 +18,7 @@ class QueryBuilder
|
|
18
18
|
@filters = []
|
19
19
|
@order_bys = []
|
20
20
|
@navigation_paths = []
|
21
|
+
@select = []
|
21
22
|
@skip = nil
|
22
23
|
@top = nil
|
23
24
|
@count = nil
|
@@ -102,6 +103,7 @@ class QueryBuilder
|
|
102
103
|
# product_links = svc.execute # => returns URIs for the products under the Category with an ID of 1
|
103
104
|
def links(navigation_property)
|
104
105
|
raise OData::NotSupportedError.new("You cannot call both the `links` method and the `count` method in the same query.") if @count
|
106
|
+
raise OData::NotSupportedError.new("You cannot call both the `links` method and the `select` method in the same query.") unless @select.empty?
|
105
107
|
@links_navigation_property = navigation_property
|
106
108
|
self
|
107
109
|
end
|
@@ -116,6 +118,8 @@ class QueryBuilder
|
|
116
118
|
# product_count = svc.execute
|
117
119
|
def count
|
118
120
|
raise OData::NotSupportedError.new("You cannot call both the `links` method and the `count` method in the same query.") if @links_navigation_property
|
121
|
+
raise OData::NotSupportedError.new("You cannot call both the `select` method and the `count` method in the same query.") unless @select.empty?
|
122
|
+
|
119
123
|
@count = true
|
120
124
|
self
|
121
125
|
end
|
@@ -131,6 +135,28 @@ class QueryBuilder
|
|
131
135
|
self
|
132
136
|
end
|
133
137
|
|
138
|
+
# Used to customize the properties that are returned for "ad-hoc" queries
|
139
|
+
#
|
140
|
+
# @param [Array<String>] properties to return
|
141
|
+
#
|
142
|
+
# @example
|
143
|
+
# svc.Products.select('Price', 'Rating')
|
144
|
+
def select(*fields)
|
145
|
+
raise OData::NotSupportedError.new("You cannot call both the `links` method and the `select` method in the same query.") if @links_navigation_property
|
146
|
+
raise OData::NotSupportedError.new("You cannot call both the `count` method and the `select` method in the same query.") if @count
|
147
|
+
|
148
|
+
@select |= fields
|
149
|
+
|
150
|
+
expands = fields.find_all { |f| /\// =~ f }
|
151
|
+
expands.each do |e|
|
152
|
+
parts = e.split '/'
|
153
|
+
@expands |= [parts[0...-1].join('/')]
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
self
|
158
|
+
end
|
159
|
+
|
134
160
|
# Builds the query URI (path, not including root) incorporating expands, filters, etc.
|
135
161
|
# This is used internally when the execute method is called on the service
|
136
162
|
def query
|
@@ -150,6 +176,7 @@ class QueryBuilder
|
|
150
176
|
end
|
151
177
|
|
152
178
|
query_options = []
|
179
|
+
query_options << "$select=#{@select.join(',')}" unless @select.empty?
|
153
180
|
query_options << "$expand=#{@expands.join(',')}" unless @expands.empty?
|
154
181
|
query_options << "$filter=#{@filters.join('+and+')}" unless @filters.empty?
|
155
182
|
query_options << "$orderby=#{@order_bys.join(',')}" unless @order_bys.empty?
|
data/lib/ruby_odata/service.rb
CHANGED
@@ -24,9 +24,7 @@ class Service
|
|
24
24
|
def method_missing(name, *args)
|
25
25
|
# Queries
|
26
26
|
if @collections.include?(name.to_s)
|
27
|
-
|
28
|
-
root << "(#{args.join(',')})" unless args.empty?
|
29
|
-
@query = QueryBuilder.new(root, @additional_params)
|
27
|
+
@query = build_collection_query_object(name,@additional_params, *args)
|
30
28
|
return @query
|
31
29
|
# Adds
|
32
30
|
elsif name.to_s =~ /^AddTo(.*)/
|
@@ -96,8 +94,13 @@ class Service
|
|
96
94
|
|
97
95
|
# Performs query operations (Read) against the server.
|
98
96
|
# Typically this returns an array of record instances, except in the case of count queries
|
97
|
+
# @raise [ServiceError] if there is an error when talking to the service
|
99
98
|
def execute
|
100
|
-
|
99
|
+
begin
|
100
|
+
@response = RestClient::Resource.new(build_query_uri, @rest_options).get
|
101
|
+
rescue Exception => e
|
102
|
+
handle_exception(e)
|
103
|
+
end
|
101
104
|
return Integer(@response) if @response =~ /^\d+$/
|
102
105
|
handle_collection_result(@response)
|
103
106
|
end
|
@@ -167,6 +170,51 @@ class Service
|
|
167
170
|
|
168
171
|
private
|
169
172
|
|
173
|
+
# Constructs a QueryBuilder instance for a collection using the arguments provided.
|
174
|
+
#
|
175
|
+
# @param [String] name the name of the collection
|
176
|
+
# @param [Hash] additional_parameters the additional parameters
|
177
|
+
# @param [Array] args the arguments to use for query
|
178
|
+
def build_collection_query_object(name, additional_parameters, *args)
|
179
|
+
root = "/#{name.to_s}"
|
180
|
+
if args.empty?
|
181
|
+
#nothing to add
|
182
|
+
elsif args.size == 1
|
183
|
+
if args.first.to_s =~ /\d+/
|
184
|
+
id_metadata = find_id_metadata(name.to_s)
|
185
|
+
root << build_id_path(args.first, id_metadata)
|
186
|
+
else
|
187
|
+
root << "(#{args.first})"
|
188
|
+
end
|
189
|
+
else
|
190
|
+
root << "(#{args.join(',')})"
|
191
|
+
end
|
192
|
+
QueryBuilder.new(root, additional_parameters)
|
193
|
+
end
|
194
|
+
|
195
|
+
# Finds the metadata associated with the given collection's first id property
|
196
|
+
# Remarks: This is used for single item lookup queries using the ID, e.g. Products(1), not complex primary keys
|
197
|
+
#
|
198
|
+
# @param [String] collection_name the name of the collection
|
199
|
+
def find_id_metadata(collection_name)
|
200
|
+
collection_data = @collections.fetch(collection_name)
|
201
|
+
class_metadata = @class_metadata.fetch(collection_data[:type].to_s)
|
202
|
+
key = class_metadata.select{|k,h| h.is_key }.collect{|k,h| h.name }[0]
|
203
|
+
class_metadata[key]
|
204
|
+
end
|
205
|
+
|
206
|
+
# Builds the ID expression of a given id for query
|
207
|
+
#
|
208
|
+
# @param [Object] id_value the actual value to be used
|
209
|
+
# @param [PropertyMetadata] id_metadata the property metadata object for the id
|
210
|
+
def build_id_path(id_value, id_metadata)
|
211
|
+
if id_metadata.type == "Edm.Int64"
|
212
|
+
"(#{id_value}L)"
|
213
|
+
else
|
214
|
+
"(#{id_value})"
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
170
218
|
def set_options!(options)
|
171
219
|
@options = options
|
172
220
|
if @options[:eager_partial].nil?
|
@@ -291,10 +339,12 @@ class Service
|
|
291
339
|
end
|
292
340
|
|
293
341
|
# Builds the metadata need for each property for things like feed customizations and navigation properties
|
294
|
-
def build_property_metadata(props)
|
342
|
+
def build_property_metadata(props, keys=[])
|
295
343
|
metadata = {}
|
296
344
|
props.each do |property_element|
|
297
345
|
prop_meta = PropertyMetadata.new(property_element)
|
346
|
+
prop_meta.is_key = keys.include?(prop_meta.name)
|
347
|
+
|
298
348
|
# If this is a navigation property, we need to add the association to the property metadata
|
299
349
|
prop_meta.association = Association.new(property_element, @edmx) if prop_meta.nav_prop
|
300
350
|
metadata[prop_meta.name] = prop_meta
|
@@ -319,13 +369,15 @@ class Service
|
|
319
369
|
error = Nokogiri::XML(e.response)
|
320
370
|
|
321
371
|
message = error.xpath("m:error/m:message", @ds_namespaces).first.content
|
322
|
-
raise
|
372
|
+
raise ServiceError.new(code), message
|
323
373
|
end
|
324
374
|
|
325
375
|
# Loops through the standard properties (non-navigation) for a given class and returns the appropriate list of methods
|
326
376
|
def collect_properties(klass_name, element, doc)
|
327
377
|
props = element.xpath(".//edm:Property", @ds_namespaces)
|
328
|
-
|
378
|
+
key_elemnts = element.xpath(".//edm:Key//edm:PropertyRef", @ds_namespaces)
|
379
|
+
keys = key_elemnts.collect { |k| k['Name'] }
|
380
|
+
@class_metadata[klass_name] = build_property_metadata(props, keys)
|
329
381
|
methods = props.collect { |p| p['Name'] }
|
330
382
|
unless element["BaseType"].nil?
|
331
383
|
base = element["BaseType"].split(".").last()
|
data/lib/ruby_odata/version.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
|
3
|
+
<edmx:DataServices m:DataServiceVersion="1.0" m:MaxDataServiceVersion="2.0" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
|
4
|
+
<Schema Namespace="Model" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
|
5
|
+
<EntityType Name="Boat">
|
6
|
+
<Key>
|
7
|
+
<PropertyRef Name="KeyId" />
|
8
|
+
</Key>
|
9
|
+
<Property Name="KeyId" Type="Edm.Int64" Nullable="false" p6:StoreGeneratedPattern="Identity" xmlns:p6="http://schemas.microsoft.com/ado/2009/02/edm/annotation" />
|
10
|
+
<Property Name="color" Type="Edm.String" Nullable="false" MaxLength="50" FixedLength="false" Unicode="false" />
|
11
|
+
</EntityType>
|
12
|
+
</Schema>
|
13
|
+
<Schema Namespace="WebApp" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
|
14
|
+
<EntityContainer Name="adoEntities" m:IsDefaultEntityContainer="true" p6:LazyLoadingEnabled="true" xmlns:p6="http://schemas.microsoft.com/ado/2009/02/edm/annotation">
|
15
|
+
<EntitySet Name="Boats" EntityType="Model.Boat" />
|
16
|
+
</EntityContainer>
|
17
|
+
</Schema>
|
18
|
+
</edmx:DataServices>
|
19
|
+
</edmx:Edmx>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
|
3
|
+
<edmx:DataServices m:DataServiceVersion="1.0" m:MaxDataServiceVersion="2.0" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
|
4
|
+
<Schema Namespace="Model" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
|
5
|
+
<EntityType Name="Car">
|
6
|
+
<Key>
|
7
|
+
<PropertyRef Name="id" />
|
8
|
+
</Key>
|
9
|
+
<Property Name="id" Type="Edm.Int64" Nullable="false" p6:StoreGeneratedPattern="Identity" xmlns:p6="http://schemas.microsoft.com/ado/2009/02/edm/annotation" />
|
10
|
+
<Property Name="color" Type="Edm.String" Nullable="false" MaxLength="50" FixedLength="false" Unicode="false" />
|
11
|
+
<Property Name="num_spots" Type="Edm.Int32" />
|
12
|
+
<Property Name="striped" Type="Edm.Byte" />
|
13
|
+
</EntityType>
|
14
|
+
</Schema>
|
15
|
+
<Schema Namespace="WebApp" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
|
16
|
+
<EntityContainer Name="adoEntities" m:IsDefaultEntityContainer="true" p6:LazyLoadingEnabled="true" xmlns:p6="http://schemas.microsoft.com/ado/2009/02/edm/annotation">
|
17
|
+
<EntitySet Name="Cars" EntityType="Model.Car" />
|
18
|
+
</EntityContainer>
|
19
|
+
</Schema>
|
20
|
+
</edmx:DataServices>
|
21
|
+
</edmx:Edmx>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<feed xml:base="http://test.com/test.svc/"
|
3
|
+
xmlns="http://www.w3.org/2005/Atom"
|
4
|
+
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
|
5
|
+
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
|
6
|
+
<id>http://test.com/test.svc/Boats</id>
|
7
|
+
<title type="text">Boats</title>
|
8
|
+
<updated>2013-10-28T19:59:15Z</updated>
|
9
|
+
<link rel="self" title="Boats" href="Boats" />
|
10
|
+
<entry>
|
11
|
+
<id>http://test.com/test.svc/Boats(213L)</id>
|
12
|
+
<category term="Model.Boat" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
13
|
+
<link rel="edit" title="Boat" href="Boats(213L)" />
|
14
|
+
<title />
|
15
|
+
<updated>2013-10-28T19:59:15Z</updated>
|
16
|
+
<author>
|
17
|
+
<name />
|
18
|
+
</author>
|
19
|
+
<content type="application/xml">
|
20
|
+
<m:properties>
|
21
|
+
<d:KeyId m:type="Edm.Int64">213</d:KeyId>
|
22
|
+
<d:color>blue</d:color>
|
23
|
+
</m:properties>
|
24
|
+
</content>
|
25
|
+
</entry>
|
26
|
+
</feed>
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<feed xml:base="http://test.com/test.svc/"
|
3
|
+
xmlns="http://www.w3.org/2005/Atom"
|
4
|
+
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
|
5
|
+
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
|
6
|
+
<id>http://test.com/test.svc/Cars</id>
|
7
|
+
<title type="text">Cars</title>
|
8
|
+
<updated>2013-10-28T19:59:15Z</updated>
|
9
|
+
<link rel="self" title="Cars" href="Cars" />
|
10
|
+
<entry>
|
11
|
+
<id>http://test.com/test.svc/Cars(213L)</id>
|
12
|
+
<category term="Model.Car" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
13
|
+
<link rel="edit" title="Car" href="Cars(213L)" />
|
14
|
+
<title />
|
15
|
+
<updated>2013-10-28T19:59:15Z</updated>
|
16
|
+
<author>
|
17
|
+
<name />
|
18
|
+
</author>
|
19
|
+
<content type="application/xml">
|
20
|
+
<m:properties>
|
21
|
+
<d:id m:type="Edm.Int64">213</d:id>
|
22
|
+
<d:color>peach</d:color>
|
23
|
+
<d:num_spots m:type="Edm.Int32" m:null="true" />
|
24
|
+
<d:striped m:type="Edm.Byte" m:null="true" />
|
25
|
+
</m:properties>
|
26
|
+
</content>
|
27
|
+
</entry>
|
28
|
+
</feed>
|
@@ -0,0 +1,268 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<feed xml:base="http://win7dev:8989/SampleService/RubyOData.svc/"
|
3
|
+
xmlns="http://www.w3.org/2005/Atom"
|
4
|
+
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
|
5
|
+
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
|
6
|
+
xmlns:georss="http://www.georss.org/georss"
|
7
|
+
xmlns:gml="http://www.opengis.net/gml">
|
8
|
+
<id>http://win7dev:8989/SampleService/RubyOdata.svc/Categories</id>
|
9
|
+
<title type="text">Categories</title>
|
10
|
+
<updated>2013-07-22T14:54:47Z</updated>
|
11
|
+
<link rel="self" title="Categories" href="Categories" />
|
12
|
+
<entry>
|
13
|
+
<id>http://win7dev:8989/SampleService/RubyOData.svc/Categories(1)</id>
|
14
|
+
<category term="RubyODataService.Category" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
15
|
+
<link rel="edit" title="Category" href="Categories(1)" />
|
16
|
+
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Products" type="application/atom+xml;type=feed" title="Products" href="Categories(1)/Products">
|
17
|
+
<m:inline>
|
18
|
+
<feed>
|
19
|
+
<id>http://win7dev:8989/SampleService/RubyOData.svc/Categories(1)/Products</id>
|
20
|
+
<title type="text">Products</title>
|
21
|
+
<updated>2013-07-22T14:54:47Z</updated>
|
22
|
+
<link rel="self" title="Products" href="Categories(1)/Products" />
|
23
|
+
<entry>
|
24
|
+
<id>http://win7dev:8989/SampleService/RubyOData.svc/Products(1)</id>
|
25
|
+
<category term="RubyODataService.Product" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
26
|
+
<link rel="edit" title="Product" href="Products(1)" />
|
27
|
+
<title />
|
28
|
+
<updated>2013-07-22T14:54:47Z</updated>
|
29
|
+
<author>
|
30
|
+
<name />
|
31
|
+
</author>
|
32
|
+
<content type="application/xml">
|
33
|
+
<m:properties>
|
34
|
+
<d:Name>Widget 0001</d:Name>
|
35
|
+
</m:properties>
|
36
|
+
</content>
|
37
|
+
</entry>
|
38
|
+
</feed>
|
39
|
+
</m:inline>
|
40
|
+
</link>
|
41
|
+
<title />
|
42
|
+
<updated>2013-07-22T14:54:47Z</updated>
|
43
|
+
<author>
|
44
|
+
<name />
|
45
|
+
</author>
|
46
|
+
<content type="application/xml">
|
47
|
+
<m:properties>
|
48
|
+
<d:Name>Category 0001</d:Name>
|
49
|
+
</m:properties>
|
50
|
+
</content>
|
51
|
+
</entry>
|
52
|
+
<entry>
|
53
|
+
<id>http://win7dev:8989/SampleService/RubyOData.svc/Categories(2)</id>
|
54
|
+
<category term="RubyODataService.Category" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
55
|
+
<link rel="edit" title="Category" href="Categories(2)" />
|
56
|
+
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Products" type="application/atom+xml;type=feed" title="Products" href="Categories(2)/Products">
|
57
|
+
<m:inline>
|
58
|
+
<feed>
|
59
|
+
<id>http://win7dev:8989/SampleService/RubyOData.svc/Categories(2)/Products</id>
|
60
|
+
<title type="text">Products</title>
|
61
|
+
<updated>2013-07-22T14:54:47Z</updated>
|
62
|
+
<link rel="self" title="Products" href="Categories(2)/Products" />
|
63
|
+
<entry>
|
64
|
+
<id>http://win7dev:8989/SampleService/RubyOData.svc/Products(2)</id>
|
65
|
+
<category term="RubyODataService.Product" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
66
|
+
<link rel="edit" title="Product" href="Products(2)" />
|
67
|
+
<title />
|
68
|
+
<updated>2013-07-22T14:54:47Z</updated>
|
69
|
+
<author>
|
70
|
+
<name />
|
71
|
+
</author>
|
72
|
+
<content type="application/xml">
|
73
|
+
<m:properties>
|
74
|
+
<d:Name>Widget 0002</d:Name>
|
75
|
+
</m:properties>
|
76
|
+
</content>
|
77
|
+
</entry>
|
78
|
+
</feed>
|
79
|
+
</m:inline>
|
80
|
+
</link>
|
81
|
+
<title />
|
82
|
+
<updated>2013-07-22T14:54:47Z</updated>
|
83
|
+
<author>
|
84
|
+
<name />
|
85
|
+
</author>
|
86
|
+
<content type="application/xml">
|
87
|
+
<m:properties>
|
88
|
+
<d:Name>Category 0001</d:Name>
|
89
|
+
</m:properties>
|
90
|
+
</content>
|
91
|
+
</entry>
|
92
|
+
<entry>
|
93
|
+
<id>http://win7dev:8989/SampleService/RubyOData.svc/Categories(3)</id>
|
94
|
+
<category term="RubyODataService.Category" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
95
|
+
<link rel="edit" title="Category" href="Categories(3)" />
|
96
|
+
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Products" type="application/atom+xml;type=feed" title="Products" href="Categories(3)/Products">
|
97
|
+
<m:inline>
|
98
|
+
<feed>
|
99
|
+
<id>http://win7dev:8989/SampleService/RubyOData.svc/Categories(3)/Products</id>
|
100
|
+
<title type="text">Products</title>
|
101
|
+
<updated>2013-07-22T14:54:47Z</updated>
|
102
|
+
<link rel="self" title="Products" href="Categories(3)/Products" />
|
103
|
+
<entry>
|
104
|
+
<id>http://win7dev:8989/SampleService/RubyOData.svc/Products(3)</id>
|
105
|
+
<category term="RubyODataService.Product" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
106
|
+
<link rel="edit" title="Product" href="Products(3)" />
|
107
|
+
<title />
|
108
|
+
<updated>2013-07-22T14:54:47Z</updated>
|
109
|
+
<author>
|
110
|
+
<name />
|
111
|
+
</author>
|
112
|
+
<content type="application/xml">
|
113
|
+
<m:properties>
|
114
|
+
<d:Name>Widget 0003</d:Name>
|
115
|
+
</m:properties>
|
116
|
+
</content>
|
117
|
+
</entry>
|
118
|
+
</feed>
|
119
|
+
</m:inline>
|
120
|
+
</link>
|
121
|
+
<title />
|
122
|
+
<updated>2013-07-22T14:54:47Z</updated>
|
123
|
+
<author>
|
124
|
+
<name />
|
125
|
+
</author>
|
126
|
+
<content type="application/xml">
|
127
|
+
<m:properties>
|
128
|
+
<d:Name>Category 0002</d:Name>
|
129
|
+
</m:properties>
|
130
|
+
</content>
|
131
|
+
</entry>
|
132
|
+
<entry>
|
133
|
+
<id>http://win7dev:8989/SampleService/RubyOData.svc/Categories(4)</id>
|
134
|
+
<category term="RubyODataService.Category" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
135
|
+
<link rel="edit" title="Category" href="Categories(4)" />
|
136
|
+
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Products" type="application/atom+xml;type=feed" title="Products" href="Categories(4)/Products">
|
137
|
+
<m:inline>
|
138
|
+
<feed>
|
139
|
+
<id>http://win7dev:8989/SampleService/RubyOData.svc/Categories(4)/Products</id>
|
140
|
+
<title type="text">Products</title>
|
141
|
+
<updated>2013-07-22T14:54:47Z</updated>
|
142
|
+
<link rel="self" title="Products" href="Categories(4)/Products" />
|
143
|
+
<entry>
|
144
|
+
<id>http://win7dev:8989/SampleService/RubyOData.svc/Products(4)</id>
|
145
|
+
<category term="RubyODataService.Product" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
146
|
+
<link rel="edit" title="Product" href="Products(4)" />
|
147
|
+
<title />
|
148
|
+
<updated>2013-07-22T14:54:47Z</updated>
|
149
|
+
<author>
|
150
|
+
<name />
|
151
|
+
</author>
|
152
|
+
<content type="application/xml">
|
153
|
+
<m:properties>
|
154
|
+
<d:Name>Widget 0004</d:Name>
|
155
|
+
</m:properties>
|
156
|
+
</content>
|
157
|
+
</entry>
|
158
|
+
</feed>
|
159
|
+
</m:inline>
|
160
|
+
</link>
|
161
|
+
<title />
|
162
|
+
<updated>2013-07-22T14:54:47Z</updated>
|
163
|
+
<author>
|
164
|
+
<name />
|
165
|
+
</author>
|
166
|
+
<content type="application/xml">
|
167
|
+
<m:properties>
|
168
|
+
<d:Name>Category 0002</d:Name>
|
169
|
+
</m:properties>
|
170
|
+
</content>
|
171
|
+
</entry>
|
172
|
+
<entry>
|
173
|
+
<id>http://win7dev:8989/SampleService/RubyOData.svc/Categories(5)</id>
|
174
|
+
<category term="RubyODataService.Category" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
175
|
+
<link rel="edit" title="Category" href="Categories(5)" />
|
176
|
+
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Products" type="application/atom+xml;type=feed" title="Products" href="Categories(5)/Products">
|
177
|
+
<m:inline>
|
178
|
+
<feed>
|
179
|
+
<id>http://win7dev:8989/SampleService/RubyOData.svc/Categories(5)/Products</id>
|
180
|
+
<title type="text">Products</title>
|
181
|
+
<updated>2013-07-22T14:54:47Z</updated>
|
182
|
+
<link rel="self" title="Products" href="Categories(5)/Products" />
|
183
|
+
<entry>
|
184
|
+
<id>http://win7dev:8989/SampleService/RubyOData.svc/Products(5)</id>
|
185
|
+
<category term="RubyODataService.Product" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
186
|
+
<link rel="edit" title="Product" href="Products(5)" />
|
187
|
+
<title />
|
188
|
+
<updated>2013-07-22T14:54:47Z</updated>
|
189
|
+
<author>
|
190
|
+
<name />
|
191
|
+
</author>
|
192
|
+
<content type="application/xml">
|
193
|
+
<m:properties>
|
194
|
+
<d:Name>Widget 0005</d:Name>
|
195
|
+
</m:properties>
|
196
|
+
</content>
|
197
|
+
</entry>
|
198
|
+
</feed>
|
199
|
+
</m:inline>
|
200
|
+
</link>
|
201
|
+
<title />
|
202
|
+
<updated>2013-07-22T14:54:47Z</updated>
|
203
|
+
<author>
|
204
|
+
<name />
|
205
|
+
</author>
|
206
|
+
<content type="application/xml">
|
207
|
+
<m:properties>
|
208
|
+
<d:Name>Category 0002</d:Name>
|
209
|
+
</m:properties>
|
210
|
+
</content>
|
211
|
+
</entry>
|
212
|
+
<entry>
|
213
|
+
<id>http://win7dev:8989/SampleService/RubyOData.svc/Categories(6)</id>
|
214
|
+
<category term="RubyODataService.Category" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
215
|
+
<link rel="edit" title="Category" href="Categories(6)" />
|
216
|
+
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Products" type="application/atom+xml;type=feed" title="Products" href="Categories(6)/Products">
|
217
|
+
<m:inline>
|
218
|
+
<feed>
|
219
|
+
<id>http://win7dev:8989/SampleService/RubyOData.svc/Categories(6)/Products</id>
|
220
|
+
<title type="text">Products</title>
|
221
|
+
<updated>2013-07-22T14:54:47Z</updated>
|
222
|
+
<link rel="self" title="Products" href="Categories(6)/Products" />
|
223
|
+
<author>
|
224
|
+
<name />
|
225
|
+
</author>
|
226
|
+
</feed>
|
227
|
+
</m:inline>
|
228
|
+
</link>
|
229
|
+
<title />
|
230
|
+
<updated>2013-07-22T14:54:47Z</updated>
|
231
|
+
<author>
|
232
|
+
<name />
|
233
|
+
</author>
|
234
|
+
<content type="application/xml">
|
235
|
+
<m:properties>
|
236
|
+
<d:Name>Category 0001</d:Name>
|
237
|
+
</m:properties>
|
238
|
+
</content>
|
239
|
+
</entry>
|
240
|
+
<entry>
|
241
|
+
<id>http://win7dev:8989/SampleService/RubyOData.svc/Categories(7)</id>
|
242
|
+
<category term="RubyODataService.Category" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
|
243
|
+
<link rel="edit" title="Category" href="Categories(7)" />
|
244
|
+
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Products" type="application/atom+xml;type=feed" title="Products" href="Categories(7)/Products">
|
245
|
+
<m:inline>
|
246
|
+
<feed>
|
247
|
+
<id>http://win7dev:8989/SampleService/RubyOData.svc/Categories(7)/Products</id>
|
248
|
+
<title type="text">Products</title>
|
249
|
+
<updated>2013-07-22T14:54:47Z</updated>
|
250
|
+
<link rel="self" title="Products" href="Categories(7)/Products" />
|
251
|
+
<author>
|
252
|
+
<name />
|
253
|
+
</author>
|
254
|
+
</feed>
|
255
|
+
</m:inline>
|
256
|
+
</link>
|
257
|
+
<title />
|
258
|
+
<updated>2013-07-22T14:54:47Z</updated>
|
259
|
+
<author>
|
260
|
+
<name />
|
261
|
+
</author>
|
262
|
+
<content type="application/xml">
|
263
|
+
<m:properties>
|
264
|
+
<d:Name>Category 0002</d:Name>
|
265
|
+
</m:properties>
|
266
|
+
</content>
|
267
|
+
</entry>
|
268
|
+
</feed>
|