odata 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -13
- data/CHANGELOG.md +4 -0
- data/lib/odata.rb +2 -2
- data/lib/odata/entity.rb +64 -47
- data/lib/odata/entity_set.rb +17 -20
- data/lib/odata/properties/boolean.rb +5 -0
- data/lib/odata/properties/integer.rb +16 -24
- data/lib/odata/property.rb +22 -0
- data/lib/odata/query.rb +105 -41
- data/lib/odata/query/criteria.rb +54 -48
- data/lib/odata/service.rb +2 -2
- data/lib/odata/version.rb +1 -1
- data/odata.gemspec +1 -2
- data/spec/fixtures/vcr_cassettes/entity_set_specs.yml +952 -0
- data/spec/fixtures/vcr_cassettes/entity_set_specs/bad_entry.yml +220 -0
- data/spec/fixtures/vcr_cassettes/entity_set_specs/existing_entry.yml +313 -0
- data/spec/fixtures/vcr_cassettes/entity_set_specs/new_entry.yml +226 -0
- data/spec/fixtures/vcr_cassettes/entity_specs.yml +164 -0
- data/spec/fixtures/vcr_cassettes/query_specs.yml +164 -0
- data/spec/fixtures/vcr_cassettes/service_registry_specs.yml +164 -0
- data/spec/fixtures/vcr_cassettes/service_specs.yml +164 -0
- data/spec/odata/entity_set_spec.rb +22 -40
- data/spec/odata/entity_spec.rb +5 -5
- data/spec/odata/query/criteria_spec.rb +57 -24
- data/spec/odata/query_spec.rb +79 -40
- data/spec/odata/service_registry_spec.rb +1 -1
- data/spec/odata/service_spec.rb +1 -7
- data/spec/spec_helper.rb +9 -46
- metadata +21 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 899ee301dd62dc8969c8a8d8191adc586b287527
|
4
|
+
data.tar.gz: 9d9122c36019cfa78a3e4567b9739e8353b07db3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 422c217129c1f82e13d3641d8468cc3ff6bc65224db8da0c17cc1e1c1c012d093e1b5e0f891c48224088f1ae01fa132b89e6bb5edc44b8c4c3b3663e88792023
|
7
|
+
data.tar.gz: 262866a54904f052099030cf1393359b2e9ba7dd06fc4bfbd56a18ea004ba6262fcc6994ea2383b175abe0d01225785661556e2dc24ec2c45695b5d91316f7f2
|
data/.travis.yml
CHANGED
@@ -11,9 +11,6 @@ jdk:
|
|
11
11
|
- openjdk7
|
12
12
|
- oraclejdk7
|
13
13
|
- oraclejdk8
|
14
|
-
env:
|
15
|
-
- REAL_HTTP=true
|
16
|
-
- REAL_HTTP=false
|
17
14
|
branches:
|
18
15
|
only:
|
19
16
|
- master
|
@@ -25,40 +22,30 @@ matrix:
|
|
25
22
|
jdk: oraclejdk7
|
26
23
|
- rvm: 1.9.3
|
27
24
|
jdk: oraclejdk8
|
28
|
-
- rvm: 1.9.3
|
29
|
-
env: REAL_HTTP=true
|
30
25
|
- rvm: 2.0.0
|
31
26
|
jdk: openjdk6
|
32
27
|
- rvm: 2.0.0
|
33
28
|
jdk: oraclejdk7
|
34
29
|
- rvm: 2.0.0
|
35
30
|
jdk: oraclejdk8
|
36
|
-
- rvm: 2.0.0
|
37
|
-
env: REAL_HTTP=true
|
38
31
|
- rvm: 2.1.0
|
39
32
|
jdk: openjdk6
|
40
33
|
- rvm: 2.1.0
|
41
34
|
jdk: oraclejdk7
|
42
35
|
- rvm: 2.1.0
|
43
36
|
jdk: oraclejdk8
|
44
|
-
- rvm: 2.1.0
|
45
|
-
env: REAL_HTTP=true
|
46
37
|
- rvm: 2.1.1
|
47
38
|
jdk: openjdk6
|
48
39
|
- rvm: 2.1.1
|
49
40
|
jdk: oraclejdk7
|
50
41
|
- rvm: 2.1.1
|
51
42
|
jdk: oraclejdk8
|
52
|
-
- rvm: 2.1.1
|
53
|
-
env: REAL_HTTP=true
|
54
43
|
- rvm: 2.1.2
|
55
44
|
jdk: openjdk6
|
56
45
|
- rvm: 2.1.2
|
57
46
|
jdk: oraclejdk7
|
58
47
|
- rvm: 2.1.2
|
59
48
|
jdk: oraclejdk8
|
60
|
-
- rvm: jruby
|
61
|
-
env: REAL_HTTP=true
|
62
49
|
addons:
|
63
50
|
code_climate:
|
64
51
|
repo_token: 56e2763b5bfe138f566c5f2bf23c14deee4f8990324436dbde07ee2a34bb87f8
|
data/CHANGELOG.md
CHANGED
data/lib/odata.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
require 'backports/2.1.0/enumerable/to_h'
|
2
|
-
|
3
1
|
require 'uri'
|
4
2
|
require 'date'
|
3
|
+
require 'bigdecimal'
|
5
4
|
require 'nokogiri'
|
6
5
|
require 'typhoeus'
|
7
6
|
|
@@ -14,6 +13,7 @@ require 'odata/property'
|
|
14
13
|
require 'odata/properties'
|
15
14
|
require 'odata/entity'
|
16
15
|
require 'odata/entity_set'
|
16
|
+
require 'odata/query/criteria'
|
17
17
|
require 'odata/query'
|
18
18
|
require 'odata/service'
|
19
19
|
require 'odata/service_registry'
|
data/lib/odata/entity.rb
CHANGED
@@ -1,16 +1,31 @@
|
|
1
1
|
module OData
|
2
|
+
# An OData::Entity represents a single record returned by the service. All
|
3
|
+
# Entities have a type and belong to a specific namespace. They are written
|
4
|
+
# back to the service via the EntitySet they came from. OData::Entity
|
5
|
+
# instances should not be instantiated directly; instead, they should either
|
6
|
+
# be read or instantiated from their respective OData::EntitySet.
|
2
7
|
class Entity
|
3
|
-
|
8
|
+
# The Entity type name
|
9
|
+
attr_reader :type
|
10
|
+
# The OData::Service namespace
|
11
|
+
attr_reader :namespace
|
4
12
|
|
13
|
+
# Initializes a bare Entity
|
14
|
+
# @param options [Hash]
|
5
15
|
def initialize(options = {})
|
6
16
|
@type = options[:type]
|
7
17
|
@namespace = options[:namespace]
|
8
18
|
end
|
9
19
|
|
20
|
+
# Returns name of Entity from Service specified type.
|
21
|
+
# @return [String]
|
10
22
|
def name
|
11
23
|
@name ||= type.gsub(/#{namespace}\./, '')
|
12
24
|
end
|
13
25
|
|
26
|
+
# Get property value
|
27
|
+
# @param property_name [to_s]
|
28
|
+
# @return [*]
|
14
29
|
def [](property_name)
|
15
30
|
begin
|
16
31
|
properties[property_name.to_s].value
|
@@ -19,6 +34,9 @@ module OData
|
|
19
34
|
end
|
20
35
|
end
|
21
36
|
|
37
|
+
# Set property value
|
38
|
+
# @param property_name [to_s]
|
39
|
+
# @param value [*]
|
22
40
|
def []=(property_name, value)
|
23
41
|
begin
|
24
42
|
properties[property_name.to_s].value = value
|
@@ -27,6 +45,10 @@ module OData
|
|
27
45
|
end
|
28
46
|
end
|
29
47
|
|
48
|
+
# Create Entity with provided properties and options.
|
49
|
+
# @param new_properties [Hash]
|
50
|
+
# @param options [Hash]
|
51
|
+
# @param [OData::Entity]
|
30
52
|
def self.with_properties(new_properties = {}, options = {})
|
31
53
|
entity = OData::Entity.new(options)
|
32
54
|
entity.instance_eval do
|
@@ -35,52 +57,27 @@ module OData
|
|
35
57
|
end
|
36
58
|
|
37
59
|
new_properties.each do |property_name, property_value|
|
38
|
-
self[property_name] = property_value
|
60
|
+
self[property_name.to_s] = property_value
|
39
61
|
end
|
40
62
|
end
|
41
63
|
entity
|
42
64
|
end
|
43
65
|
|
66
|
+
# Create Entity from XML document with provided options.
|
67
|
+
# @param xml_doc [Nokogiri::XML]
|
68
|
+
# @param options [Hash]
|
69
|
+
# @return [OData::Entity]
|
44
70
|
def self.from_xml(xml_doc, options = {})
|
45
71
|
return nil if xml_doc.nil?
|
46
72
|
entity = OData::Entity.new(options)
|
47
|
-
entity
|
48
|
-
|
49
|
-
|
50
|
-
if property_xml.attributes['null'] &&
|
51
|
-
property_xml.attributes['null'].value == 'true'
|
52
|
-
value = nil
|
53
|
-
value_type = service.get_property_type(name, property_name)
|
54
|
-
else
|
55
|
-
value_type = property_xml.attributes['type'].value
|
56
|
-
value = property_xml.content
|
57
|
-
end
|
58
|
-
klass_name = value_type.gsub(/^Edm\./, '')
|
59
|
-
property = get_property_class(klass_name).new(property_name, value)
|
60
|
-
set_property(property_name, property)
|
61
|
-
end
|
62
|
-
|
63
|
-
begin
|
64
|
-
title_value = xml_doc.xpath('//title').first.content
|
65
|
-
property_name = service.get_title_property_name(name)
|
66
|
-
value_type = service.get_property_type(name, property_name)
|
67
|
-
klass_name = value_type.gsub(/^Edm\./, '')
|
68
|
-
property = get_property_class(klass_name).new(property_name, title_value)
|
69
|
-
set_property(property_name, property)
|
70
|
-
end
|
71
|
-
|
72
|
-
begin
|
73
|
-
summary_value = xml_doc.xpath('//summary').first.content
|
74
|
-
property_name = service.get_summary_property_name(name)
|
75
|
-
value_type = service.get_property_type(name, property_name)
|
76
|
-
klass_name = value_type.gsub(/^Edm\./, '')
|
77
|
-
property = get_property_class(klass_name).new(property_name, summary_value)
|
78
|
-
set_property(property_name, property)
|
79
|
-
end
|
80
|
-
end
|
73
|
+
process_properties(entity, xml_doc)
|
74
|
+
process_feed_property(entity, xml_doc, 'title')
|
75
|
+
process_feed_property(entity, xml_doc, 'summary')
|
81
76
|
entity
|
82
77
|
end
|
83
78
|
|
79
|
+
# Converts Entity to its XML representation.
|
80
|
+
# @return [String]
|
84
81
|
def to_xml
|
85
82
|
builder = Nokogiri::XML::Builder.new do |xml|
|
86
83
|
xml.entry('xmlns' => 'http://www.w3.org/2005/Atom',
|
@@ -97,16 +94,7 @@ module OData
|
|
97
94
|
xml['metadata'].properties do
|
98
95
|
properties.each do |name, property|
|
99
96
|
next if name == primary_key
|
100
|
-
|
101
|
-
'metadata:type' => property.type,
|
102
|
-
}
|
103
|
-
|
104
|
-
if property.value.nil?
|
105
|
-
attributes['metadata:null'] = 'true'
|
106
|
-
xml['data'].send(name.to_sym, attributes)
|
107
|
-
else
|
108
|
-
xml['data'].send(name.to_sym, attributes, property.xml_value)
|
109
|
-
end
|
97
|
+
property.to_xml(xml)
|
110
98
|
end
|
111
99
|
end
|
112
100
|
end
|
@@ -115,13 +103,17 @@ module OData
|
|
115
103
|
builder.to_xml
|
116
104
|
end
|
117
105
|
|
106
|
+
# Returns the primary key for the Entity.
|
107
|
+
# @return [String]
|
118
108
|
def primary_key
|
119
109
|
service.primary_key_for(name)
|
120
110
|
end
|
121
111
|
|
122
112
|
private
|
123
113
|
|
124
|
-
def get_property_class(
|
114
|
+
def get_property_class(property_name)
|
115
|
+
value_type = service.get_property_type(name, property_name)
|
116
|
+
klass_name = value_type.gsub(/^Edm\./, '')
|
125
117
|
::OData::Properties.const_get(klass_name)
|
126
118
|
end
|
127
119
|
|
@@ -136,5 +128,30 @@ module OData
|
|
136
128
|
def set_property(name, odata_property)
|
137
129
|
properties[name.to_s] = odata_property.dup
|
138
130
|
end
|
131
|
+
|
132
|
+
def self.process_properties(entity, xml_doc)
|
133
|
+
entity.instance_eval do
|
134
|
+
xml_doc.xpath('//content/properties/*').each do |property_xml|
|
135
|
+
property_name = property_xml.name
|
136
|
+
if property_xml.attributes['null'] &&
|
137
|
+
property_xml.attributes['null'].value == 'true'
|
138
|
+
value = nil
|
139
|
+
else
|
140
|
+
value = property_xml.content
|
141
|
+
end
|
142
|
+
property = get_property_class(property_name).new(property_name, value)
|
143
|
+
set_property(property_name, property)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def self.process_feed_property(entity, xml_doc, property_name)
|
149
|
+
entity.instance_eval do
|
150
|
+
property_value = xml_doc.xpath("//#{property_name}").first.content
|
151
|
+
property_name = service.send("get_#{property_name}_property_name", name)
|
152
|
+
property = get_property_class(property_name).new(property_name, property_value)
|
153
|
+
set_property(property_name, property)
|
154
|
+
end
|
155
|
+
end
|
139
156
|
end
|
140
157
|
end
|
data/lib/odata/entity_set.rb
CHANGED
@@ -10,7 +10,14 @@ module OData
|
|
10
10
|
class EntitySet
|
11
11
|
include Enumerable
|
12
12
|
|
13
|
-
|
13
|
+
# The name of the EntitySet
|
14
|
+
attr_reader :name
|
15
|
+
# The Entity type for the EntitySet
|
16
|
+
attr_reader :type
|
17
|
+
# The OData::Service namespace
|
18
|
+
attr_reader :namespace
|
19
|
+
# The EntitySet's container name
|
20
|
+
attr_reader :container
|
14
21
|
|
15
22
|
# Sets up the EntitySet to permit querying for the resources in the set.
|
16
23
|
#
|
@@ -50,9 +57,7 @@ module OData
|
|
50
57
|
# Return the first Entity for the set.
|
51
58
|
# @return [OData::EntitySet]
|
52
59
|
def first
|
53
|
-
query = OData::Query.new(
|
54
|
-
query << OData::Query::Criteria.new(operation: 'skip', argument: 0)
|
55
|
-
query << OData::Query::Criteria.new(operation: 'top', argument: 1)
|
60
|
+
query = OData::Query.new(self).limit(1)
|
56
61
|
result = service.execute(query)
|
57
62
|
entities = service.find_entities(result)
|
58
63
|
OData::Entity.from_xml(entities[0], entity_options)
|
@@ -71,19 +76,13 @@ module OData
|
|
71
76
|
OData::Entity.with_properties(properties, entity_options)
|
72
77
|
end
|
73
78
|
|
74
|
-
#
|
75
|
-
# @
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
result = service.execute("#{name}?$filter=#{filter}")
|
79
|
+
# Returns a query targetted at the current EntitySet.
|
80
|
+
# @return [OData::Query]
|
81
|
+
def query
|
82
|
+
OData::Query.new(self)
|
83
|
+
end
|
80
84
|
|
81
|
-
service.find_entities(result).each do |entity_xml|
|
82
|
-
entities << OData::Entity.from_xml(entity_xml, entity_options)
|
83
|
-
end
|
84
85
|
|
85
|
-
entities
|
86
|
-
end
|
87
86
|
|
88
87
|
# Find the Entity with the supplied key value.
|
89
88
|
# @param key [to_s] primary key to lookup
|
@@ -107,7 +106,7 @@ module OData
|
|
107
106
|
method: :post,
|
108
107
|
body: entity.to_xml.gsub(/\n\s+/, ''),
|
109
108
|
headers: {
|
110
|
-
Accept
|
109
|
+
'Accept' => 'application/atom+xml',
|
111
110
|
'Content-Type' => 'application/atom+xml'
|
112
111
|
}
|
113
112
|
}
|
@@ -138,10 +137,8 @@ module OData
|
|
138
137
|
end
|
139
138
|
|
140
139
|
def get_paginated_entities(per_page, page)
|
141
|
-
query = OData::Query.new(
|
142
|
-
query
|
143
|
-
query << OData::Query::Criteria.new(operation: 'skip', argument: (per_page * page))
|
144
|
-
query << OData::Query::Criteria.new(operation: 'top', argument: per_page)
|
140
|
+
query = OData::Query.new(self)
|
141
|
+
query.include_count.skip(per_page * page).limit(per_page)
|
145
142
|
result = service.execute(query)
|
146
143
|
entities = service.find_entities(result)
|
147
144
|
total = service.find_node(result, 'count').content.to_i
|
@@ -2,6 +2,8 @@ module OData
|
|
2
2
|
module Properties
|
3
3
|
# Defines the Boolean OData type.
|
4
4
|
class Boolean < OData::Property
|
5
|
+
# Returns the property value, properly typecast
|
6
|
+
# @return [Boolean, nil]
|
5
7
|
def value
|
6
8
|
if @value.nil? && allows_nil?
|
7
9
|
nil
|
@@ -10,11 +12,14 @@ module OData
|
|
10
12
|
end
|
11
13
|
end
|
12
14
|
|
15
|
+
# Sets the property value
|
16
|
+
# @params new_value [Boolean]
|
13
17
|
def value=(new_value)
|
14
18
|
validate(new_value)
|
15
19
|
@value = new_value.to_s
|
16
20
|
end
|
17
21
|
|
22
|
+
# The OData type name
|
18
23
|
def type
|
19
24
|
'Edm.Boolean'
|
20
25
|
end
|
@@ -28,12 +28,16 @@ module OData
|
|
28
28
|
|
29
29
|
private
|
30
30
|
|
31
|
+
def exponent_size
|
32
|
+
63
|
33
|
+
end
|
34
|
+
|
31
35
|
def min_value
|
32
|
-
@min ||= -(2**
|
36
|
+
@min ||= -(2**exponent_size)
|
33
37
|
end
|
34
38
|
|
35
39
|
def max_value
|
36
|
-
@max ||= (2**
|
40
|
+
@max ||= (2**exponent_size)-1
|
37
41
|
end
|
38
42
|
end
|
39
43
|
|
@@ -46,12 +50,8 @@ module OData
|
|
46
50
|
|
47
51
|
private
|
48
52
|
|
49
|
-
def
|
50
|
-
|
51
|
-
end
|
52
|
-
|
53
|
-
def max_value
|
54
|
-
@max ||= (2**15)-1
|
53
|
+
def exponent_size
|
54
|
+
15
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
@@ -64,12 +64,8 @@ module OData
|
|
64
64
|
|
65
65
|
private
|
66
66
|
|
67
|
-
def
|
68
|
-
|
69
|
-
end
|
70
|
-
|
71
|
-
def max_value
|
72
|
-
@max ||= (2**31)-1
|
67
|
+
def exponent_size
|
68
|
+
31
|
73
69
|
end
|
74
70
|
end
|
75
71
|
|
@@ -85,12 +81,12 @@ module OData
|
|
85
81
|
|
86
82
|
private
|
87
83
|
|
88
|
-
def
|
89
|
-
|
84
|
+
def exponent_size
|
85
|
+
8
|
90
86
|
end
|
91
87
|
|
92
|
-
def
|
93
|
-
|
88
|
+
def min_value
|
89
|
+
0
|
94
90
|
end
|
95
91
|
end
|
96
92
|
|
@@ -103,12 +99,8 @@ module OData
|
|
103
99
|
|
104
100
|
private
|
105
101
|
|
106
|
-
def
|
107
|
-
|
108
|
-
end
|
109
|
-
|
110
|
-
def max_value
|
111
|
-
@max ||= (2**7)-1
|
102
|
+
def exponent_size
|
103
|
+
7
|
112
104
|
end
|
113
105
|
end
|
114
106
|
end
|