ruby_odata 0.0.10 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. data/.gitignore +9 -3
  2. data/.travis.yml +4 -0
  3. data/CHANGELOG.rdoc +18 -1
  4. data/README.rdoc +77 -19
  5. data/config/cucumber.yml +4 -3
  6. data/features/basic_auth.feature +5 -7
  7. data/features/batch_request.feature +11 -11
  8. data/features/complex_types.feature +11 -11
  9. data/features/query_builder.feature +27 -18
  10. data/features/service.feature +8 -8
  11. data/features/service_manage.feature +27 -12
  12. data/features/service_methods.feature +37 -0
  13. data/features/ssl.feature +4 -4
  14. data/features/step_definitions/pickle_steps.rb +100 -0
  15. data/features/step_definitions/service_steps.rb +99 -65
  16. data/features/support/constants.rb +3 -0
  17. data/features/support/custom_helpers.rb +54 -0
  18. data/features/support/env.rb +0 -10
  19. data/features/support/hooks.rb +1 -1
  20. data/features/support/pickle.rb +82 -0
  21. data/features/type_conversion.feature +10 -10
  22. data/lib/ruby_odata.rb +4 -1
  23. data/lib/ruby_odata/association.rb +36 -0
  24. data/lib/ruby_odata/class_builder.rb +96 -16
  25. data/lib/ruby_odata/helpers.rb +10 -0
  26. data/lib/ruby_odata/operation.rb +7 -5
  27. data/lib/ruby_odata/property_metadata.rb +11 -6
  28. data/lib/ruby_odata/query_builder.rb +20 -1
  29. data/lib/ruby_odata/service.rb +407 -94
  30. data/lib/ruby_odata/version.rb +1 -1
  31. data/ruby_odata.gemspec +2 -0
  32. data/spec/association_spec.rb +48 -0
  33. data/spec/class_builder_spec.rb +11 -2
  34. data/spec/fixtures/inheritance/edmx_pluralsight.xml +111 -0
  35. data/spec/fixtures/inheritance/result_pluralsight_courses.xml +229 -0
  36. data/spec/fixtures/links/result_links_query.xml +6 -0
  37. data/spec/fixtures/partial/partial_feed_metadata.xml +25 -0
  38. data/spec/fixtures/partial/partial_feed_part_1.xml +42 -0
  39. data/spec/fixtures/partial/partial_feed_part_2.xml +42 -0
  40. data/spec/fixtures/partial/partial_feed_part_3.xml +40 -0
  41. data/spec/fixtures/sample_service/edmx_categories_products.xml +1 -0
  42. data/spec/fixtures/sample_service/result_category_names.xml +5 -0
  43. data/spec/fixtures/sample_service/result_entity_category_web_get.xml +29 -0
  44. data/spec/fixtures/sample_service/result_entity_single_category_web_get.xml +23 -0
  45. data/spec/fixtures/sample_service/result_first_category_id.xml +2 -0
  46. data/spec/fixtures/sample_service/result_multiple_category_products.xml +57 -0
  47. data/spec/fixtures/sample_service/result_single_category.xml +18 -0
  48. data/spec/fixtures/sample_service/result_single_product.xml +26 -0
  49. data/spec/fixtures/sample_service/result_single_product_not_found.xml +4 -0
  50. data/spec/fixtures/sap/edmx_sap_demo_flight.xml +62 -58
  51. data/spec/property_metadata_spec.rb +9 -2
  52. data/spec/query_builder_spec.rb +11 -0
  53. data/spec/revised_service_spec.rb +197 -0
  54. data/spec/service_spec.rb +463 -4
  55. data/test/RubyODataService/RubyODataService.sln +20 -0
  56. data/test/RubyODataService/RubyODataService/App_Start/EntityFramework.SqlServerCompact.cs +12 -0
  57. data/test/RubyODataService/RubyODataService/BasicAuth/RubyOData.svc +3 -0
  58. data/test/RubyODataService/RubyODataService/BasicAuth/RubyOData.svc.cs +107 -0
  59. data/test/RubyODataService/RubyODataService/Global.asax +1 -0
  60. data/test/RubyODataService/RubyODataService/Global.asax.cs +49 -0
  61. data/test/RubyODataService/RubyODataService/Models/AuditFields.cs +16 -0
  62. data/test/RubyODataService/RubyODataService/Models/Category.cs +16 -0
  63. data/test/RubyODataService/RubyODataService/Models/Product.cs +20 -0
  64. data/test/RubyODataService/RubyODataService/Properties/AssemblyInfo.cs +35 -0
  65. data/test/RubyODataService/RubyODataService/RubyOData.svc +3 -0
  66. data/test/RubyODataService/RubyODataService/RubyOData.svc.cs +57 -0
  67. data/test/RubyODataService/RubyODataService/RubyODataContext.cs +16 -0
  68. data/test/RubyODataService/RubyODataService/RubyODataService.csproj +159 -0
  69. data/test/RubyODataService/RubyODataService/RubyODataService.csproj.user +31 -0
  70. data/test/RubyODataService/RubyODataService/Web.Debug.config +30 -0
  71. data/test/RubyODataService/RubyODataService/Web.Release.config +31 -0
  72. data/test/RubyODataService/RubyODataService/Web.config +27 -0
  73. data/test/RubyODataService/RubyODataService/bin/EntityFramework.dll +0 -0
  74. data/test/RubyODataService/RubyODataService/bin/Microsoft.Data.Edm.dll +0 -0
  75. data/test/RubyODataService/RubyODataService/bin/Microsoft.Data.OData.dll +0 -0
  76. data/test/RubyODataService/RubyODataService/bin/Microsoft.Data.Services.Client.dll +0 -0
  77. data/test/RubyODataService/RubyODataService/bin/Microsoft.Data.Services.dll +0 -0
  78. data/test/RubyODataService/RubyODataService/bin/Microsoft.Data.Spatial.dll +0 -0
  79. data/test/RubyODataService/RubyODataService/bin/RubyODataService.dll +0 -0
  80. data/test/RubyODataService/RubyODataService/bin/System.Data.SqlServerCe.Entity.dll +0 -0
  81. data/test/RubyODataService/RubyODataService/bin/System.Data.SqlServerCe.dll +0 -0
  82. data/test/RubyODataService/RubyODataService/bin/System.Spatial.dll +0 -0
  83. data/test/RubyODataService/RubyODataService/bin/WebActivator.dll +0 -0
  84. data/test/RubyODataService/RubyODataService/bin/amd64/Microsoft.VC90.CRT/Microsoft.VC90.CRT.manifest +6 -0
  85. data/test/RubyODataService/RubyODataService/bin/amd64/Microsoft.VC90.CRT/README_ENU.txt +0 -0
  86. data/test/RubyODataService/RubyODataService/bin/amd64/Microsoft.VC90.CRT/msvcr90.dll +0 -0
  87. data/test/RubyODataService/RubyODataService/bin/amd64/sqlcecompact40.dll +0 -0
  88. data/test/RubyODataService/RubyODataService/bin/amd64/sqlceer40EN.dll +0 -0
  89. data/test/RubyODataService/RubyODataService/bin/amd64/sqlceme40.dll +0 -0
  90. data/test/RubyODataService/RubyODataService/bin/amd64/sqlceqp40.dll +0 -0
  91. data/test/RubyODataService/RubyODataService/bin/amd64/sqlcese40.dll +0 -0
  92. data/test/RubyODataService/RubyODataService/bin/x86/Microsoft.VC90.CRT/Microsoft.VC90.CRT.manifest +6 -0
  93. data/test/RubyODataService/RubyODataService/bin/x86/Microsoft.VC90.CRT/README_ENU.txt +0 -0
  94. data/test/RubyODataService/RubyODataService/bin/x86/Microsoft.VC90.CRT/msvcr90.dll +0 -0
  95. data/test/RubyODataService/RubyODataService/bin/x86/sqlcecompact40.dll +0 -0
  96. data/test/RubyODataService/RubyODataService/bin/x86/sqlceer40EN.dll +0 -0
  97. data/test/RubyODataService/RubyODataService/bin/x86/sqlceme40.dll +0 -0
  98. data/test/RubyODataService/RubyODataService/bin/x86/sqlceqp40.dll +0 -0
  99. data/test/RubyODataService/RubyODataService/bin/x86/sqlcese40.dll +0 -0
  100. data/test/RubyODataService/RubyODataService/packages.config +7 -0
  101. data/test/RubyODataService/packages/EntityFramework.4.2.0.0/EntityFramework.4.2.0.0.nupkg +0 -0
  102. data/test/RubyODataService/packages/EntityFramework.4.2.0.0/lib/net40/EntityFramework.dll +0 -0
  103. data/test/RubyODataService/packages/EntityFramework.4.2.0.0/lib/net40/EntityFramework.xml +13488 -0
  104. data/test/RubyODataService/packages/EntityFramework.SqlServerCompact.4.1.8482.2/Content/App_Start/EntityFramework.SqlServerCompact.cs.pp +12 -0
  105. data/test/RubyODataService/packages/EntityFramework.SqlServerCompact.4.1.8482.2/EULA_ENU.rtf +969 -0
  106. data/test/RubyODataService/packages/EntityFramework.SqlServerCompact.4.1.8482.2/EntityFramework.SqlServerCompact.4.1.8482.2.nupkg +0 -0
  107. data/test/RubyODataService/packages/EntityFramework.SqlServerCompact.4.1.8482.2/lib/System.Data.SqlServerCe.Entity.dll +0 -0
  108. data/test/RubyODataService/packages/EntityFramework.SqlServerCompact.4.1.8482.2/tools/install.ps1 +3 -0
  109. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/Content/web.config.transform +8 -0
  110. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/amd64/Microsoft.VC90.CRT/Microsoft.VC90.CRT.manifest +6 -0
  111. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/amd64/Microsoft.VC90.CRT/README_ENU.txt +0 -0
  112. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/amd64/Microsoft.VC90.CRT/msvcr90.dll +0 -0
  113. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/amd64/sqlcecompact40.dll +0 -0
  114. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/amd64/sqlceer40EN.dll +0 -0
  115. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/amd64/sqlceme40.dll +0 -0
  116. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/amd64/sqlceqp40.dll +0 -0
  117. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/amd64/sqlcese40.dll +0 -0
  118. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/x86/Microsoft.VC90.CRT/Microsoft.VC90.CRT.manifest +6 -0
  119. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/x86/Microsoft.VC90.CRT/README_ENU.txt +0 -0
  120. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/x86/Microsoft.VC90.CRT/msvcr90.dll +0 -0
  121. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/x86/sqlcecompact40.dll +0 -0
  122. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/x86/sqlceer40EN.dll +0 -0
  123. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/x86/sqlceme40.dll +0 -0
  124. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/x86/sqlceqp40.dll +0 -0
  125. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/x86/sqlcese40.dll +0 -0
  126. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/SQLCE_EULA_ENU.rtf +778 -0
  127. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/SqlServerCompact.4.0.8482.1.nupkg +0 -0
  128. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/Tools/GetSqlCEPostBuildCmd.ps1 +12 -0
  129. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/Tools/install.ps1 +11 -0
  130. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/Tools/uninstall.ps1 +9 -0
  131. data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/lib/System.Data.SqlServerCe.dll +0 -0
  132. data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/DataSvcUtil.exe +0 -0
  133. data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/License.rtf +708 -0
  134. data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.Edm.dll +0 -0
  135. data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.Edm.xml +4150 -0
  136. data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.OData.dll +0 -0
  137. data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.OData.xml +1969 -0
  138. data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.Services.Client.dll +0 -0
  139. data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.Services.Client.xml +1442 -0
  140. data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.Services.Design.dll +0 -0
  141. data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.Services.Design.xml +191 -0
  142. data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.Services.dll +0 -0
  143. data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.Services.xml +2559 -0
  144. data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.Spatial.dll +0 -0
  145. data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.Spatial.xml +15 -0
  146. data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.VsDesigner.DataServices.Adapter.dll +0 -0
  147. data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/README.txt +6 -0
  148. data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/System.Spatial.dll +0 -0
  149. data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/System.Spatial.xml +2276 -0
  150. data/test/RubyODataService/packages/WebActivator.1.0.0.0/WebActivator.1.0.0.0.nupkg +0 -0
  151. data/test/RubyODataService/packages/WebActivator.1.0.0.0/lib/WebActivator.dll +0 -0
  152. data/test/RubyODataService/packages/repositories.config +4 -0
  153. data/test/applicationhost.config.template +2 -2
  154. data/test/blueprints.rb +5 -4
  155. data/test/iisExpress x64.bat b/data/test/iisExpress → x64.bat +0 -0
  156. data/test/iisExpress x86.bat b/data/test/iisExpress → x86.bat +0 -0
  157. data/test/setpath.rb +13 -3
  158. data/test/usage_samples/querying.rb +45 -0
  159. data/test/usage_samples/reflection.rb +16 -0
  160. data/test/usage_samples/sample_data.rb +30 -0
  161. metadata +327 -36
  162. data/test/Cassini x64.bat +0 -1
  163. data/test/Cassini x86.bat +0 -1
  164. data/test/SampleService/App_Code/AuditFields.cs +0 -13
  165. data/test/SampleService/App_Code/Entities.cs +0 -145
  166. data/test/SampleService/App_Code/Model.Designer.cs +0 -578
  167. data/test/SampleService/App_Code/Model.edmx +0 -157
  168. data/test/SampleService/App_Code/ModelContainerExtended.cs +0 -32
  169. data/test/SampleService/App_Data/_TestDB.mdf +0 -0
  170. data/test/SampleService/App_Data/_TestDB_Log.ldf +0 -0
  171. data/test/SampleService/BasicAuth/Entities.svc +0 -1
  172. data/test/SampleService/Entities.svc +0 -1
  173. data/test/SampleService/web.config +0 -37
data/.gitignore CHANGED
@@ -4,12 +4,18 @@ rerun.txt
4
4
  tmp
5
5
  tmp/*
6
6
  .eprj
7
- test/SampleService/App_Data/TestDB.mdf
8
- test/SampleService/App_Data/TestDB_Log.ldf
9
7
  pkg/*
10
8
  doc/*
11
9
  *.gem
12
10
  .bundle
13
11
  Gemfile.lock
14
12
  pkg/*
15
- test/applicationhost.config
13
+ test/applicationhost.config
14
+ .rvmrc
15
+ .DS_Store
16
+ *ReSharper*
17
+ *.suo
18
+ obj
19
+ App_Data/
20
+ *.pdb
21
+ test/RubyODataService/RubyODataService/bin/*.xml
@@ -0,0 +1,4 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.2
4
+ script: "bundle exec rake spec"
@@ -68,4 +68,21 @@
68
68
  * Handled building results (classes) where the category element is missing but there is a title element instead. (Reported by mkoegel, issue #3 on github in the comments)
69
69
  * Other
70
70
  * Change HTTP port to 8989 since 8888 conflicts with the Intel AppStore
71
- * Refactored service step for HTTP calls where the service address is defined within the step making it easier to make changes in the future.
71
+ * Refactored service step for HTTP calls where the service address is defined within the step making it easier to make changes in the future.
72
+
73
+ === 0.1.0
74
+ * **BREAKING CHANGES**
75
+ * Previously the ruby_odata +Service.execute+ and +Service.save_changes+ used to return a single entity object if there was only one result returned. Now, the results are always an Enumerable (except in the case of boolean results like a delete), so if you just need one result, use the +first+ method on the result set
76
+ * New Features
77
+ * Support for partial results (thanks arienmalec)
78
+ * Added support for single layer inheritance (thanks to http://odetocode.com/Blogs/scott/archive/2010/07/11/odata-and-ruby.aspx)
79
+ * Added support for querying links (see https://github.com/visoft/ruby_odata/issues/10)
80
+ * Added support for adding links between entities (add_link)
81
+ * Added support for lazy loading
82
+ * Added a convenience method (+first+) for accessing a single result by id
83
+ * Added basic reflection of the entity model via the ruby_odata service
84
+ * Added the ability to create ruby_odata models in a specified namespace to prevent conflicts with local models
85
+ * Added the ability to call function imports exposed by the WCF Data Service
86
+ * Other
87
+ * Changed the test project (for Cucumber integration tests) to use SQL Compact 4, Entity Framework 4.1, and WCF Data Services October 2011 CTP
88
+ * Added {Pickle}[https://github.com/ianwhite/pickle] integration to simplify Cucumber step definitions
@@ -9,10 +9,11 @@ The <b>Open Data Protocol</b> (OData) is a fantastic way to query and update dat
9
9
  * Issue tracking (hosted on GitHub): https://github.com/visoft/ruby_odata/issues
10
10
  * Wiki (hosted on GitHub): http://wiki.github.com/visoft/ruby_odata/
11
11
  * Gem (hosted on Gemcutter): http://gemcutter.org/gems/ruby_odata
12
- * Blog articles: {Introducing a Ruby OData Client Library}[http://bit.ly/IntroRubyOData]
13
- {Ruby OData Update v0.0.7}[http://bit.ly/ruby_odata007]
14
- {Ruby OData Update v0.0.8}[http://bit.ly/ruby_odata008]
15
- {Ruby OData Update v0.0.10}[http://bit.ly/ruby_odata0010]
12
+ * Blog articles:
13
+ * {Introducing a Ruby OData Client Library}[http://bit.ly/IntroRubyOData]
14
+ * {Ruby OData Update v0.0.7}[http://bit.ly/ruby_odata007]
15
+ * {Ruby OData Update v0.0.8}[http://bit.ly/ruby_odata008]
16
+ * {Ruby OData Update v0.0.10}[http://bit.ly/ruby_odata0010]
16
17
 
17
18
  == Installation
18
19
  You can install ruby_odata as a gem using:
@@ -26,13 +27,14 @@ There are various options that you can pass when creating an instance of the ser
26
27
  * password: password for http basic auth
27
28
  * verify_ssl: false if no verification, otherwise mode (OpenSSL::SSL::VERIFY_PEER is default)
28
29
  * additional_params: a hash of query string params that will be passed on all calls (query, new, update, delete, batch)
30
+ * namespace: a string based namespace to create your objects in. You can specify the namespace using periods as separators (like .NET, for example <tt>VisoftInc.Sample.Models</tt>) or using double colons as separators (like Ruby <tt>VisoftInc::Sample::Models</tt>). By providing a namespace you can prevent naming collisions in your applications.
29
31
 
30
32
  === Adding
31
33
  When you point at a service, an AddTo<EntityName> method is created for you. This method takes in the new entity to create. To commit the change, you need to call the save_changes method on the service. To add a new category for example, you would simply do the following:
32
34
 
33
35
  require 'ruby_odata'
34
36
 
35
- svc = OData::Service.new "http://127.0.0.1:8989/SampleService/Entities.svc"
37
+ svc = OData::Service.new "http://127.0.0.1:8989/SampleService/RubyOData.svc"
36
38
  new_category = Category.new
37
39
  new_category.Name = "Sample Category"
38
40
  svc.AddToCategories(new_category)
@@ -44,7 +46,7 @@ To update an object, simply pass the modified object to the update_object method
44
46
 
45
47
  require 'ruby_odata'
46
48
 
47
- svc = OData::Service.new "http://127.0.0.1:8989/SampleService/Entities.svc"
49
+ svc = OData::Service.new "http://127.0.0.1:8989/SampleService/RubyOData.svc"
48
50
  new_category = Category.new
49
51
  new_category.Name = "Sample Category"
50
52
  svc.AddToCategories(new_category)
@@ -61,7 +63,7 @@ Deleting an object involves passing the tracked object to the delete_object meth
61
63
 
62
64
  require 'ruby_odata'
63
65
 
64
- svc = OData::Service.new "http://127.0.0.1:8989/SampleService/Entities.svc"
66
+ svc = OData::Service.new "http://127.0.0.1:8989/SampleService/RubyOData.svc"
65
67
  new_category = Category.new
66
68
  new_category.Name = "Sample Category"
67
69
  svc.AddToCategories(new_category)
@@ -72,12 +74,19 @@ Deleting an object involves passing the tracked object to the delete_object meth
72
74
  result = svc.save_changes
73
75
  puts "Was the category deleted? #{result}"
74
76
 
77
+ === Add Link
78
+ Adding a linkage between entities can now be performed outside of creation or modification of the objects. See the {OData documents}[http://www.odata.org/developers/protocols/operations#CreatingLinksbetweenEntries] for more details.
79
+ To add a link between entities, simply call the +add_link+ method on the Service passing the parent object, the name of the navigation property, and the child object. Like all save operations, you need to call +save_changes+ to persist the changes.
80
+
81
+ svc.add_link(<Parent>, <Navigation Property Name>, <Child>)
82
+ svc.save_changes
83
+
75
84
  === Querying
76
85
  Querying is easy, for example to pull all the categories from the SampleService, you simply can run:
77
86
 
78
87
  require 'ruby_odata'
79
88
 
80
- svc = OData::Service.new "http://127.0.0.1:8989/SampleService/Entities.svc"
89
+ svc = OData::Service.new "http://127.0.0.1:8989/SampleService/RubyOData.svc"
81
90
  svc.Categories
82
91
  categories = svc.execute
83
92
  puts categories.to_json
@@ -87,7 +96,7 @@ You can also expand, add filters, order, skip records, and take only the top X r
87
96
  === Expanding
88
97
  Expanding allows you to eagerly load other objects that are children of the root.
89
98
  You can use more than one expand on a query.
90
- For expanding grandchild and lower entities, you must pass in the full path from the root, for example +Products.expand('Orders').expand('Orders/LineItems')+
99
+ For expanding grandchild and lower entities, you must pass in the full path from the root, for example <tt>Products.expand('Orders').expand('Orders/LineItems')</tt>
91
100
 
92
101
  # Without expanding the query
93
102
  svc.Products(1)
@@ -98,9 +107,20 @@ For expanding grandchild and lower entities, you must pass in the full path from
98
107
  # With expanding the query
99
108
  svc.Products(1).expand('Category')
100
109
  prod1 = svc.execute
101
- puts "Without expanding the query"
110
+ puts "With expanding the query"
102
111
  puts "#{prod1.to_json}\n"
103
112
 
113
+ === Lazy Loading
114
+ If you want to implement lazy loading, the ruby_odata `Service` allows you to perform this. You simply need to call the `load_property` method on the `Service` passing in the object and the navigation property to fill.
115
+
116
+ # Without expanding the query
117
+ svc.Products(1)
118
+ prod1 = svc.execute.first
119
+ puts "#{prod1.to_json}\n"
120
+
121
+ # Use load_property for lazy loading
122
+ svc.load_property(prod1, "Category")
123
+ puts "#{prod1.to_json}\n"
104
124
 
105
125
  === Filtering
106
126
  The syntax for filtering can be found on the {OData Protocol URI Conventions}[http://www.odata.org/developers/protocols/uri-conventions#FilterSystemQueryOption] page.
@@ -133,7 +153,7 @@ The query operations follow a {fluent interface}[http://en.wikipedia.org/wiki/Fl
133
153
 
134
154
  === Order By
135
155
  You can order the results by properties of your choice, either ascending or descending.
136
- Order by are similar to +expand+s in that you can use more than one of them on a query.
156
+ Order by are similar to +expands+ in that you can use more than one of them on a query.
137
157
  For expanding grandchild and lower entities, you must pass in the full path from the root like would do on an +expand+
138
158
 
139
159
  svc.Products.order_by("Name")
@@ -164,38 +184,76 @@ Top allows you only retrieve the top X number of records when querying. This is
164
184
  svc.Products.top(5)
165
185
  products = svc.execute # => returns only the first 5 items
166
186
 
187
+ === Navigation Property Links Only Query
188
+ OData allows you to {query navigation properties and only return the links for the entities}[http://www.odata.org/developers/protocols/uri-conventions#AddressingLinksBetweenEntries] (instead of the data)
189
+ svc.Categories(1).links("Products")
190
+ product_links = svc.execute # => returns URIs for the products under the Category with an ID of 1
191
+
192
+ === Partial feeds
193
+ OData allows services to do server-side paging in Atom by defining a next link. The default behavior is to repeatedly consume partial feeds until the result set is complete.
194
+
195
+ svc.Partials
196
+ results = svc.execute # => retrieves all results in the Partials collection
197
+
198
+ If desired (e.g., because the result set is too large to fit in memory), explicit traversal of partial results can be requested via options:
199
+
200
+ svc = OData::Service.new "http://example.com/Example.svc", { :eager_partial => false }
201
+ svc.Partials
202
+ results = svc.execute # => retrieves the first set of results returned by the server
203
+ if svc.partial? # => true if the last result set was a partial result set (i.e., had a next link)
204
+ results.concat svc.next # => retrieves the next set of results
205
+ end
206
+ while svc.partial? # => to retrieve all partial result sets
207
+ results.concat svc.next
208
+ end
209
+
167
210
  === Authentication
168
211
  Basic HTTP Authentication is supported via sending a username and password as service constructor arguments:
169
212
 
170
213
  require 'ruby_odata'
171
214
 
172
- svc = OData::Service.new "http://127.0.0.1:8989/SampleService/Entities.svc", { :username => "bob", :password=> "12345" }
215
+ svc = OData::Service.new "http://127.0.0.1:8989/SampleService/RubyOData.svc", { :username => "bob", :password=> "12345" }
173
216
 
174
217
  === SSL/https Certificate Verification
175
218
  The certificate verification mode can be passed in the options hash via the :verify_ssl key. For example, to ignore verification in order to use a self-signed certificate:
176
219
 
177
220
  require 'ruby_odata'
178
221
 
179
- svc = OData::Service.new "https://127.0.0.1:44300/SampleService/Entities.svc", { :verify_ssl => false }
222
+ svc = OData::Service.new "https://127.0.0.1:44300/SampleService/RubyOData.svc", { :verify_ssl => false }
180
223
 
181
224
  Or an OpenSSL integer constant can be passed as well:
182
225
 
183
226
  require 'ruby_odata'
184
227
 
185
- svc = OData::Service.new "https://127.0.0.1:44300/SampleService/Entities.svc", { :verify_ssl => OpenSSL::SSL::VERIFY_PEER }
228
+ svc = OData::Service.new "https://127.0.0.1:44300/SampleService/RubyOData.svc", { :verify_ssl => OpenSSL::SSL::VERIFY_PEER }
186
229
 
187
230
  Default verification is OpenSSL::SSL::VERIFY_PEER. Note due to the way Ruby's Request object implements certificate checking, you CAN NOT pass OpenSSL::SSL::VERIFY_NONE, you must instead pass a boolean false.
188
231
 
232
+ == Function Imports / Custom Service Methods
233
+ Function Imports are custom service methods exposed by the WCF Data Service. Each function import will be created as a method on the ruby_odata Service. When you make a call to one of these, they return a result immediately without the need to call +execute+ or +save_changes+.
234
+
235
+ == Reflection
236
+ Instead of relying on looking at the EDMX directly, ruby_odata allows you to perform basic reflection on objects
237
+ === Service Level Methods
238
+ * *Collections* - You can look at the collections exposed by a service by accessing the +collections+ method, which is a hash. The key is the name of the collection and the value is the hash with +edmx_type+, which returns the name of the type from the EDMX and <tt>:type</tt>, which is the local type that is created for you
239
+ * *Classes* - To see the generated classes, you can utilize the +classes+ method on the service. The return result is a hash where the key is the class name and the value is the class type.
240
+ * <b>Function Imports</b> - You can find any function import (custom service methods) exposed by the service by accessing the +function_imports+ method. This is a hash where the key is the Function Import name and the value is metadata about the Function Import.
241
+
242
+ === Class Level Methods
243
+ * *Properties* - You can call the class method +properties+ on a generated class to see the method (properties) that were created. The returned result is a hash where the key is the property name and the value is metadata for the property like if it is nullable, the EDM Type, etc.
244
+
189
245
  == Tests
190
- All of the tests are written using Cucumber going against a sample service (Found in /test/SampleService/*). The SampleService is an ASP.NET Web Site running a SQLEXPRESS 2008 R2 Database (TestDB), as well as the ADO.NET Entity Framework and a WCF Data Service. In order to run the tests, you need to spin up the SampleService and have it running on port 8989 (http://localhost:8989/SampleService).
246
+ All of the tests are written using Cucumber going against a sample service (Found in test/RubyODataService/RubyODataService/*).
247
+ The SampleService is an ASP.NET Web Site running a SQL Compact 4 Database, which gets generated at runtime, as well as the ADO.NET Entity Framework 4.1 and WCF Data Services October 2011 CTP. The reason for the CTP is that WCF Data Services currently shipping with .NET 4 doesn't support Entity Framework 4.1's "Code First" approach (e.g. no EDMX, all POCOs)
248
+ In order to run the tests, you need to spin up IIS running a virtual directory of SampleService on port 8989 (http://localhost:8989/SampleService) and another instance running on port 44300.
191
249
 
192
- One way to do this is to open the SampleService within Visual Studio 2010 and run it from there (must use IIS instead of development web server in order for basic auth tests to pass, however). Another option is to use IIS Express. It is a free download from Microsoft. Once installed, there is a batch file found in /test called "iisExpress x64.bat", you can run the batch file and just close the command window. There is a also an "iisExpress x86.bat" file for those of you running a 32-bit machine. The only difference is the path to the Program Files directory. Once you run the batch file, the web server will spin up and you can find the instance in your systray just like if Visual Studio ran it for you. To stop the server, right click on the icon in your systray and tell it to stop.
250
+ *NOTE* The ports (8989 and 44300) and webserver (localhost by default) here are customizable thanks to <tt>/features/contants.rb</tt>. Take a look in there for the corresponding environment variables that you can set.
193
251
 
194
- Note there are also Cassini batch files that you can use as well, but the basic auth tests will fail if using this server (which doesn't support basic http authentication).
252
+ The SampleService requires IIS or IIS Express. IIS Express is a free download from Microsoft and the preferred approach to running the application. Once installed, there is a batch file found in /test called "iisExpress x64.bat" that will spin up the appropriate instances needed for the Cucumber tests. There is a also an "iisExpress x86.bat" file for those of you running a 32-bit machine. The only difference is the path to the Program Files directory. Once you run the batch file, the web server will spin up. To stop the server, use 'Q' and then enter or close the command window.
195
253
 
196
- If you are testing on a Windows machine, you may encounter a problem with using cucumber and Ruby 1.9.2. You will get a message when you fire up cucumber about missing msvcrt-ruby18.dll. The fix for this is to make sure you have the {RubyInstaller DevKit}[https://github.com/oneclick/rubyinstaller/wiki/Development-Kit] installed, then do the following:
254
+ If you are testing on a Windows machine, you may encounter a problem with using Cucumber and Ruby 1.9.2. You will get a message when you fire up cucumber about missing msvcrt-ruby18.dll. The fix for this is to make sure you have the {RubyInstaller DevKit}[https://github.com/oneclick/rubyinstaller/wiki/Development-Kit] installed, then do the following:
197
255
  gem uninstall json
198
256
  gem install json --platform=ruby -v 1.4.6
199
257
 
200
- From the BASE ruby_odata directory, run cucumber, which will execute all of the tests.
258
+ Once the SampleService is running, from the BASE ruby_odata directory, simply type +rake+, which will run the RSpec and Cucumber specs. You can also run them separately <tt>rake spec</tt> for RSpec and <tt>rake features</tt> for Cucumber.
201
259
 
@@ -1,7 +1,8 @@
1
1
  <%
2
2
  rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
3
- rerun_opts = rerun.to_s.strip.empty? ? "--format progress features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}"
4
- std_opts = "#{rerun_opts} --format rerun --out rerun.txt --strict --tags ~@wip"
3
+ rerun_opts = rerun.to_s.strip.empty? ? "--format progress features" : "--format pretty #{rerun}"
4
+ std_opts = "--format progress features --tags ~@wip"
5
5
  %>
6
- default: <%= std_opts %>
6
+ default: <%= std_opts %> features
7
7
  wip: --tags @wip:3 --wip features
8
+ rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags ~@wip
@@ -1,7 +1,7 @@
1
1
  Feature: Service Should Access Basic Auth Protected Resources
2
2
 
3
3
  Background:
4
- Given an ODataService exists with uri: "http://localhost:8989/SampleService/BasicAuth/Entities.svc" using username "admin" and password "passwd"
4
+ Given a HTTP BasicAuth ODataService exists using username "admin" and password "passwd"
5
5
  And blueprints exist for the service
6
6
 
7
7
  Scenario: Service should respond to valid collections
@@ -12,13 +12,11 @@ Scenario: Entity should fill values on protected resource
12
12
  And I save changes
13
13
  And I call "Categories" on the service with args: "1"
14
14
  When I run the query
15
- Then the method "Id" on the result should equal: "1"
16
- And the method "Name" on the result should equal: "Auth Test Category"
15
+ Then the method "Id" on the first result should equal: "1"
16
+ And the method "Name" on the first result should equal: "Auth Test Category"
17
17
 
18
18
  Scenario: Should get 401 if invalid credentials provided to protected URL
19
- Given an ODataService exists with uri: "http://localhost:8989/SampleService/BasicAuth/Entities.svc" using username "admin" and password "bad_pwd" it should throw an exception with message "401 Unauthorized"
19
+ Given a HTTP BasicAuth ODataService exists using username "admin" and password "bad_pwd" it should throw an exception with message "401 Unauthorized"
20
20
 
21
21
  Scenario: Should get 401 if no credentials provided to protected URL
22
- Given an ODataService exists with uri: "http://localhost:8989/SampleService/BasicAuth/Entities.svc" it should throw an exception with message "401 Unauthorized"
23
-
24
-
22
+ Given a HTTP BasicAuth ODataService exists it should throw an exception with message "401 Unauthorized"
@@ -4,7 +4,7 @@ Feature: Batch request
4
4
  I want to be able to batch changes (Add/Update/Delete) and persist the batch instead of one at a time
5
5
 
6
6
  Background:
7
- Given a sample HTTP ODataService exists
7
+ Given a HTTP ODataService exists
8
8
  And blueprints exist for the service
9
9
 
10
10
  Scenario: Save Changes should allow for batch additions
@@ -27,13 +27,13 @@ Scenario: Save Changes should allow for batch updates
27
27
  When I call "Products" on the service
28
28
  And I filter the query with: "Name eq 'Product 1'"
29
29
  And I run the query
30
- And I set "Name" on the result to "Product 1 - Updated"
31
- And I call "update_object" on the service with the last query result
30
+ And I set "Name" on the first result to "Product 1 - Updated"
31
+ And I call "update_object" on the service with the first last query result
32
32
  When I call "Products" on the service
33
33
  And I filter the query with: "Name eq 'Product 2'"
34
34
  And I run the query
35
- And I set "Name" on the result to "Product 2 - Updated"
36
- And I call "update_object" on the service with the last query result
35
+ And I set "Name" on the first result to "Product 2 - Updated"
36
+ And I call "update_object" on the service with the first last query result
37
37
  When I save changes
38
38
  When I call "Products" on the service
39
39
  And I order by: "Name"
@@ -52,11 +52,11 @@ Scenario: Save Changes should allow for batch deletes
52
52
  When I call "Products" on the service
53
53
  And I filter the query with: "Name eq 'Product 2'"
54
54
  And I run the query
55
- And I call "delete_object" on the service with the last query result
55
+ And I call "delete_object" on the service with the first last query result
56
56
  When I call "Products" on the service
57
57
  And I filter the query with: "Name eq 'Product 3'"
58
58
  And I run the query
59
- And I call "delete_object" on the service with the last query result
59
+ And I call "delete_object" on the service with the first last query result
60
60
  When I save changes
61
61
  When I call "Products" on the service
62
62
  And I order by: "Name"
@@ -67,7 +67,7 @@ Scenario: Save Changes should allow for batch deletes
67
67
  | Product 4 |
68
68
 
69
69
  Scenario: Save Changes should allow for a mix of adds, updates, and deletes to be batched
70
- Given the following Products exist:
70
+ Given the following products exist:
71
71
  | Name |
72
72
  | Product 1 |
73
73
  | Product 2 |
@@ -76,12 +76,12 @@ Scenario: Save Changes should allow for a mix of adds, updates, and deletes to b
76
76
  When I call "Products" on the service
77
77
  And I filter the query with: "Name eq 'Product 1'"
78
78
  And I run the query
79
- And I set "Name" on the result to "Product 1 - Updated"
80
- And I call "update_object" on the service with the last query result
79
+ And I set "Name" on the first result to "Product 1 - Updated"
80
+ And I call "update_object" on the service with the first last query result
81
81
  When I call "Products" on the service
82
82
  And I filter the query with: "Name eq 'Product 2'"
83
83
  And I run the query
84
- And I call "delete_object" on the service with the last query result
84
+ And I call "delete_object" on the service with the first last query result
85
85
  When I save changes
86
86
  When I call "Products" on the service
87
87
  And I order by: "Name"
@@ -4,7 +4,7 @@ Feature: Complex types
4
4
  I want to be able to manage objects with complex types
5
5
 
6
6
  Background:
7
- Given a sample HTTP ODataService exists
7
+ Given a HTTP ODataService exists
8
8
  And blueprints exist for the service
9
9
 
10
10
  Scenario: The proxy must generate classes for complex types if they exist
@@ -15,16 +15,16 @@ Scenario: Complex properties on an entity must be the correct type
15
15
  And I save changes
16
16
  And I call "Products" on the service with args: "1"
17
17
  When I run the query
18
- Then the result should have a method: "AuditFields"
19
- And the method "AuditFields" on the result should be of type "AuditFields"
18
+ Then the first result should have a method: "AuditFields"
19
+ And the method "AuditFields" on the first result should be of type "AuditFields"
20
20
 
21
21
  Scenario: Complex properties on an entity must be filled
22
22
  Given I call "AddToProducts" on the service with a new "Product" object
23
23
  And I save changes
24
24
  And I call "Products" on the service with args: "1"
25
25
  When I run the query
26
- Then the result should have a method: "AuditFields"
27
- When I call "CreateDate" for "AuditFields" on the result
26
+ Then the first result should have a method: "AuditFields"
27
+ When I call "CreateDate" for "AuditFields" on the first result
28
28
  Then the operation should not be null
29
29
 
30
30
  # TODO: This scenario should have the AuditFields.CreatedBy field set in the Given
@@ -34,19 +34,19 @@ Scenario: Complex properties should be able to be added
34
34
  And I save changes
35
35
  And I call "Products" on the service with args: "1"
36
36
  When I run the query
37
- Then the method "CreatedBy" on the result's method "AuditFields" should equal: "Cucumber"
38
-
39
- Scenario: Complex propertis should be able to be updated
37
+ Then the method "CreatedBy" on the first result's method "AuditFields" should equal: "Machinist"
38
+
39
+ Scenario: Complex properties should be able to be updated
40
40
  Given I call "AddToProducts" on the service with a new "Product" object
41
41
  And I save changes
42
42
  And I call "Products" on the service with args: "1"
43
43
  When I run the query
44
- When I set "CreatedBy" on the result's method "AuditFields" to "This Test"
45
- And I call "update_object" on the service with the last query result
44
+ When I set "CreatedBy" on the first result's method "AuditFields" to "This Test"
45
+ And I call "update_object" on the service with the first last query result
46
46
  And I save changes
47
47
  Then the save result should equal: "true"
48
48
  When I call "Products" on the service with args: "1"
49
49
  And I run the query
50
- Then the method "CreatedBy" on the result's method "AuditFields" should equal: "This Test"
50
+ Then the method "CreatedBy" on the first result's method "AuditFields" should equal: "This Test"
51
51
 
52
52
 
@@ -4,21 +4,21 @@ Feature: Query Builder
4
4
  I want to be able to perform valid OData protocol operations
5
5
 
6
6
  Background:
7
- Given a sample HTTP ODataService exists
7
+ Given a HTTP ODataService exists
8
8
  And blueprints exist for the service
9
9
 
10
- # Expand
10
+ # Expand
11
11
  Scenario: Navigation Properties should be able to be eager loaded
12
12
  Given I call "AddToCategories" on the service with a new "Category" object with Name: "Test Category"
13
13
  And I save changes
14
- And I call "AddToProducts" on the service with a new "Product" object with Category: "@@LastSave"
14
+ And I call "AddToProducts" on the service with a new "Product" object with Category: "@@LastSave.first"
15
15
  And I save changes
16
16
  And I call "Products" on the service with args: "1"
17
17
  And I expand the query to include "Category"
18
18
  When I run the query
19
- Then the method "Category" on the result should be of type "Category"
20
- And the method "Name" on the result's method "Category" should equal: "Test Category"
21
- And the method "Id" on the result's method "Category" should equal: "1"
19
+ Then the method "Category" on the first result should be of type "Category"
20
+ And the method "Name" on the first result's method "Category" should equal: "Test Category"
21
+ And the method "Id" on the first result's method "Category" should equal: "1"
22
22
 
23
23
 
24
24
  # Filters
@@ -29,12 +29,12 @@ Scenario: Filters should be allowed on the root level entity
29
29
  When I call "Products" on the service
30
30
  And I filter the query with: "Name eq 'Test Product'"
31
31
  And I run the query
32
- Then the method "Name" on the result should equal: "Test Product"
32
+ Then the method "Name" on the first result should equal: "Test Product"
33
33
 
34
34
 
35
35
  # Order By
36
36
  Scenario: Order by should be allowed on the root level entity
37
- Given the following Products exist:
37
+ Given the following products exist:
38
38
  | Name |
39
39
  | Product 2 |
40
40
  | Product 4 |
@@ -53,7 +53,7 @@ Scenario: Order by should be allowed on the root level entity
53
53
  | Product 5 |
54
54
 
55
55
  Scenario: Order by should accept sorting descending
56
- Given the following Products exist:
56
+ Given the following products exist:
57
57
  | Name |
58
58
  | Product 2 |
59
59
  | Product 4 |
@@ -72,7 +72,7 @@ Scenario: Order by should accept sorting descending
72
72
  | Product 1 |
73
73
 
74
74
  Scenario: Order by should access sorting acsending
75
- Given the following Products exist:
75
+ Given the following products exist:
76
76
  | Name |
77
77
  | Product 2 |
78
78
  | Product 4 |
@@ -93,7 +93,7 @@ Scenario: Order by should access sorting acsending
93
93
 
94
94
  # Skip
95
95
  Scenario: Skip should be allowed on the root level entity
96
- Given the following Products exist:
96
+ Given the following products exist:
97
97
  | Name |
98
98
  | Product 1 |
99
99
  | Product 2 |
@@ -111,7 +111,7 @@ Scenario: Skip should be allowed on the root level entity
111
111
 
112
112
  # Top
113
113
  Scenario: Top should be allowed on the root level entity
114
- Given the following Products exist:
114
+ Given the following products exist:
115
115
  | Name |
116
116
  | Product 1 |
117
117
  | Product 2 |
@@ -128,7 +128,7 @@ Scenario: Top should be allowed on the root level entity
128
128
  | Product 3 |
129
129
 
130
130
  Scenario: Top should be able to be used along with skip for paging
131
- Given the following Products exist:
131
+ Given the following products exist:
132
132
  | Name |
133
133
  | Product 1 |
134
134
  | Product 2 |
@@ -146,8 +146,17 @@ Scenario: Top should be able to be used along with skip for paging
146
146
  | Product 4 |
147
147
 
148
148
 
149
-
150
-
151
-
152
-
153
-
149
+ # Links
150
+ Scenario: Navigation Properties should be able to represented as links
151
+ Given a category: "cat1" exists with Name: "Test Category"
152
+ And I save changes
153
+ And the following products exist:
154
+ | Name | Category |
155
+ | Product 1 | category: "cat1" |
156
+ | Product 2 | category: "cat1" |
157
+ | Product 3 | category: "cat1" |
158
+ When I call "Categories" on the service with args: "1"
159
+ And I ask for the links for "Products"
160
+ And I run the query
161
+ Then the result count should be 3
162
+ Then the method "path" on the first result should equal: "/SampleService/RubyOData.svc/Products(1)"