ruby_odata 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -1
- data/CHANGELOG.rdoc +46 -38
- data/Gemfile +4 -0
- data/LICENSE +24 -24
- data/README.rdoc +179 -153
- data/Rakefile +10 -28
- data/features/basic_auth.feature +24 -0
- data/features/batch_request.feature +94 -94
- data/features/complex_types.feature +52 -52
- data/features/query_builder.feature +153 -153
- data/features/service.feature +49 -49
- data/features/service_manage.feature +54 -44
- data/features/step_definitions/service_steps.rb +255 -243
- data/features/support/env.rb +14 -4
- data/features/support/hooks.rb +3 -3
- data/features/type_conversion.feature +53 -45
- data/lib/ruby_odata.rb +17 -17
- data/lib/ruby_odata/class_builder.rb +117 -109
- data/lib/ruby_odata/operation.rb +17 -17
- data/lib/ruby_odata/query_builder.rb +106 -106
- data/lib/ruby_odata/service.rb +359 -339
- data/lib/ruby_odata/version.rb +3 -0
- data/ruby_odata.gemspec +24 -78
- data/test/SampleService/App_Code/Entities.cs +105 -2
- data/test/SampleService/App_Code/Model.Designer.cs +24 -0
- data/test/SampleService/App_Code/Model.edmx +3 -0
- 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 +1 -0
- data/test/SampleService/web.config +11 -1
- data/test/blueprints.rb +20 -20
- data/test/iisExpress x64.bat +1 -0
- data/test/iisExpress x86.bat +1 -0
- metadata +88 -14
- data/VERSION +0 -1
data/features/support/env.rb
CHANGED
@@ -1,4 +1,14 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require '
|
4
|
-
require '
|
1
|
+
lib = File.expand_path(File.join(File.dirname(__FILE__), "../..", "lib"))
|
2
|
+
|
3
|
+
require lib + '/ruby_odata'
|
4
|
+
require 'machinist/object'
|
5
|
+
require 'sham'
|
6
|
+
require 'faker'
|
7
|
+
|
8
|
+
require 'fileutils'
|
9
|
+
root_dir = File.expand_path(File.join(File.dirname(__FILE__), "../..", "test/SampleService/App_Data"))
|
10
|
+
|
11
|
+
if !File.exists?("#{root_dir}/TestDB.mdf")
|
12
|
+
FileUtils.copy("#{root_dir}/_TestDB.mdf", "#{root_dir}/TestDB.mdf")
|
13
|
+
FileUtils.copy("#{root_dir}/_TestDB_Log.ldf", "#{root_dir}/TestDB_Log.ldf")
|
14
|
+
end
|
data/features/support/hooks.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Before do
|
2
|
-
|
3
|
-
|
1
|
+
Before do
|
2
|
+
Sham.reset
|
3
|
+
RestClient.post "http://localhost:8888/SampleService/Entities.svc/CleanDatabaseForTesting", {}
|
4
4
|
end
|
@@ -1,45 +1,53 @@
|
|
1
|
-
Feature: Type conversion
|
2
|
-
In order to accurately perform operations
|
3
|
-
As a user of the API
|
4
|
-
I want types returned to be accurately represented
|
5
|
-
|
6
|
-
Background:
|
7
|
-
Given an ODataService exists with uri: "http://localhost:8888/SampleService/Entities.svc"
|
8
|
-
And blueprints exist for the service
|
9
|
-
|
10
|
-
Scenario: Integers should be Fixnums
|
11
|
-
Given I call "AddToProducts" on the service with a new "Product" object
|
12
|
-
And I save changes
|
13
|
-
When I call "Products" on the service
|
14
|
-
And I run the query
|
15
|
-
Then the "Id" method should return a Fixnum
|
16
|
-
|
17
|
-
Scenario: Decimals should be BigDecimals
|
18
|
-
Given I call "AddToProducts" on the service with a new "Product" object
|
19
|
-
And I save changes
|
20
|
-
When I call "Products" on the service
|
21
|
-
And I run the query
|
22
|
-
Then the "Price" method should return a BigDecimal
|
23
|
-
|
24
|
-
Scenario: DateTimes should be Times
|
25
|
-
Given I call "AddToProducts" on the service with a new "Product" object
|
26
|
-
And I save changes
|
27
|
-
When I call "Products" on the service
|
28
|
-
And I run the query
|
29
|
-
Then the "AuditFields.CreateDate" method should return a Time
|
30
|
-
|
31
|
-
Scenario: Verify that DateTimes don't change if not modified on an update
|
32
|
-
Given I call "AddToProducts" on the service with a new "Product" object with Name: "Test Product"
|
33
|
-
When I save changes
|
34
|
-
And I call "Products" on the service with args: "1"
|
35
|
-
And I run the query
|
36
|
-
Then I store the last query result for comparison
|
37
|
-
When I set "Name" on the result to "Changed Test Product"
|
38
|
-
Then the method "Name" on the result should equal: "Changed Test Product"
|
39
|
-
And I call "update_object" on the service with the last query result
|
40
|
-
And I save changes
|
41
|
-
Then the save result should equal: "true"
|
42
|
-
When I call "Products" on the service with args: "1"
|
43
|
-
And I run the query
|
44
|
-
Then the new query result's time "AuditFields.CreateDate" should equal the saved query result
|
45
|
-
|
1
|
+
Feature: Type conversion
|
2
|
+
In order to accurately perform operations
|
3
|
+
As a user of the API
|
4
|
+
I want types returned to be accurately represented
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given an ODataService exists with uri: "http://localhost:8888/SampleService/Entities.svc"
|
8
|
+
And blueprints exist for the service
|
9
|
+
|
10
|
+
Scenario: Integers should be Fixnums
|
11
|
+
Given I call "AddToProducts" on the service with a new "Product" object
|
12
|
+
And I save changes
|
13
|
+
When I call "Products" on the service
|
14
|
+
And I run the query
|
15
|
+
Then the "Id" method should return a Fixnum
|
16
|
+
|
17
|
+
Scenario: Decimals should be BigDecimals
|
18
|
+
Given I call "AddToProducts" on the service with a new "Product" object
|
19
|
+
And I save changes
|
20
|
+
When I call "Products" on the service
|
21
|
+
And I run the query
|
22
|
+
Then the "Price" method should return a BigDecimal
|
23
|
+
|
24
|
+
Scenario: DateTimes should be Times
|
25
|
+
Given I call "AddToProducts" on the service with a new "Product" object
|
26
|
+
And I save changes
|
27
|
+
When I call "Products" on the service
|
28
|
+
And I run the query
|
29
|
+
Then the "AuditFields.CreateDate" method should return a Time
|
30
|
+
|
31
|
+
Scenario: Verify that DateTimes don't change if not modified on an update
|
32
|
+
Given I call "AddToProducts" on the service with a new "Product" object with Name: "Test Product"
|
33
|
+
When I save changes
|
34
|
+
And I call "Products" on the service with args: "1"
|
35
|
+
And I run the query
|
36
|
+
Then I store the last query result for comparison
|
37
|
+
When I set "Name" on the result to "Changed Test Product"
|
38
|
+
Then the method "Name" on the result should equal: "Changed Test Product"
|
39
|
+
And I call "update_object" on the service with the last query result
|
40
|
+
And I save changes
|
41
|
+
Then the save result should equal: "true"
|
42
|
+
When I call "Products" on the service with args: "1"
|
43
|
+
And I run the query
|
44
|
+
Then the new query result's time "AuditFields.CreateDate" should equal the saved query result
|
45
|
+
|
46
|
+
Scenario: DateTimes should be able to be null
|
47
|
+
Given I call "AddToProducts" on the service with a new "Product" object
|
48
|
+
And I save changes
|
49
|
+
When I call "Products" on the service
|
50
|
+
And I run the query
|
51
|
+
Then the "DiscontinuedDate" method should return a NilClass
|
52
|
+
|
53
|
+
|
data/lib/ruby_odata.rb
CHANGED
@@ -1,18 +1,18 @@
|
|
1
|
-
lib = File.dirname(__FILE__)
|
2
|
-
|
3
|
-
$: << lib + '/ruby_odata/'
|
4
|
-
require 'rubygems'
|
5
|
-
require 'active_support' # Used for serializtion to JSON
|
6
|
-
require 'active_support/inflector'
|
7
|
-
require 'active_support/core_ext'
|
8
|
-
require 'cgi'
|
9
|
-
require 'open-uri'
|
10
|
-
require 'rest_client'
|
11
|
-
require 'nokogiri'
|
12
|
-
require 'bigdecimal'
|
13
|
-
require 'bigdecimal/util'
|
14
|
-
|
15
|
-
require lib + '/ruby_odata/query_builder'
|
16
|
-
require lib + '/ruby_odata/class_builder'
|
17
|
-
require lib + '/ruby_odata/operation'
|
1
|
+
lib = File.dirname(__FILE__)
|
2
|
+
|
3
|
+
$: << lib + '/ruby_odata/'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'active_support' # Used for serializtion to JSON
|
6
|
+
require 'active_support/inflector'
|
7
|
+
require 'active_support/core_ext'
|
8
|
+
require 'cgi'
|
9
|
+
require 'open-uri'
|
10
|
+
require 'rest_client'
|
11
|
+
require 'nokogiri'
|
12
|
+
require 'bigdecimal'
|
13
|
+
require 'bigdecimal/util'
|
14
|
+
|
15
|
+
require lib + '/ruby_odata/query_builder'
|
16
|
+
require lib + '/ruby_odata/class_builder'
|
17
|
+
require lib + '/ruby_odata/operation'
|
18
18
|
require lib + '/ruby_odata/service'
|
@@ -1,109 +1,117 @@
|
|
1
|
-
module OData
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
1
|
+
module OData
|
2
|
+
# Internally used helper class for building a dynamic class. This class shouldn't be called directly.
|
3
|
+
class ClassBuilder
|
4
|
+
# Creates a new instance of the ClassBuilder class
|
5
|
+
#
|
6
|
+
# ==== Required Attributes
|
7
|
+
# - klass_name: The name/type of the class to create
|
8
|
+
# - methods: The accessor methods to add to the class
|
9
|
+
# - nav_props: The accessor methods to add for navigation properties
|
10
|
+
def initialize(klass_name, methods, nav_props)
|
11
|
+
@klass_name = klass_name
|
12
|
+
@methods = methods
|
13
|
+
@nav_props = nav_props
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns a dynamically generated class definition based on the constructor parameters
|
17
|
+
def build
|
18
|
+
# return if already built
|
19
|
+
return @klass unless @klass.nil?
|
20
|
+
|
21
|
+
# need the class name to build class
|
22
|
+
return nil if @klass_name.nil?
|
23
|
+
|
24
|
+
# return if we can find constant corresponding to class name
|
25
|
+
if Object.const_defined? @klass_name
|
26
|
+
@klass = @klass_name.constantize
|
27
|
+
return @klass
|
28
|
+
end
|
29
|
+
|
30
|
+
Object.const_set(@klass_name, Class.new.extend(ActiveSupport::JSON))
|
31
|
+
@klass = @klass_name.constantize
|
32
|
+
@klass.class_eval do
|
33
|
+
include OData
|
34
|
+
end
|
35
|
+
|
36
|
+
add_methods(@klass)
|
37
|
+
add_nav_props(@klass)
|
38
|
+
|
39
|
+
return @klass
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
def add_methods(klass)
|
44
|
+
# Add metadata methods
|
45
|
+
klass.send :define_method, :__metadata do
|
46
|
+
instance_variable_get("@__metadata")
|
47
|
+
end
|
48
|
+
klass.send :define_method, :__metadata= do |value|
|
49
|
+
instance_variable_set("@__metadata", value)
|
50
|
+
end
|
51
|
+
klass.send :define_method, :as_json do |*args|
|
52
|
+
meta = RUBY_VERSION < "1.9" ? '@__metadata' :'@__metadata'.to_sym
|
53
|
+
|
54
|
+
options = args[0] || {}
|
55
|
+
options[:type] ||= :unknown
|
56
|
+
|
57
|
+
vars = self.instance_values
|
58
|
+
|
59
|
+
# For adds, we need to get rid of all attributes except __metadata when passing
|
60
|
+
# the object to the server
|
61
|
+
if(options[:type] == :add)
|
62
|
+
vars.each_value do |value|
|
63
|
+
if value.is_a? OData
|
64
|
+
child_vars = value.instance_variables
|
65
|
+
if(child_vars.include?(meta))
|
66
|
+
child_vars.each do |var|
|
67
|
+
value.send :remove_instance_variable, var if var != meta
|
68
|
+
end
|
69
|
+
else
|
70
|
+
value.send :remove_instance_variable, meta if value.instance_variable_defined? meta
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Convert a BigDecimal to a string for serialization (to match Edm.Decimal)
|
77
|
+
decimals = vars.find_all { |o| o[1].class == BigDecimal } || []
|
78
|
+
decimals.each do |d|
|
79
|
+
vars[d[0]] = d[1].to_s
|
80
|
+
end
|
81
|
+
|
82
|
+
# Convert Time to an RFC3339 string for serialization
|
83
|
+
times = vars.find_all { |o| o[1].class == Time } || []
|
84
|
+
times.each do |t|
|
85
|
+
sdate = t[1].xmlschema(3)
|
86
|
+
# Remove the ending Z (indicating UTC).
|
87
|
+
# If the Z is there when saving, the time is converted to local time on the server
|
88
|
+
sdate.chop! if sdate.match(/Z$/)
|
89
|
+
vars[t[0]] = sdate
|
90
|
+
end
|
91
|
+
|
92
|
+
vars
|
93
|
+
end
|
94
|
+
|
95
|
+
# Add the methods that were passed in
|
96
|
+
@methods.each do |method_name|
|
97
|
+
klass.send :define_method, method_name do
|
98
|
+
instance_variable_get("@#{method_name}")
|
99
|
+
end
|
100
|
+
klass.send :define_method, "#{method_name}=" do |value|
|
101
|
+
instance_variable_set("@#{method_name}", value)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def add_nav_props(klass)
|
107
|
+
@nav_props.each do |method_name|
|
108
|
+
klass.send :define_method, method_name do
|
109
|
+
instance_variable_get("@#{method_name}")
|
110
|
+
end
|
111
|
+
klass.send :define_method, "#{method_name}=" do |value|
|
112
|
+
instance_variable_set("@#{method_name}", value)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end # module OData
|
data/lib/ruby_odata/operation.rb
CHANGED
@@ -1,18 +1,18 @@
|
|
1
|
-
module OData
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
1
|
+
module OData
|
2
|
+
# Internally used helper class for storing operations called against the service. This class shouldn't be used directly.
|
3
|
+
class Operation
|
4
|
+
attr_accessor :kind, :klass_name, :klass
|
5
|
+
|
6
|
+
# Creates a new instance of the Operation class
|
7
|
+
#
|
8
|
+
# ==== Required Attributes
|
9
|
+
# - kind: The operation type (Add, Update, or Delete)
|
10
|
+
# - klass_name: The name/type of the class to operate against
|
11
|
+
# - klass: The actual class
|
12
|
+
def initialize(kind, klass_name, klass)
|
13
|
+
@kind = kind
|
14
|
+
@klass_name = klass_name
|
15
|
+
@klass = klass
|
16
|
+
end
|
17
|
+
end
|
18
18
|
end
|
@@ -1,107 +1,107 @@
|
|
1
|
-
module OData
|
2
|
-
# The query builder is used to call query operations against the service. This shouldn't be called directly, but rather it is returned from the dynamic methods created for the specific service that you are calling.
|
3
|
-
#
|
4
|
-
# For example, given the following code snippet:
|
5
|
-
# svc = OData::Service.new "http://127.0.0.1:8888/SampleService/Entities.svc"
|
6
|
-
# svc.Categories
|
7
|
-
# The *Categories* method would return a QueryBuilder
|
8
|
-
class QueryBuilder
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
end
|
106
|
-
|
1
|
+
module OData
|
2
|
+
# The query builder is used to call query operations against the service. This shouldn't be called directly, but rather it is returned from the dynamic methods created for the specific service that you are calling.
|
3
|
+
#
|
4
|
+
# For example, given the following code snippet:
|
5
|
+
# svc = OData::Service.new "http://127.0.0.1:8888/SampleService/Entities.svc"
|
6
|
+
# svc.Categories
|
7
|
+
# The *Categories* method would return a QueryBuilder
|
8
|
+
class QueryBuilder
|
9
|
+
# Creates a new instance of the QueryBuilder class
|
10
|
+
#
|
11
|
+
# ==== Required Attributes
|
12
|
+
# - root: The root entity collection to query against
|
13
|
+
def initialize(root)
|
14
|
+
@root = root.to_s
|
15
|
+
@expands = []
|
16
|
+
@filters = []
|
17
|
+
@order_bys = []
|
18
|
+
@skip = nil
|
19
|
+
@top = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
# Used to eagerly-load data for nested objects, for example, obtaining a Category for a Product within one call to the server
|
23
|
+
# ==== Required Attributes
|
24
|
+
# - path: The path of the entity to expand relative to the root
|
25
|
+
#
|
26
|
+
# ==== Example
|
27
|
+
# # Without expanding the query (no Category will be filled in for the Product)
|
28
|
+
# svc.Products(1)
|
29
|
+
# prod1 = svc.execute
|
30
|
+
#
|
31
|
+
# # With expanding the query (the Category will be filled in)
|
32
|
+
# svc.Products(1).expand('Category')
|
33
|
+
# prod1 = svc.execute
|
34
|
+
def expand(path)
|
35
|
+
@expands << path
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
# Used to filter data being returned
|
40
|
+
# ==== Required Attributes
|
41
|
+
# - filter: The conditions to apply to the query
|
42
|
+
#
|
43
|
+
# ==== Example
|
44
|
+
# svc.Products.filter("Name eq 'Product 2'")
|
45
|
+
# products = svc.execute
|
46
|
+
def filter(filter)
|
47
|
+
@filters << CGI.escape(filter)
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
# Used to order the data being returned
|
52
|
+
# ==== Required Attributes
|
53
|
+
# - order_by: The order by statement. Note to specify direction, use "desc" or "asc"; must be lowercase
|
54
|
+
#
|
55
|
+
# ==== Example
|
56
|
+
# svc.Products.order_by("Name")
|
57
|
+
# products = svc.execute
|
58
|
+
def order_by(order_by)
|
59
|
+
@order_bys << CGI.escape(order_by)
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
63
|
+
# Used to skip a number of records
|
64
|
+
# This is typically used for paging, where it would be used along with the +top+ method.
|
65
|
+
# ==== Required Attributes
|
66
|
+
# - num: The number of items to skip
|
67
|
+
#
|
68
|
+
# ==== Example
|
69
|
+
# svc.Products.skip(5)
|
70
|
+
# products = svc.execute # => skips the first 5 items
|
71
|
+
def skip(num)
|
72
|
+
@skip = num
|
73
|
+
self
|
74
|
+
end
|
75
|
+
|
76
|
+
# Used to take only the top X records
|
77
|
+
# This is typically used for paging, where it would be used along with the +skip+ method.
|
78
|
+
# ==== Required Attributes
|
79
|
+
# - num: The number of items to return
|
80
|
+
#
|
81
|
+
# ==== Example
|
82
|
+
# svc.Products.top(5)
|
83
|
+
# products = svc.execute # => returns only the first 5 items
|
84
|
+
def top(num)
|
85
|
+
@top = num
|
86
|
+
self
|
87
|
+
end
|
88
|
+
|
89
|
+
# Builds the query URI (path, not including root) incorporating expands, filters, etc.
|
90
|
+
# This is used internally when the execute method is called on the service
|
91
|
+
def query
|
92
|
+
q = @root.clone
|
93
|
+
query_options = []
|
94
|
+
query_options << "$expand=#{@expands.join(',')}" unless @expands.empty?
|
95
|
+
query_options << "$filter=#{@filters.join('+and+')}" unless @filters.empty?
|
96
|
+
query_options << "$orderby=#{@order_bys.join(',')}" unless @order_bys.empty?
|
97
|
+
query_options << "$skip=#{@skip}" unless @skip.nil?
|
98
|
+
query_options << "$top=#{@top}" unless @top.nil?
|
99
|
+
if !query_options.empty?
|
100
|
+
q << "?"
|
101
|
+
q << query_options.join('&')
|
102
|
+
end
|
103
|
+
return q
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
107
|
end # Module
|