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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 44a27c048ec4706996d0eccc9aff655a5c60be94
4
- data.tar.gz: de691ae9f3cb75ab544642f9826521cfc3bb09e5
3
+ metadata.gz: 0168d51fbc598d14a4ad183bf905476b1c7e0c33
4
+ data.tar.gz: 2b1678db31c28a5bd4122753d43153f9d83ac6a7
5
5
  SHA512:
6
- metadata.gz: cdaae668ecb311bbb45f7abd54b116c9576d6c158c86968379405890aafad70bd14b0deda585c8f7e0cdbe9cb50e258d2590ccec2e3f78561ea851e58cc7a096
7
- data.tar.gz: 84222c7cf63702ccc0f6073962a3ce3317cfb32507560dc49ada9c6ac6fb676cf66061a264fba8fa72849638448739d03c2a47bccdd684097499e1cf473a3cc2
6
+ metadata.gz: 315c0846a3e364a234fa63595618d89e8a6d340d0046440c815ba9153ec7db419136443027203ae6d307ba82883d089af0fcb02379c1c33010b53f21979f3251
7
+ data.tar.gz: 53b3c627ab42f413d264c23aa8dfea0f64e559e87c0cd747ceba9e786de2c0f537836c6fdf528d27bcc6fd1cdfa32c4746350c681a22daed1664f3dfcfa63cd6
data/lib/odata.rb CHANGED
@@ -11,6 +11,7 @@ require 'typhoeus'
11
11
  require 'odata/version'
12
12
  require 'odata/property'
13
13
  require 'odata/properties'
14
+ require 'odata/complex_type'
14
15
  require 'odata/entity'
15
16
  require 'odata/entity_set'
16
17
  require 'odata/query/criteria'
@@ -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
- begin
34
- properties[property_name.to_s].value
35
- rescue NoMethodError
36
- raise ArgumentError, "Unknown property: #{property_name}"
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
- begin
45
- properties[property_name.to_s].value = value
46
- rescue NoMethodError
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.properties_for(name).each do |name, instance|
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 get_property_class(property_name)
121
+ def instantiate_property(property_name, value)
122
122
  value_type = service.get_property_type(name, property_name)
123
- klass_name = value_type.gsub(/^Edm\./, '')
124
- ::OData::Properties.const_get(klass_name)
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.content
157
+ value = property_xml
148
158
  end
149
- property = get_property_class(property_name).new(property_name, value)
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.content
167
+ property_value = xml_doc.xpath("//#{property_name}").first
158
168
  property_name = service.send("get_#{property_name}_property_name", name)
159
- property = get_property_class(property_name).new(property_name, property_value)
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
@@ -11,4 +11,5 @@ require 'odata/properties/float'
11
11
  require 'odata/properties/guid'
12
12
  require 'odata/properties/integer'
13
13
  require 'odata/properties/string'
14
- require 'odata/properties/time'
14
+ require 'odata/properties/time'
15
+ require 'odata/properties/geography_point'
@@ -0,0 +1,6 @@
1
+ module OData
2
+ module Properties
3
+ class GeographyPoint < OData::Property
4
+ end
5
+ end
6
+ end
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
- def properties_for(entity_name)
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.attributes['Name'].value
166
- value_type = property_xml.attributes['Type'].value
167
- property_options = {}
168
- property_options[:allows_nil] = false if property_xml.attributes['Nullable'] == 'false'
169
- klass_name = value_type.gsub(/^Edm\./, '')
170
- properties_to_return[property_name] = get_property_class(klass_name).new(property_name, nil, property_options)
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
@@ -1,3 +1,3 @@
1
1
  module OData
2
- VERSION = '0.5.0'
2
+ VERSION = '0.5.1'
3
3
  end
@@ -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/&quot;0&quot;">
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
@@ -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.0
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-07-21 00:00:00.000000000 Z
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