ruby_odata 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- 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>
|