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.
- data/.gitignore +9 -3
- data/.travis.yml +4 -0
- data/CHANGELOG.rdoc +18 -1
- data/README.rdoc +77 -19
- data/config/cucumber.yml +4 -3
- data/features/basic_auth.feature +5 -7
- data/features/batch_request.feature +11 -11
- data/features/complex_types.feature +11 -11
- data/features/query_builder.feature +27 -18
- data/features/service.feature +8 -8
- data/features/service_manage.feature +27 -12
- data/features/service_methods.feature +37 -0
- data/features/ssl.feature +4 -4
- data/features/step_definitions/pickle_steps.rb +100 -0
- data/features/step_definitions/service_steps.rb +99 -65
- data/features/support/constants.rb +3 -0
- data/features/support/custom_helpers.rb +54 -0
- data/features/support/env.rb +0 -10
- data/features/support/hooks.rb +1 -1
- data/features/support/pickle.rb +82 -0
- data/features/type_conversion.feature +10 -10
- data/lib/ruby_odata.rb +4 -1
- data/lib/ruby_odata/association.rb +36 -0
- data/lib/ruby_odata/class_builder.rb +96 -16
- data/lib/ruby_odata/helpers.rb +10 -0
- data/lib/ruby_odata/operation.rb +7 -5
- data/lib/ruby_odata/property_metadata.rb +11 -6
- data/lib/ruby_odata/query_builder.rb +20 -1
- data/lib/ruby_odata/service.rb +407 -94
- data/lib/ruby_odata/version.rb +1 -1
- data/ruby_odata.gemspec +2 -0
- data/spec/association_spec.rb +48 -0
- data/spec/class_builder_spec.rb +11 -2
- data/spec/fixtures/inheritance/edmx_pluralsight.xml +111 -0
- data/spec/fixtures/inheritance/result_pluralsight_courses.xml +229 -0
- data/spec/fixtures/links/result_links_query.xml +6 -0
- data/spec/fixtures/partial/partial_feed_metadata.xml +25 -0
- data/spec/fixtures/partial/partial_feed_part_1.xml +42 -0
- data/spec/fixtures/partial/partial_feed_part_2.xml +42 -0
- data/spec/fixtures/partial/partial_feed_part_3.xml +40 -0
- data/spec/fixtures/sample_service/edmx_categories_products.xml +1 -0
- data/spec/fixtures/sample_service/result_category_names.xml +5 -0
- data/spec/fixtures/sample_service/result_entity_category_web_get.xml +29 -0
- data/spec/fixtures/sample_service/result_entity_single_category_web_get.xml +23 -0
- data/spec/fixtures/sample_service/result_first_category_id.xml +2 -0
- data/spec/fixtures/sample_service/result_multiple_category_products.xml +57 -0
- data/spec/fixtures/sample_service/result_single_category.xml +18 -0
- data/spec/fixtures/sample_service/result_single_product.xml +26 -0
- data/spec/fixtures/sample_service/result_single_product_not_found.xml +4 -0
- data/spec/fixtures/sap/edmx_sap_demo_flight.xml +62 -58
- data/spec/property_metadata_spec.rb +9 -2
- data/spec/query_builder_spec.rb +11 -0
- data/spec/revised_service_spec.rb +197 -0
- data/spec/service_spec.rb +463 -4
- data/test/RubyODataService/RubyODataService.sln +20 -0
- data/test/RubyODataService/RubyODataService/App_Start/EntityFramework.SqlServerCompact.cs +12 -0
- data/test/RubyODataService/RubyODataService/BasicAuth/RubyOData.svc +3 -0
- data/test/RubyODataService/RubyODataService/BasicAuth/RubyOData.svc.cs +107 -0
- data/test/RubyODataService/RubyODataService/Global.asax +1 -0
- data/test/RubyODataService/RubyODataService/Global.asax.cs +49 -0
- data/test/RubyODataService/RubyODataService/Models/AuditFields.cs +16 -0
- data/test/RubyODataService/RubyODataService/Models/Category.cs +16 -0
- data/test/RubyODataService/RubyODataService/Models/Product.cs +20 -0
- data/test/RubyODataService/RubyODataService/Properties/AssemblyInfo.cs +35 -0
- data/test/RubyODataService/RubyODataService/RubyOData.svc +3 -0
- data/test/RubyODataService/RubyODataService/RubyOData.svc.cs +57 -0
- data/test/RubyODataService/RubyODataService/RubyODataContext.cs +16 -0
- data/test/RubyODataService/RubyODataService/RubyODataService.csproj +159 -0
- data/test/RubyODataService/RubyODataService/RubyODataService.csproj.user +31 -0
- data/test/RubyODataService/RubyODataService/Web.Debug.config +30 -0
- data/test/RubyODataService/RubyODataService/Web.Release.config +31 -0
- data/test/RubyODataService/RubyODataService/Web.config +27 -0
- data/test/RubyODataService/RubyODataService/bin/EntityFramework.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/Microsoft.Data.Edm.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/Microsoft.Data.OData.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/Microsoft.Data.Services.Client.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/Microsoft.Data.Services.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/Microsoft.Data.Spatial.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/RubyODataService.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/System.Data.SqlServerCe.Entity.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/System.Data.SqlServerCe.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/System.Spatial.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/WebActivator.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/amd64/Microsoft.VC90.CRT/Microsoft.VC90.CRT.manifest +6 -0
- data/test/RubyODataService/RubyODataService/bin/amd64/Microsoft.VC90.CRT/README_ENU.txt +0 -0
- data/test/RubyODataService/RubyODataService/bin/amd64/Microsoft.VC90.CRT/msvcr90.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/amd64/sqlcecompact40.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/amd64/sqlceer40EN.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/amd64/sqlceme40.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/amd64/sqlceqp40.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/amd64/sqlcese40.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/x86/Microsoft.VC90.CRT/Microsoft.VC90.CRT.manifest +6 -0
- data/test/RubyODataService/RubyODataService/bin/x86/Microsoft.VC90.CRT/README_ENU.txt +0 -0
- data/test/RubyODataService/RubyODataService/bin/x86/Microsoft.VC90.CRT/msvcr90.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/x86/sqlcecompact40.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/x86/sqlceer40EN.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/x86/sqlceme40.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/x86/sqlceqp40.dll +0 -0
- data/test/RubyODataService/RubyODataService/bin/x86/sqlcese40.dll +0 -0
- data/test/RubyODataService/RubyODataService/packages.config +7 -0
- data/test/RubyODataService/packages/EntityFramework.4.2.0.0/EntityFramework.4.2.0.0.nupkg +0 -0
- data/test/RubyODataService/packages/EntityFramework.4.2.0.0/lib/net40/EntityFramework.dll +0 -0
- data/test/RubyODataService/packages/EntityFramework.4.2.0.0/lib/net40/EntityFramework.xml +13488 -0
- data/test/RubyODataService/packages/EntityFramework.SqlServerCompact.4.1.8482.2/Content/App_Start/EntityFramework.SqlServerCompact.cs.pp +12 -0
- data/test/RubyODataService/packages/EntityFramework.SqlServerCompact.4.1.8482.2/EULA_ENU.rtf +969 -0
- data/test/RubyODataService/packages/EntityFramework.SqlServerCompact.4.1.8482.2/EntityFramework.SqlServerCompact.4.1.8482.2.nupkg +0 -0
- data/test/RubyODataService/packages/EntityFramework.SqlServerCompact.4.1.8482.2/lib/System.Data.SqlServerCe.Entity.dll +0 -0
- data/test/RubyODataService/packages/EntityFramework.SqlServerCompact.4.1.8482.2/tools/install.ps1 +3 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/Content/web.config.transform +8 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/amd64/Microsoft.VC90.CRT/Microsoft.VC90.CRT.manifest +6 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/amd64/Microsoft.VC90.CRT/README_ENU.txt +0 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/amd64/Microsoft.VC90.CRT/msvcr90.dll +0 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/amd64/sqlcecompact40.dll +0 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/amd64/sqlceer40EN.dll +0 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/amd64/sqlceme40.dll +0 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/amd64/sqlceqp40.dll +0 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/amd64/sqlcese40.dll +0 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/x86/Microsoft.VC90.CRT/Microsoft.VC90.CRT.manifest +6 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/x86/Microsoft.VC90.CRT/README_ENU.txt +0 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/x86/Microsoft.VC90.CRT/msvcr90.dll +0 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/x86/sqlcecompact40.dll +0 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/x86/sqlceer40EN.dll +0 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/x86/sqlceme40.dll +0 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/x86/sqlceqp40.dll +0 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/NativeBinaries/x86/sqlcese40.dll +0 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/SQLCE_EULA_ENU.rtf +778 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/SqlServerCompact.4.0.8482.1.nupkg +0 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/Tools/GetSqlCEPostBuildCmd.ps1 +12 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/Tools/install.ps1 +11 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/Tools/uninstall.ps1 +9 -0
- data/test/RubyODataService/packages/SqlServerCompact.4.0.8482.1/lib/System.Data.SqlServerCe.dll +0 -0
- data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/DataSvcUtil.exe +0 -0
- data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/License.rtf +708 -0
- data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.Edm.dll +0 -0
- data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.Edm.xml +4150 -0
- data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.OData.dll +0 -0
- data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.OData.xml +1969 -0
- data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.Services.Client.dll +0 -0
- data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.Services.Client.xml +1442 -0
- data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.Services.Design.dll +0 -0
- data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.Services.Design.xml +191 -0
- data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.Services.dll +0 -0
- data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.Services.xml +2559 -0
- data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.Spatial.dll +0 -0
- data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.Data.Spatial.xml +15 -0
- data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/Microsoft.VsDesigner.DataServices.Adapter.dll +0 -0
- data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/README.txt +6 -0
- data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/System.Spatial.dll +0 -0
- data/test/RubyODataService/packages/WCF DataServices October 2011 CTP/System.Spatial.xml +2276 -0
- data/test/RubyODataService/packages/WebActivator.1.0.0.0/WebActivator.1.0.0.0.nupkg +0 -0
- data/test/RubyODataService/packages/WebActivator.1.0.0.0/lib/WebActivator.dll +0 -0
- data/test/RubyODataService/packages/repositories.config +4 -0
- data/test/applicationhost.config.template +2 -2
- data/test/blueprints.rb +5 -4
- data/test/iisExpress x64.bat b/data/test/iisExpress → x64.bat +0 -0
- data/test/iisExpress x86.bat b/data/test/iisExpress → x86.bat +0 -0
- data/test/setpath.rb +13 -3
- data/test/usage_samples/querying.rb +45 -0
- data/test/usage_samples/reflection.rb +16 -0
- data/test/usage_samples/sample_data.rb +30 -0
- metadata +327 -36
- data/test/Cassini x64.bat +0 -1
- data/test/Cassini x86.bat +0 -1
- data/test/SampleService/App_Code/AuditFields.cs +0 -13
- data/test/SampleService/App_Code/Entities.cs +0 -145
- data/test/SampleService/App_Code/Model.Designer.cs +0 -578
- data/test/SampleService/App_Code/Model.edmx +0 -157
- data/test/SampleService/App_Code/ModelContainerExtended.cs +0 -32
- data/test/SampleService/App_Data/_TestDB.mdf +0 -0
- data/test/SampleService/App_Data/_TestDB_Log.ldf +0 -0
- data/test/SampleService/BasicAuth/Entities.svc +0 -1
- data/test/SampleService/Entities.svc +0 -1
- 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
|
data/.travis.yml
ADDED
data/CHANGELOG.rdoc
CHANGED
@@ -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
|
data/README.rdoc
CHANGED
@@ -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:
|
13
|
-
|
14
|
-
|
15
|
-
|
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/
|
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/
|
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/
|
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/
|
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
|
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 "
|
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 +
|
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/
|
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/
|
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/
|
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
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
|
data/config/cucumber.yml
CHANGED
@@ -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
|
4
|
-
std_opts = "
|
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
|
data/features/basic_auth.feature
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Feature: Service Should Access Basic Auth Protected Resources
|
2
2
|
|
3
3
|
Background:
|
4
|
-
Given
|
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
|
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
|
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
|
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
|
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
|
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: "
|
38
|
-
|
39
|
-
Scenario: Complex
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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)"
|