microsoft_graph 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE +10 -0
- data/README.md +97 -0
- data/Rakefile +7 -0
- data/data/metadata_v1.0.xml +1687 -0
- data/integration_spec/integration_spec_helper.rb +18 -0
- data/integration_spec/live_spec.rb +180 -0
- data/lib/microsoft_graph.rb +35 -0
- data/lib/microsoft_graph/base.rb +110 -0
- data/lib/microsoft_graph/base_entity.rb +152 -0
- data/lib/microsoft_graph/cached_metadata_directory.rb +3 -0
- data/lib/microsoft_graph/class_builder.rb +217 -0
- data/lib/microsoft_graph/collection.rb +95 -0
- data/lib/microsoft_graph/collection_association.rb +230 -0
- data/lib/microsoft_graph/errors.rb +6 -0
- data/lib/microsoft_graph/version.rb +3 -0
- data/lib/odata.rb +49 -0
- data/lib/odata/entity_set.rb +20 -0
- data/lib/odata/errors.rb +18 -0
- data/lib/odata/navigation_property.rb +30 -0
- data/lib/odata/operation.rb +17 -0
- data/lib/odata/property.rb +38 -0
- data/lib/odata/request.rb +48 -0
- data/lib/odata/service.rb +280 -0
- data/lib/odata/singleton.rb +20 -0
- data/lib/odata/type.rb +25 -0
- data/lib/odata/types/collection_type.rb +30 -0
- data/lib/odata/types/complex_type.rb +19 -0
- data/lib/odata/types/entity_type.rb +33 -0
- data/lib/odata/types/enum_type.rb +37 -0
- data/lib/odata/types/primitive_type.rb +12 -0
- data/lib/odata/types/primitive_types/binary_type.rb +15 -0
- data/lib/odata/types/primitive_types/boolean_type.rb +15 -0
- data/lib/odata/types/primitive_types/date_time_offset_type.rb +15 -0
- data/lib/odata/types/primitive_types/date_type.rb +23 -0
- data/lib/odata/types/primitive_types/double_type.rb +16 -0
- data/lib/odata/types/primitive_types/guid_type.rb +24 -0
- data/lib/odata/types/primitive_types/int_16_type.rb +19 -0
- data/lib/odata/types/primitive_types/int_32_type.rb +15 -0
- data/lib/odata/types/primitive_types/int_64_type.rb +15 -0
- data/lib/odata/types/primitive_types/stream_type.rb +15 -0
- data/lib/odata/types/primitive_types/string_type.rb +15 -0
- data/microsoft_graph.gemspec +31 -0
- data/tasks/update_metadata.rb +17 -0
- metadata +232 -0
@@ -0,0 +1,217 @@
|
|
1
|
+
class MicrosoftGraph
|
2
|
+
class ClassBuilder
|
3
|
+
@@loaded = false
|
4
|
+
|
5
|
+
def self.load!(service)
|
6
|
+
if !@@loaded
|
7
|
+
@service_namespace = service.namespace
|
8
|
+
service.entity_types.each do |entity_type|
|
9
|
+
create_class! entity_type
|
10
|
+
end
|
11
|
+
|
12
|
+
service.complex_types.each do |complex_type|
|
13
|
+
create_class! complex_type
|
14
|
+
end
|
15
|
+
|
16
|
+
service.entity_sets.each do |entity_set|
|
17
|
+
add_graph_association! entity_set
|
18
|
+
end
|
19
|
+
|
20
|
+
service.actions.each do |action|
|
21
|
+
add_action_method! action
|
22
|
+
end
|
23
|
+
|
24
|
+
service.functions.each do |function|
|
25
|
+
add_function_method! function
|
26
|
+
end
|
27
|
+
|
28
|
+
service.singletons.each do |singleton|
|
29
|
+
class_name = classify(singleton.type_name)
|
30
|
+
MicrosoftGraph.instance_eval do
|
31
|
+
resource_name = singleton.name
|
32
|
+
define_method(OData.convert_to_snake_case(resource_name)) do
|
33
|
+
MicrosoftGraph
|
34
|
+
.const_get(class_name)
|
35
|
+
.new(
|
36
|
+
graph: self,
|
37
|
+
resource_name: resource_name,
|
38
|
+
parent: self
|
39
|
+
).tap(&:fetch)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
MicrosoftGraph.instance_eval do
|
45
|
+
define_method(:navigation_properties) do
|
46
|
+
service.entity_sets
|
47
|
+
.concat(service.singletons)
|
48
|
+
.map { |navigation_property|
|
49
|
+
[navigation_property.name.to_sym, navigation_property]
|
50
|
+
}.to_h
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
@@loaded = true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.loaded?
|
59
|
+
@@loaded
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def remove_service_namespace(name)
|
65
|
+
name.gsub("#{@service_namespace}.", "")
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.create_class!(type)
|
69
|
+
superklass = get_superklass(type)
|
70
|
+
klass = MicrosoftGraph.const_set(classify(type.name), Class.new(superklass))
|
71
|
+
klass.const_set("ODATA_TYPE", type)
|
72
|
+
klass.instance_eval do
|
73
|
+
def self.odata_type
|
74
|
+
const_get("ODATA_TYPE")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
create_properties(klass, type)
|
78
|
+
create_navigation_properties(klass, type) if type.respond_to? :navigation_properties
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.add_graph_association!(entity_set)
|
82
|
+
klass = get_namespaced_class(entity_set.member_type)
|
83
|
+
resource_name = entity_set.name.gsub("#{@service_namespace}.", "")
|
84
|
+
odata_collection =
|
85
|
+
OData::CollectionType.new(member_type: klass.odata_type, name: entity_set.name)
|
86
|
+
MicrosoftGraph.send(:define_method, resource_name) do
|
87
|
+
@association_collections[entity_set.name] ||=
|
88
|
+
MicrosoftGraph::CollectionAssociation
|
89
|
+
.new(
|
90
|
+
type: odata_collection,
|
91
|
+
resource_name: resource_name,
|
92
|
+
parent: self
|
93
|
+
)
|
94
|
+
.tap do |collection|
|
95
|
+
collection.graph = self
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.create_properties(klass, type)
|
101
|
+
property_map = type.properties.map { |property|
|
102
|
+
define_getter_and_setter(klass, property)
|
103
|
+
[
|
104
|
+
OData.convert_to_snake_case(property.name).to_sym,
|
105
|
+
property
|
106
|
+
]
|
107
|
+
}.to_h
|
108
|
+
|
109
|
+
klass.class_eval do
|
110
|
+
define_method(:properties) do
|
111
|
+
super().merge(property_map)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.define_getter_and_setter(klass, property)
|
117
|
+
klass.class_eval do
|
118
|
+
property_name = OData.convert_to_snake_case(property.name)
|
119
|
+
define_method(property_name.to_sym) do
|
120
|
+
get(property_name.to_sym)
|
121
|
+
end
|
122
|
+
define_method("#{property_name}=".to_sym) do |value|
|
123
|
+
set(property_name.to_sym, value)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def self.create_navigation_properties(klass, type)
|
129
|
+
klass.class_eval do
|
130
|
+
type.navigation_properties.each do |navigation_property|
|
131
|
+
navigation_property_name = OData.convert_to_snake_case(navigation_property.name).to_sym
|
132
|
+
define_method(navigation_property_name.to_sym) do
|
133
|
+
get_navigation_property(navigation_property_name.to_sym)
|
134
|
+
end
|
135
|
+
unless navigation_property.collection?
|
136
|
+
define_method("#{navigation_property_name}=".to_sym) do |value|
|
137
|
+
set_navigation_property(navigation_property_name.to_sym, value)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
define_method(:navigation_properties) do
|
143
|
+
type.navigation_properties.map { |navigation_property|
|
144
|
+
[
|
145
|
+
OData.convert_to_snake_case(navigation_property.name).to_sym,
|
146
|
+
navigation_property
|
147
|
+
]
|
148
|
+
}.to_h
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def self.add_function_method!(function)
|
154
|
+
klass = get_namespaced_class(function.binding_type.name)
|
155
|
+
klass.class_eval do
|
156
|
+
define_method(OData.convert_to_snake_case(function.name).to_sym) do |params={}|
|
157
|
+
raise NoAssociationError unless parent
|
158
|
+
raise_no_graph_error! unless graph
|
159
|
+
function_params = params.map do |param_key, param_value|
|
160
|
+
"#{OData.convert_to_camel_case(param_key)}='#{param_value}'"
|
161
|
+
end
|
162
|
+
response = graph.service.get("#{path}/microsoft.graph.#{function.name}(#{function_params.join(',')})")
|
163
|
+
if function.return_type
|
164
|
+
if function.return_type.collection?
|
165
|
+
Collection.new(function.return_type, response[:attributes]['value'])
|
166
|
+
else
|
167
|
+
ClassBuilder.get_namespaced_class(function.return_type.name).new(attributes: response[:attributes]['value'])
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def self.add_action_method!(action)
|
175
|
+
klass = get_namespaced_class(action.binding_type.name)
|
176
|
+
klass.class_eval do
|
177
|
+
define_method(OData.convert_to_snake_case(action.name).to_sym) do |args={}|
|
178
|
+
raise NoAssociationError unless parent
|
179
|
+
raise_no_graph_error! unless graph
|
180
|
+
response = graph.service.post("#{path}/#{action.name}", OData.convert_keys_to_camel_case(args).to_json)
|
181
|
+
if action.return_type
|
182
|
+
if action.return_type.collection?
|
183
|
+
Collection.new(action.return_type, response['value'])
|
184
|
+
else
|
185
|
+
ClassBuilder.get_namespaced_class(action.return_type.name).new(attributes: response['value'])
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def self.classify(name)
|
193
|
+
raw_name = name.gsub("#{@service_namespace}.", "")
|
194
|
+
raw_name.to_s.slice(0, 1).capitalize + raw_name.to_s.slice(1..-1)
|
195
|
+
end
|
196
|
+
|
197
|
+
def self.get_namespaced_class(property_name)
|
198
|
+
klass_name = classify(property_name)
|
199
|
+
klass = begin
|
200
|
+
MicrosoftGraph.const_get(klass_name) if MicrosoftGraph.const_defined?(klass_name)
|
201
|
+
rescue NameError
|
202
|
+
return false
|
203
|
+
end
|
204
|
+
klass && MicrosoftGraph::BaseEntity != klass.superclass && klass
|
205
|
+
end
|
206
|
+
|
207
|
+
def self.get_superklass(type)
|
208
|
+
if type.base_type.nil?
|
209
|
+
(type.class == OData::ComplexType) ?
|
210
|
+
MicrosoftGraph::Base :
|
211
|
+
MicrosoftGraph::BaseEntity
|
212
|
+
else
|
213
|
+
Object.const_get("MicrosoftGraph::" + classify(type.base_type))
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
class MicrosoftGraph
|
4
|
+
class Collection
|
5
|
+
include Enumerable
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
attr_accessor :graph
|
9
|
+
|
10
|
+
def_delegators :values, :size, :length, :include?, :empty?, :[]
|
11
|
+
|
12
|
+
def initialize(type, initial_values = [])
|
13
|
+
@type = type
|
14
|
+
@dirty = false
|
15
|
+
@internal_values =
|
16
|
+
if klass = MicrosoftGraph::ClassBuilder.get_namespaced_class(type.member_type.name)
|
17
|
+
initial_values.map { |v| klass.new(attributes: v) }
|
18
|
+
else
|
19
|
+
initial_values
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def each
|
24
|
+
values.each do |value|
|
25
|
+
yield value
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def <<(value)
|
30
|
+
unless @type.valid_value?(value)
|
31
|
+
raise MicrosoftGraph::TypeError.new(
|
32
|
+
"Value \"#{value}\" does not match type #{@type.member_type.name}"
|
33
|
+
)
|
34
|
+
end
|
35
|
+
@dirty = true
|
36
|
+
@internal_values << value
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
def []=(index, value)
|
41
|
+
raise MicrosoftGraph::TypeError unless @type.valid_value?(value)
|
42
|
+
@dirty = true
|
43
|
+
values[index] = value
|
44
|
+
end
|
45
|
+
|
46
|
+
def dirty?
|
47
|
+
@dirty || @internal_values.any? { |value|
|
48
|
+
value.respond_to?(:dirty?) && value.dirty?
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
def mark_clean
|
53
|
+
@dirty = false
|
54
|
+
@internal_values.each { |value|
|
55
|
+
value.respond_to?(:mark_clean) && value.mark_clean
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
def as_json(options = {})
|
60
|
+
values.map do |value|
|
61
|
+
if value.respond_to? :as_json
|
62
|
+
value.as_json(options)
|
63
|
+
else
|
64
|
+
value
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def new(attributes = {})
|
70
|
+
klass = MicrosoftGraph::ClassBuilder.get_namespaced_class(@type.member_type.name)
|
71
|
+
if klass
|
72
|
+
new_instance = klass.new(graph: graph, attributes: attributes)
|
73
|
+
self << new_instance
|
74
|
+
new_instance
|
75
|
+
else
|
76
|
+
raise NoMethodError.new("undefined method `new' for #{as_json}:#{self.class}")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def parental_chain
|
81
|
+
if parent && parent.respond_to?(:parental_chain)
|
82
|
+
parent.parental_chain.concat([parent])
|
83
|
+
else
|
84
|
+
[parent]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def values
|
91
|
+
@internal_values
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,230 @@
|
|
1
|
+
class MicrosoftGraph
|
2
|
+
class CollectionAssociation < Collection
|
3
|
+
attr_reader :type
|
4
|
+
attr_reader :parent
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
@type = options[:type]
|
8
|
+
@graph = options[:graph]
|
9
|
+
@resource_name = options[:resource_name]
|
10
|
+
@parent = options[:parent]
|
11
|
+
@order_by = options[:order_by]
|
12
|
+
@filter = options[:filter]
|
13
|
+
@dirty = false
|
14
|
+
@loaded = false
|
15
|
+
@internal_values = []
|
16
|
+
|
17
|
+
raise MicrosoftGraph::TypeError.new("A collection cannot be both ordered and filtered.") if @order_by && @filter
|
18
|
+
@order_by && @order_by.each do |field|
|
19
|
+
field_name, direction = field.to_s.split(' ')
|
20
|
+
field_names = field_name.split("/")
|
21
|
+
unless valid_nested_property(field_names, @type)
|
22
|
+
raise MicrosoftGraph::TypeError.new("Tried to order by invalid field: #{field_name}")
|
23
|
+
end
|
24
|
+
if direction && ! %w(asc desc).include?(direction)
|
25
|
+
raise MicrosoftGraph::TypeError.new("Tried to order field #{field_name} by invalid direction: #{direction}")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
@filter && @filter.respond_to?(:keys) && @filter.keys.each do |field_name|
|
29
|
+
unless @type.properties.map(&:name).include? OData.convert_to_camel_case(field_name)
|
30
|
+
raise MicrosoftGraph::TypeError.new("Tried to filter by invalid field: #{field_name}")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
def find(id)
|
37
|
+
if response = graph.service.get("#{path}/#{URI.escape(id.to_s)}")
|
38
|
+
klass = if member_type = specified_member_type(response)
|
39
|
+
ClassBuilder.get_namespaced_class(response)
|
40
|
+
else
|
41
|
+
default_member_class
|
42
|
+
end
|
43
|
+
klass.new(
|
44
|
+
graph: graph,
|
45
|
+
parent: self,
|
46
|
+
attributes: response[:attributes],
|
47
|
+
persisted: true
|
48
|
+
)
|
49
|
+
else
|
50
|
+
nil
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def path
|
55
|
+
if parent && parent.path
|
56
|
+
"#{parent.path}/#{@resource_name}"
|
57
|
+
else
|
58
|
+
@resource_name
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def query_path
|
63
|
+
if @order_by
|
64
|
+
order_by_names = @order_by.map do |field|
|
65
|
+
URI.escape OData.convert_to_camel_case(field)
|
66
|
+
end
|
67
|
+
"#{path}?$orderby=#{order_by_names.join(',')}"
|
68
|
+
elsif @filter
|
69
|
+
escaped_filters = URI.escape(stringify_filters(@filter))
|
70
|
+
"#{path}?$filter=#{escaped_filters}"
|
71
|
+
else
|
72
|
+
path
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def order_by(*fields)
|
77
|
+
self.class.new(
|
78
|
+
type: @type,
|
79
|
+
graph: @graph,
|
80
|
+
resource_name: @resource_name,
|
81
|
+
parent: @parent,
|
82
|
+
order_by: fields,
|
83
|
+
filter: @filter
|
84
|
+
)
|
85
|
+
end
|
86
|
+
|
87
|
+
def valid_nested_property(field_names, parent_type)
|
88
|
+
field_name = field_names.shift
|
89
|
+
if field_name
|
90
|
+
property = parent_type.properties.find do |prop|
|
91
|
+
OData.convert_to_camel_case(prop.name) == OData.convert_to_camel_case(field_name)
|
92
|
+
end
|
93
|
+
property && valid_nested_property(field_names, property.type)
|
94
|
+
else
|
95
|
+
true
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def filter(new_filters)
|
100
|
+
self.class.new(
|
101
|
+
type: @type,
|
102
|
+
graph: @graph,
|
103
|
+
resource_name: @resource_name,
|
104
|
+
parent: @parent,
|
105
|
+
order_by: @order_by,
|
106
|
+
filter: merge_with_existing_filter(new_filters)
|
107
|
+
)
|
108
|
+
end
|
109
|
+
|
110
|
+
def merge_with_existing_filter(new_filters)
|
111
|
+
existing_filter = @filter || {}
|
112
|
+
if new_filters.respond_to?(:keys) && existing_filter.respond_to?(:keys)
|
113
|
+
existing_filter.merge(new_filters)
|
114
|
+
else
|
115
|
+
[stringify_filters(new_filters), stringify_filters(@filter)].compact.join(" and ")
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def stringify_filters(filters)
|
120
|
+
if filters.respond_to?(:keys)
|
121
|
+
filter_strings = filters.map do |k,v|
|
122
|
+
v = v.is_a?(String) ? "'#{v}'" : v
|
123
|
+
"#{OData.convert_to_camel_case(k)} eq #{v}"
|
124
|
+
end
|
125
|
+
filter_strings.sort.join(' and ')
|
126
|
+
else
|
127
|
+
filters
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def create(attributes = {})
|
132
|
+
build(attributes).tap { |n| n.save }
|
133
|
+
end
|
134
|
+
|
135
|
+
def create!(attributes = {})
|
136
|
+
build(attributes).tap { |n| n.save! }
|
137
|
+
end
|
138
|
+
|
139
|
+
def build(attributes = {})
|
140
|
+
ClassBuilder
|
141
|
+
.get_namespaced_class(type.member_type.name)
|
142
|
+
.new(
|
143
|
+
graph: graph,
|
144
|
+
resource_name: @resource_name,
|
145
|
+
parent: self,
|
146
|
+
attributes: attributes,
|
147
|
+
).tap { |new_member|
|
148
|
+
@internal_values << new_member
|
149
|
+
}
|
150
|
+
end
|
151
|
+
|
152
|
+
def <<(new_member)
|
153
|
+
super
|
154
|
+
new_member.graph = graph
|
155
|
+
new_member.parent = self
|
156
|
+
new_member.save
|
157
|
+
self
|
158
|
+
end
|
159
|
+
|
160
|
+
def each(start = 0)
|
161
|
+
return to_enum(:each, start) unless block_given?
|
162
|
+
@next_link = query_path
|
163
|
+
Array(@internal_values[start..-1]).each do |element|
|
164
|
+
yield(element)
|
165
|
+
end
|
166
|
+
|
167
|
+
unless last?
|
168
|
+
start = [@internal_values.size, start].max
|
169
|
+
|
170
|
+
fetch_next_page
|
171
|
+
|
172
|
+
each(start, &Proc.new)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def collection?
|
177
|
+
true
|
178
|
+
end
|
179
|
+
|
180
|
+
def reload!
|
181
|
+
@next_link = query_path
|
182
|
+
@internal_values = []
|
183
|
+
fetch_next_page
|
184
|
+
end
|
185
|
+
|
186
|
+
private
|
187
|
+
|
188
|
+
def last?
|
189
|
+
@loaded || @internal_values.size >= 1000
|
190
|
+
end
|
191
|
+
|
192
|
+
def fetch_next_page
|
193
|
+
@next_link ||= query_path
|
194
|
+
result = begin
|
195
|
+
@graph.service.get(@next_link)
|
196
|
+
rescue OData::ClientError => e
|
197
|
+
if matches = /Unsupported sort property '([^']*)'/.match(e.message)
|
198
|
+
raise MicrosoftGraph::TypeError.new("Cannot sort by #{matches[1]}")
|
199
|
+
elsif /OrderBy not supported/.match(e.message)
|
200
|
+
if @order_by.length == 1
|
201
|
+
raise MicrosoftGraph::TypeError.new("Cannot sort by #{@order_by.first}")
|
202
|
+
else
|
203
|
+
raise MicrosoftGraph::TypeError.new("Cannot sort by at least one field requested")
|
204
|
+
end
|
205
|
+
else
|
206
|
+
raise e
|
207
|
+
end
|
208
|
+
end
|
209
|
+
@next_link = result[:attributes]['@odata.next_link']
|
210
|
+
result[:attributes]['value'].each do |entity_hash|
|
211
|
+
klass =
|
212
|
+
if member_type = specified_member_type(entity_hash)
|
213
|
+
ClassBuilder.get_namespaced_class(member_type.name)
|
214
|
+
else
|
215
|
+
default_member_class
|
216
|
+
end
|
217
|
+
@internal_values.push klass.new(attributes: entity_hash, parent: self, persisted: true)
|
218
|
+
end
|
219
|
+
@loaded = result[:attributes]['@odata.next_link'].nil?
|
220
|
+
end
|
221
|
+
|
222
|
+
def default_member_class
|
223
|
+
ClassBuilder.get_namespaced_class(type.member_type.name)
|
224
|
+
end
|
225
|
+
|
226
|
+
def specified_member_type(entity_hash)
|
227
|
+
@graph.service.get_type_for_odata_response(entity_hash)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|