odata 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/odata.rb +1 -0
- data/lib/odata/complex_type.rb +67 -0
- data/lib/odata/entity.rb +28 -17
- data/lib/odata/properties.rb +2 -1
- data/lib/odata/properties/geography_point.rb +6 -0
- data/lib/odata/service.rb +32 -8
- data/lib/odata/version.rb +1 -1
- data/spec/fixtures/sample_service/supplier_0.xml +37 -0
- data/spec/fixtures/vcr_cassettes/complex_type_specs.yml +164 -0
- data/spec/odata/complex_type_spec.rb +34 -0
- data/spec/odata/entity_spec.rb +22 -0
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0168d51fbc598d14a4ad183bf905476b1c7e0c33
|
4
|
+
data.tar.gz: 2b1678db31c28a5bd4122753d43153f9d83ac6a7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 315c0846a3e364a234fa63595618d89e8a6d340d0046440c815ba9153ec7db419136443027203ae6d307ba82883d089af0fcb02379c1c33010b53f21979f3251
|
7
|
+
data.tar.gz: 53b3c627ab42f413d264c23aa8dfea0f64e559e87c0cd747ceba9e786de2c0f537836c6fdf528d27bcc6fd1cdfa32c4746350c681a22daed1664f3dfcfa63cd6
|
data/lib/odata.rb
CHANGED
@@ -0,0 +1,67 @@
|
|
1
|
+
module OData
|
2
|
+
# ComplexTypes are used in OData to either encapsulate richer data types for
|
3
|
+
# use as Entity properties. ComplexTypes are composed of properties the same
|
4
|
+
# way that Entities are and, so, the interface for working with the various
|
5
|
+
# properties of a ComplexType mimics that of Entities.
|
6
|
+
class ComplexType
|
7
|
+
# The name of the ComplexType
|
8
|
+
attr_reader :name
|
9
|
+
|
10
|
+
# Creates a new ComplexType based on the supplied options.
|
11
|
+
# @param options [Hash]
|
12
|
+
# @return [self]
|
13
|
+
def initialize(options = {})
|
14
|
+
validate_options(options)
|
15
|
+
|
16
|
+
@name = options[:name].to_s
|
17
|
+
@service = options[:service]
|
18
|
+
|
19
|
+
collect_properties
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns the namespace this ComplexType belongs to.
|
23
|
+
# @return [String]
|
24
|
+
def namespace
|
25
|
+
@namespace ||= service.namespace
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns a list of this ComplexType's property names.
|
29
|
+
# @return [Array<String>]
|
30
|
+
def property_names
|
31
|
+
@property_names ||= properties.collect {|name, property| name}
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns the value of the requested property.
|
35
|
+
# @param property_name [to_s]
|
36
|
+
# @return [*]
|
37
|
+
def [](property_name)
|
38
|
+
properties[property_name.to_s].value
|
39
|
+
end
|
40
|
+
|
41
|
+
# Sets the value of the named property.
|
42
|
+
# @param property_name [to_s]
|
43
|
+
# @param value [*]
|
44
|
+
# @return [*]
|
45
|
+
def []=(property_name, value)
|
46
|
+
properties[property_name.to_s].value = value
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def service
|
52
|
+
@service
|
53
|
+
end
|
54
|
+
|
55
|
+
def properties
|
56
|
+
@properties
|
57
|
+
end
|
58
|
+
|
59
|
+
def validate_options(options)
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
def collect_properties
|
64
|
+
@properties = service.properties_for_complex_type(name)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/odata/entity.rb
CHANGED
@@ -30,22 +30,22 @@ module OData
|
|
30
30
|
# @param property_name [to_s]
|
31
31
|
# @return [*]
|
32
32
|
def [](property_name)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
if properties[property_name.to_s].is_a?(::OData::ComplexType)
|
34
|
+
properties[property_name.to_s]
|
35
|
+
else
|
36
|
+
properties[property_name.to_s].value
|
37
37
|
end
|
38
|
+
rescue NoMethodError
|
39
|
+
raise ArgumentError, "Unknown property: #{property_name}"
|
38
40
|
end
|
39
41
|
|
40
42
|
# Set property value
|
41
43
|
# @param property_name [to_s]
|
42
44
|
# @param value [*]
|
43
45
|
def []=(property_name, value)
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
raise ArgumentError, "Unknown property: #{property_name}"
|
48
|
-
end
|
46
|
+
properties[property_name.to_s].value = value
|
47
|
+
rescue NoMethodError
|
48
|
+
raise ArgumentError, "Unknown property: #{property_name}"
|
49
49
|
end
|
50
50
|
|
51
51
|
# Create Entity with provided properties and options.
|
@@ -55,7 +55,7 @@ module OData
|
|
55
55
|
def self.with_properties(new_properties = {}, options = {})
|
56
56
|
entity = OData::Entity.new(options)
|
57
57
|
entity.instance_eval do
|
58
|
-
service.
|
58
|
+
service.properties_for_entity(name).each do |name, instance|
|
59
59
|
set_property(name, instance)
|
60
60
|
end
|
61
61
|
|
@@ -118,10 +118,20 @@ module OData
|
|
118
118
|
|
119
119
|
private
|
120
120
|
|
121
|
-
def
|
121
|
+
def instantiate_property(property_name, value)
|
122
122
|
value_type = service.get_property_type(name, property_name)
|
123
|
-
|
124
|
-
|
123
|
+
if value_type =~ /^#{namespace}\./
|
124
|
+
type_name = value_type.gsub(/^#{namespace}\./, '')
|
125
|
+
property = ::OData::ComplexType.new(name: type_name, service: service)
|
126
|
+
value.element_children.each do |node|
|
127
|
+
property[node.name] = node.content
|
128
|
+
end
|
129
|
+
property
|
130
|
+
else
|
131
|
+
klass_name = value_type.gsub(/^Edm\./, '')
|
132
|
+
value = value.content unless value.nil?
|
133
|
+
::OData::Properties.const_get(klass_name).new(property_name, value)
|
134
|
+
end
|
125
135
|
end
|
126
136
|
|
127
137
|
def properties
|
@@ -144,9 +154,9 @@ module OData
|
|
144
154
|
property_xml.attributes['null'].value == 'true'
|
145
155
|
value = nil
|
146
156
|
else
|
147
|
-
value = property_xml
|
157
|
+
value = property_xml
|
148
158
|
end
|
149
|
-
property =
|
159
|
+
property = instantiate_property(property_name, value)
|
150
160
|
set_property(property_name, property)
|
151
161
|
end
|
152
162
|
end
|
@@ -154,9 +164,10 @@ module OData
|
|
154
164
|
|
155
165
|
def self.process_feed_property(entity, xml_doc, property_name)
|
156
166
|
entity.instance_eval do
|
157
|
-
property_value = xml_doc.xpath("//#{property_name}").first
|
167
|
+
property_value = xml_doc.xpath("//#{property_name}").first
|
158
168
|
property_name = service.send("get_#{property_name}_property_name", name)
|
159
|
-
|
169
|
+
return if property_name.nil?
|
170
|
+
property = instantiate_property(property_name, property_value)
|
160
171
|
set_property(property_name, property)
|
161
172
|
end
|
162
173
|
end
|
data/lib/odata/properties.rb
CHANGED
data/lib/odata/service.rb
CHANGED
@@ -142,6 +142,8 @@ module OData
|
|
142
142
|
# @return [String] the name of the property used as the entity summary
|
143
143
|
def get_summary_property_name(entity_name)
|
144
144
|
metadata.xpath("//EntityType[@Name='#{entity_name}']/Property[@FC_TargetPath='SyndicationSummary']").first.attributes['Name'].value
|
145
|
+
rescue NoMethodError
|
146
|
+
nil
|
145
147
|
end
|
146
148
|
|
147
149
|
# Get the primary key for the supplied Entity.
|
@@ -154,20 +156,32 @@ module OData
|
|
154
156
|
|
155
157
|
# Get the list of properties and their various options for the supplied
|
156
158
|
# Entity name.
|
157
|
-
#
|
158
159
|
# @param entity_name [to_s]
|
159
160
|
# @return [Hash]
|
160
|
-
|
161
|
+
# @api private
|
162
|
+
def properties_for_entity(entity_name)
|
161
163
|
type_definition = metadata.xpath("//EntityType[@Name='#{entity_name}']").first
|
162
164
|
raise ArgumentError, "Unknown EntityType: #{entity_name}" if type_definition.nil?
|
163
165
|
properties_to_return = {}
|
164
166
|
type_definition.xpath('./Property').each do |property_xml|
|
165
|
-
property_name = property_xml
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
167
|
+
property_name, property = process_property_from_xml(property_xml)
|
168
|
+
properties_to_return[property_name] = property
|
169
|
+
end
|
170
|
+
properties_to_return
|
171
|
+
end
|
172
|
+
|
173
|
+
# Get list of properties and their various options for the supplied
|
174
|
+
# ComplexType name.
|
175
|
+
# @param type_name [to_s]
|
176
|
+
# @return [Hash]
|
177
|
+
# @api private
|
178
|
+
def properties_for_complex_type(type_name)
|
179
|
+
type_definition = metadata.xpath("//ComplexType[@Name='#{type_name}']").first
|
180
|
+
raise ArgumentError, "Unknown ComplexType: #{type_name}" if type_definition.nil?
|
181
|
+
properties_to_return = {}
|
182
|
+
type_definition.xpath('./Property').each do |property_xml|
|
183
|
+
property_name, property = process_property_from_xml(property_xml)
|
184
|
+
properties_to_return[property_name] = property
|
171
185
|
end
|
172
186
|
properties_to_return
|
173
187
|
end
|
@@ -197,5 +211,15 @@ module OData
|
|
197
211
|
::Nokogiri::XML(response.body).remove_namespaces!
|
198
212
|
}.call
|
199
213
|
end
|
214
|
+
|
215
|
+
def process_property_from_xml(property_xml)
|
216
|
+
property_name = property_xml.attributes['Name'].value
|
217
|
+
value_type = property_xml.attributes['Type'].value
|
218
|
+
property_options = {}
|
219
|
+
property_options[:allows_nil] = false if property_xml.attributes['Nullable'] == 'false'
|
220
|
+
klass_name = value_type.gsub(/^Edm\./, '')
|
221
|
+
property = get_property_class(klass_name).new(property_name, nil, property_options)
|
222
|
+
return [property_name, property]
|
223
|
+
end
|
200
224
|
end
|
201
225
|
end
|
data/lib/odata/version.rb
CHANGED
@@ -0,0 +1,37 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<entry xml:base="http://services.odata.org/OData/OData.svc/" xmlns="http://www.w3.org/2005/Atom"
|
3
|
+
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
|
4
|
+
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
|
5
|
+
xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml" m:etag="W/"0"">
|
6
|
+
<id>http://services.odata.org/OData/OData.svc/Suppliers(0)</id>
|
7
|
+
<category term="ODataDemo.Supplier" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
|
8
|
+
<link rel="edit" title="Supplier" href="Suppliers(0)"/>
|
9
|
+
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Products"
|
10
|
+
type="application/atom+xml;type=feed" title="Products" href="Suppliers(0)/Products"/>
|
11
|
+
<title type="text">Exotic Liquids</title>
|
12
|
+
<updated>2014-09-15T04:34:42Z</updated>
|
13
|
+
<author>
|
14
|
+
<name/>
|
15
|
+
</author>
|
16
|
+
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/Products" type="application/xml"
|
17
|
+
title="Products" href="Suppliers(0)/$links/Products"/>
|
18
|
+
<content type="application/xml">
|
19
|
+
<m:properties>
|
20
|
+
<d:ID m:type="Edm.Int32">0</d:ID>
|
21
|
+
<d:Name>Exotic Liquids</d:Name>
|
22
|
+
<d:Address m:type="ODataDemo.Address">
|
23
|
+
<d:Street>NE 228th</d:Street>
|
24
|
+
<d:City>Sammamish</d:City>
|
25
|
+
<d:State>WA</d:State>
|
26
|
+
<d:ZipCode>98074</d:ZipCode>
|
27
|
+
<d:Country>USA</d:Country>
|
28
|
+
</d:Address>
|
29
|
+
<d:Location m:type="Edm.GeographyPoint">
|
30
|
+
<gml:Point gml:srsName="http://www.opengis.net/def/crs/EPSG/0/4326">
|
31
|
+
<gml:pos>47.6316604614258 -122.03547668457</gml:pos>
|
32
|
+
</gml:Point>
|
33
|
+
</d:Location>
|
34
|
+
<d:Concurrency m:type="Edm.Int32">0</d:Concurrency>
|
35
|
+
</m:properties>
|
36
|
+
</content>
|
37
|
+
</entry>
|
@@ -0,0 +1,164 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://services.odata.org/OData/OData.svc/$metadata
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
User-Agent:
|
11
|
+
- Typhoeus - https://github.com/typhoeus/typhoeus
|
12
|
+
response:
|
13
|
+
status:
|
14
|
+
code: 200
|
15
|
+
message: OK
|
16
|
+
headers:
|
17
|
+
Cache-Control:
|
18
|
+
- no-cache
|
19
|
+
Content-Length:
|
20
|
+
- '10034'
|
21
|
+
Content-Type:
|
22
|
+
- application/xml;charset=utf-8
|
23
|
+
Server:
|
24
|
+
- Microsoft-IIS/8.0
|
25
|
+
X-Content-Type-Options:
|
26
|
+
- nosniff
|
27
|
+
DataServiceVersion:
|
28
|
+
- 3.0;
|
29
|
+
X-AspNet-Version:
|
30
|
+
- 4.0.30319
|
31
|
+
X-Powered-By:
|
32
|
+
- ASP.NET
|
33
|
+
Access-Control-Allow-Origin:
|
34
|
+
- "*"
|
35
|
+
Access-Control-Allow-Methods:
|
36
|
+
- GET
|
37
|
+
Access-Control-Allow-Headers:
|
38
|
+
- Accept, Origin, Content-Type, MaxDataServiceVersion
|
39
|
+
Access-Control-Expose-Headers:
|
40
|
+
- DataServiceVersion
|
41
|
+
Set-Cookie:
|
42
|
+
- ARRAffinity=9df27d486a924e1ae61bad0640ee28788b5a0f49ab9983f64ad6636df0c674a5;Path=/;Domain=services.odata.org
|
43
|
+
Date:
|
44
|
+
- Wed, 23 Jul 2014 17:40:38 GMT
|
45
|
+
body:
|
46
|
+
encoding: UTF-8
|
47
|
+
string: <?xml version="1.0" encoding="utf-8"?><edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx"><edmx:DataServices
|
48
|
+
m:DataServiceVersion="3.0" m:MaxDataServiceVersion="3.0" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"><Schema
|
49
|
+
Namespace="ODataDemo" xmlns="http://schemas.microsoft.com/ado/2009/11/edm"><EntityType
|
50
|
+
Name="Product"><Key><PropertyRef Name="ID" /></Key><Property Name="ID" Type="Edm.Int32"
|
51
|
+
Nullable="false" /><Property Name="Name" Type="Edm.String" m:FC_TargetPath="SyndicationTitle"
|
52
|
+
m:FC_ContentKind="text" m:FC_KeepInContent="false" /><Property Name="Description"
|
53
|
+
Type="Edm.String" m:FC_TargetPath="SyndicationSummary" m:FC_ContentKind="text"
|
54
|
+
m:FC_KeepInContent="false" /><Property Name="ReleaseDate" Type="Edm.DateTime"
|
55
|
+
Nullable="false" /><Property Name="DiscontinuedDate" Type="Edm.DateTime" /><Property
|
56
|
+
Name="Rating" Type="Edm.Int16" Nullable="false" /><Property Name="Price" Type="Edm.Double"
|
57
|
+
Nullable="false" /><NavigationProperty Name="Categories" Relationship="ODataDemo.Product_Categories_Category_Products"
|
58
|
+
ToRole="Category_Products" FromRole="Product_Categories" /><NavigationProperty
|
59
|
+
Name="Supplier" Relationship="ODataDemo.Product_Supplier_Supplier_Products"
|
60
|
+
ToRole="Supplier_Products" FromRole="Product_Supplier" /><NavigationProperty
|
61
|
+
Name="ProductDetail" Relationship="ODataDemo.Product_ProductDetail_ProductDetail_Product"
|
62
|
+
ToRole="ProductDetail_Product" FromRole="Product_ProductDetail" /></EntityType><EntityType
|
63
|
+
Name="FeaturedProduct" BaseType="ODataDemo.Product"><NavigationProperty Name="Advertisement"
|
64
|
+
Relationship="ODataDemo.FeaturedProduct_Advertisement_Advertisement_FeaturedProduct"
|
65
|
+
ToRole="Advertisement_FeaturedProduct" FromRole="FeaturedProduct_Advertisement"
|
66
|
+
/></EntityType><EntityType Name="ProductDetail"><Key><PropertyRef Name="ProductID"
|
67
|
+
/></Key><Property Name="ProductID" Type="Edm.Int32" Nullable="false" /><Property
|
68
|
+
Name="Details" Type="Edm.String" /><NavigationProperty Name="Product" Relationship="ODataDemo.Product_ProductDetail_ProductDetail_Product"
|
69
|
+
ToRole="Product_ProductDetail" FromRole="ProductDetail_Product" /></EntityType><EntityType
|
70
|
+
Name="Category" OpenType="true"><Key><PropertyRef Name="ID" /></Key><Property
|
71
|
+
Name="ID" Type="Edm.Int32" Nullable="false" /><Property Name="Name" Type="Edm.String"
|
72
|
+
m:FC_TargetPath="SyndicationTitle" m:FC_ContentKind="text" m:FC_KeepInContent="true"
|
73
|
+
/><NavigationProperty Name="Products" Relationship="ODataDemo.Product_Categories_Category_Products"
|
74
|
+
ToRole="Product_Categories" FromRole="Category_Products" /></EntityType><EntityType
|
75
|
+
Name="Supplier"><Key><PropertyRef Name="ID" /></Key><Property Name="ID" Type="Edm.Int32"
|
76
|
+
Nullable="false" /><Property Name="Name" Type="Edm.String" m:FC_TargetPath="SyndicationTitle"
|
77
|
+
m:FC_ContentKind="text" m:FC_KeepInContent="true" /><Property Name="Address"
|
78
|
+
Type="ODataDemo.Address" /><Property Name="Location" Type="Edm.GeographyPoint"
|
79
|
+
SRID="Variable" /><Property Name="Concurrency" Type="Edm.Int32" ConcurrencyMode="Fixed"
|
80
|
+
Nullable="false" /><NavigationProperty Name="Products" Relationship="ODataDemo.Product_Supplier_Supplier_Products"
|
81
|
+
ToRole="Product_Supplier" FromRole="Supplier_Products" /></EntityType><ComplexType
|
82
|
+
Name="Address"><Property Name="Street" Type="Edm.String" /><Property Name="City"
|
83
|
+
Type="Edm.String" /><Property Name="State" Type="Edm.String" /><Property Name="ZipCode"
|
84
|
+
Type="Edm.String" /><Property Name="Country" Type="Edm.String" /></ComplexType><EntityType
|
85
|
+
Name="Person"><Key><PropertyRef Name="ID" /></Key><Property Name="ID" Type="Edm.Int32"
|
86
|
+
Nullable="false" /><Property Name="Name" Type="Edm.String" /><NavigationProperty
|
87
|
+
Name="PersonDetail" Relationship="ODataDemo.Person_PersonDetail_PersonDetail_Person"
|
88
|
+
ToRole="PersonDetail_Person" FromRole="Person_PersonDetail" /></EntityType><EntityType
|
89
|
+
Name="Customer" BaseType="ODataDemo.Person"><Property Name="TotalExpense"
|
90
|
+
Type="Edm.Decimal" Nullable="false" /></EntityType><EntityType Name="Employee"
|
91
|
+
BaseType="ODataDemo.Person"><Property Name="EmployeeID" Type="Edm.Int64" Nullable="false"
|
92
|
+
/><Property Name="HireDate" Type="Edm.DateTime" Nullable="false" /><Property
|
93
|
+
Name="Salary" Type="Edm.Single" Nullable="false" /></EntityType><EntityType
|
94
|
+
Name="PersonDetail"><Key><PropertyRef Name="PersonID" /></Key><Property Name="PersonID"
|
95
|
+
Type="Edm.Int32" Nullable="false" /><Property Name="Age" Type="Edm.Byte" Nullable="false"
|
96
|
+
/><Property Name="Gender" Type="Edm.Boolean" Nullable="false" /><Property
|
97
|
+
Name="Phone" Type="Edm.String" /><Property Name="Address" Type="ODataDemo.Address"
|
98
|
+
/><Property Name="Photo" Type="Edm.Stream" Nullable="false" /><NavigationProperty
|
99
|
+
Name="Person" Relationship="ODataDemo.Person_PersonDetail_PersonDetail_Person"
|
100
|
+
ToRole="Person_PersonDetail" FromRole="PersonDetail_Person" /></EntityType><EntityType
|
101
|
+
Name="Advertisement" m:HasStream="true"><Key><PropertyRef Name="ID" /></Key><Property
|
102
|
+
Name="ID" Type="Edm.Guid" Nullable="false" /><Property Name="Name" Type="Edm.String"
|
103
|
+
/><Property Name="AirDate" Type="Edm.DateTime" Nullable="false" /><NavigationProperty
|
104
|
+
Name="FeaturedProduct" Relationship="ODataDemo.FeaturedProduct_Advertisement_Advertisement_FeaturedProduct"
|
105
|
+
ToRole="FeaturedProduct_Advertisement" FromRole="Advertisement_FeaturedProduct"
|
106
|
+
/></EntityType><Association Name="Product_Categories_Category_Products"><End
|
107
|
+
Type="ODataDemo.Category" Role="Category_Products" Multiplicity="*" /><End
|
108
|
+
Type="ODataDemo.Product" Role="Product_Categories" Multiplicity="*" /></Association><Association
|
109
|
+
Name="Product_Supplier_Supplier_Products"><End Type="ODataDemo.Supplier" Role="Supplier_Products"
|
110
|
+
Multiplicity="0..1" /><End Type="ODataDemo.Product" Role="Product_Supplier"
|
111
|
+
Multiplicity="*" /></Association><Association Name="Product_ProductDetail_ProductDetail_Product"><End
|
112
|
+
Type="ODataDemo.ProductDetail" Role="ProductDetail_Product" Multiplicity="0..1"
|
113
|
+
/><End Type="ODataDemo.Product" Role="Product_ProductDetail" Multiplicity="0..1"
|
114
|
+
/></Association><Association Name="FeaturedProduct_Advertisement_Advertisement_FeaturedProduct"><End
|
115
|
+
Type="ODataDemo.Advertisement" Role="Advertisement_FeaturedProduct" Multiplicity="0..1"
|
116
|
+
/><End Type="ODataDemo.FeaturedProduct" Role="FeaturedProduct_Advertisement"
|
117
|
+
Multiplicity="0..1" /></Association><Association Name="Person_PersonDetail_PersonDetail_Person"><End
|
118
|
+
Type="ODataDemo.PersonDetail" Role="PersonDetail_Person" Multiplicity="0..1"
|
119
|
+
/><End Type="ODataDemo.Person" Role="Person_PersonDetail" Multiplicity="0..1"
|
120
|
+
/></Association><EntityContainer Name="DemoService" m:IsDefaultEntityContainer="true"><EntitySet
|
121
|
+
Name="Products" EntityType="ODataDemo.Product" /><EntitySet Name="ProductDetails"
|
122
|
+
EntityType="ODataDemo.ProductDetail" /><EntitySet Name="Categories" EntityType="ODataDemo.Category"
|
123
|
+
/><EntitySet Name="Suppliers" EntityType="ODataDemo.Supplier" /><EntitySet
|
124
|
+
Name="Persons" EntityType="ODataDemo.Person" /><EntitySet Name="PersonDetails"
|
125
|
+
EntityType="ODataDemo.PersonDetail" /><EntitySet Name="Advertisements" EntityType="ODataDemo.Advertisement"
|
126
|
+
/><FunctionImport Name="GetProductsByRating" ReturnType="Collection(ODataDemo.Product)"
|
127
|
+
EntitySet="Products" m:HttpMethod="GET"><Parameter Name="rating" Type="Edm.Int16"
|
128
|
+
Nullable="false" /></FunctionImport><AssociationSet Name="Products_Advertisement_Advertisements"
|
129
|
+
Association="ODataDemo.FeaturedProduct_Advertisement_Advertisement_FeaturedProduct"><End
|
130
|
+
Role="FeaturedProduct_Advertisement" EntitySet="Products" /><End Role="Advertisement_FeaturedProduct"
|
131
|
+
EntitySet="Advertisements" /></AssociationSet><AssociationSet Name="Products_Categories_Categories"
|
132
|
+
Association="ODataDemo.Product_Categories_Category_Products"><End Role="Product_Categories"
|
133
|
+
EntitySet="Products" /><End Role="Category_Products" EntitySet="Categories"
|
134
|
+
/></AssociationSet><AssociationSet Name="Products_Supplier_Suppliers" Association="ODataDemo.Product_Supplier_Supplier_Products"><End
|
135
|
+
Role="Product_Supplier" EntitySet="Products" /><End Role="Supplier_Products"
|
136
|
+
EntitySet="Suppliers" /></AssociationSet><AssociationSet Name="Products_ProductDetail_ProductDetails"
|
137
|
+
Association="ODataDemo.Product_ProductDetail_ProductDetail_Product"><End Role="Product_ProductDetail"
|
138
|
+
EntitySet="Products" /><End Role="ProductDetail_Product" EntitySet="ProductDetails"
|
139
|
+
/></AssociationSet><AssociationSet Name="Persons_PersonDetail_PersonDetails"
|
140
|
+
Association="ODataDemo.Person_PersonDetail_PersonDetail_Person"><End Role="Person_PersonDetail"
|
141
|
+
EntitySet="Persons" /><End Role="PersonDetail_Person" EntitySet="PersonDetails"
|
142
|
+
/></AssociationSet></EntityContainer><Annotations Target="ODataDemo.DemoService"><ValueAnnotation
|
143
|
+
Term="Org.OData.Display.V1.Description" String="This is a sample OData service
|
144
|
+
with vocabularies" /></Annotations><Annotations Target="ODataDemo.Product"><ValueAnnotation
|
145
|
+
Term="Org.OData.Display.V1.Description" String="All Products available in
|
146
|
+
the online store" /></Annotations><Annotations Target="ODataDemo.Product/Name"><ValueAnnotation
|
147
|
+
Term="Org.OData.Display.V1.DisplayName" String="Product Name" /></Annotations><Annotations
|
148
|
+
Target="ODataDemo.DemoService/Suppliers"><ValueAnnotation Term="Org.OData.Publication.V1.PublisherName"
|
149
|
+
String="Microsoft Corp." /><ValueAnnotation Term="Org.OData.Publication.V1.PublisherId"
|
150
|
+
String="MSFT" /><ValueAnnotation Term="Org.OData.Publication.V1.Keywords"
|
151
|
+
String="Inventory, Supplier, Advertisers, Sales, Finance" /><ValueAnnotation
|
152
|
+
Term="Org.OData.Publication.V1.AttributionUrl" String="http://www.odata.org/"
|
153
|
+
/><ValueAnnotation Term="Org.OData.Publication.V1.AttributionDescription"
|
154
|
+
String="All rights reserved" /><ValueAnnotation Term="Org.OData.Publication.V1.DocumentationUrl
|
155
|
+
" String="http://www.odata.org/" /><ValueAnnotation Term="Org.OData.Publication.V1.TermsOfUseUrl"
|
156
|
+
String="All rights reserved" /><ValueAnnotation Term="Org.OData.Publication.V1.PrivacyPolicyUrl"
|
157
|
+
String="http://www.odata.org/" /><ValueAnnotation Term="Org.OData.Publication.V1.LastModified"
|
158
|
+
String="4/2/2013" /><ValueAnnotation Term="Org.OData.Publication.V1.ImageUrl
|
159
|
+
" String="http://www.odata.org/" /></Annotations></Schema></edmx:DataServices></edmx:Edmx>
|
160
|
+
http_version: '1.1'
|
161
|
+
adapter_metadata:
|
162
|
+
effective_url: http://services.odata.org/OData/OData.svc/$metadata
|
163
|
+
recorded_at: Wed, 23 Jul 2014 17:40:40 GMT
|
164
|
+
recorded_with: VCR 2.9.2
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe OData::ComplexType, vcr: {cassette_name: 'complex_type_specs'} do
|
4
|
+
before(:example) do
|
5
|
+
OData::Service.open('http://services.odata.org/OData/OData.svc', name: 'ODataDemo')
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:subject) { OData::ComplexType.new(name: 'Address', service: service) }
|
9
|
+
let(:service) { OData::ServiceRegistry['ODataDemo'] }
|
10
|
+
|
11
|
+
it { expect(subject).to respond_to(:name) }
|
12
|
+
it { expect(subject).to respond_to(:namespace) }
|
13
|
+
it { expect(subject).to respond_to(:property_names) }
|
14
|
+
it { expect(subject).to respond_to(:[]) }
|
15
|
+
it { expect(subject).to respond_to(:[]=) }
|
16
|
+
|
17
|
+
describe 'is properly parsed from service metadata' do
|
18
|
+
it { expect(subject.name).to eq('Address') }
|
19
|
+
it { expect(subject.namespace).to eq('ODataDemo') }
|
20
|
+
it { expect(subject.property_names).to eq(%w{Street City State ZipCode Country}) }
|
21
|
+
|
22
|
+
it { expect(subject['Street']).to be_nil }
|
23
|
+
it { expect(subject['City']).to be_nil }
|
24
|
+
it { expect(subject['State']).to be_nil }
|
25
|
+
it { expect(subject['ZipCode']).to be_nil }
|
26
|
+
it { expect(subject['Country']).to be_nil }
|
27
|
+
|
28
|
+
it { subject['Street'] = 'Test'; expect(subject['Street']).to eq('Test') }
|
29
|
+
it { subject['City'] = 'Test'; expect(subject['City']).to eq('Test') }
|
30
|
+
it { subject['State'] = 'Test'; expect(subject['State']).to eq('Test') }
|
31
|
+
it { subject['ZipCode'] = 'Test'; expect(subject['ZipCode']).to eq('Test') }
|
32
|
+
it { subject['Country'] = 'Test'; expect(subject['Country']).to eq('Test') }
|
33
|
+
end
|
34
|
+
end
|
data/spec/odata/entity_spec.rb
CHANGED
@@ -45,5 +45,27 @@ describe OData::Entity, vcr: {cassette_name: 'entity_specs'} do
|
|
45
45
|
|
46
46
|
it { expect {subject['NonExistant']}.to raise_error(ArgumentError) }
|
47
47
|
it { expect {subject['NonExistant'] = 5}.to raise_error(ArgumentError) }
|
48
|
+
|
49
|
+
context 'with a complex type property' do
|
50
|
+
let(:options) { {
|
51
|
+
type: 'ODataDemo.Supplier',
|
52
|
+
namespace: 'ODataDemo',
|
53
|
+
service_name: 'ODataDemo'
|
54
|
+
} }
|
55
|
+
|
56
|
+
let(:subject) { OData::Entity.from_xml(supplier_xml, options) }
|
57
|
+
let(:supplier_xml) {
|
58
|
+
document = ::Nokogiri::XML(File.open('spec/fixtures/sample_service/supplier_0.xml'))
|
59
|
+
document.remove_namespaces!
|
60
|
+
document.xpath('//entry').first
|
61
|
+
}
|
62
|
+
|
63
|
+
it { expect(subject.name).to eq('Supplier') }
|
64
|
+
it { expect(subject.type).to eq('ODataDemo.Supplier') }
|
65
|
+
|
66
|
+
it { expect(subject['Address']).to be_a(OData::ComplexType) }
|
67
|
+
it { expect(subject['Address']['Street']).to eq('NE 228th') }
|
68
|
+
it { expect(subject['Address']['City']).to eq('Sammamish') }
|
69
|
+
end
|
48
70
|
end
|
49
71
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: odata
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Thompson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-09-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -153,6 +153,7 @@ files:
|
|
153
153
|
- README.md
|
154
154
|
- Rakefile
|
155
155
|
- lib/odata.rb
|
156
|
+
- lib/odata/complex_type.rb
|
156
157
|
- lib/odata/entity.rb
|
157
158
|
- lib/odata/entity_set.rb
|
158
159
|
- lib/odata/properties.rb
|
@@ -162,6 +163,7 @@ files:
|
|
162
163
|
- lib/odata/properties/date_time_offset.rb
|
163
164
|
- lib/odata/properties/decimal.rb
|
164
165
|
- lib/odata/properties/float.rb
|
166
|
+
- lib/odata/properties/geography_point.rb
|
165
167
|
- lib/odata/properties/guid.rb
|
166
168
|
- lib/odata/properties/integer.rb
|
167
169
|
- lib/odata/properties/number.rb
|
@@ -187,6 +189,8 @@ files:
|
|
187
189
|
- spec/fixtures/sample_service/products_skip0_top5.xml
|
188
190
|
- spec/fixtures/sample_service/products_skip10_top5.xml
|
189
191
|
- spec/fixtures/sample_service/products_skip5_top5.xml
|
192
|
+
- spec/fixtures/sample_service/supplier_0.xml
|
193
|
+
- spec/fixtures/vcr_cassettes/complex_type_specs.yml
|
190
194
|
- spec/fixtures/vcr_cassettes/entity_set_specs.yml
|
191
195
|
- spec/fixtures/vcr_cassettes/entity_set_specs/bad_entry.yml
|
192
196
|
- spec/fixtures/vcr_cassettes/entity_set_specs/existing_entry.yml
|
@@ -196,6 +200,7 @@ files:
|
|
196
200
|
- spec/fixtures/vcr_cassettes/query_specs.yml
|
197
201
|
- spec/fixtures/vcr_cassettes/service_registry_specs.yml
|
198
202
|
- spec/fixtures/vcr_cassettes/service_specs.yml
|
203
|
+
- spec/odata/complex_type_spec.rb
|
199
204
|
- spec/odata/entity_set_spec.rb
|
200
205
|
- spec/odata/entity_spec.rb
|
201
206
|
- spec/odata/properties/binary_spec.rb
|
@@ -251,6 +256,8 @@ test_files:
|
|
251
256
|
- spec/fixtures/sample_service/products_skip0_top5.xml
|
252
257
|
- spec/fixtures/sample_service/products_skip10_top5.xml
|
253
258
|
- spec/fixtures/sample_service/products_skip5_top5.xml
|
259
|
+
- spec/fixtures/sample_service/supplier_0.xml
|
260
|
+
- spec/fixtures/vcr_cassettes/complex_type_specs.yml
|
254
261
|
- spec/fixtures/vcr_cassettes/entity_set_specs.yml
|
255
262
|
- spec/fixtures/vcr_cassettes/entity_set_specs/bad_entry.yml
|
256
263
|
- spec/fixtures/vcr_cassettes/entity_set_specs/existing_entry.yml
|
@@ -260,6 +267,7 @@ test_files:
|
|
260
267
|
- spec/fixtures/vcr_cassettes/query_specs.yml
|
261
268
|
- spec/fixtures/vcr_cassettes/service_registry_specs.yml
|
262
269
|
- spec/fixtures/vcr_cassettes/service_specs.yml
|
270
|
+
- spec/odata/complex_type_spec.rb
|
263
271
|
- spec/odata/entity_set_spec.rb
|
264
272
|
- spec/odata/entity_spec.rb
|
265
273
|
- spec/odata/properties/binary_spec.rb
|