Class: OData::Service

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_odata/service.rb

Overview

The main service class, also known as a Context

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (Service) initialize(service_uri, options = {})

Creates a new instance of the Service class

Parameters:

  • service_uri (String)

    the root URI of the OData service

  • options (Hash) (defaults to: {})

    the options to pass to the service

Options Hash (options):

  • :username (String)

    for http basic auth

  • :password (String)

    for http basic auth

  • :verify_ssl (Object)

    false if no verification, otherwise mode (OpenSSL::SSL::VERIFY_PEER is default)

  • :rest_options (Hash)

    a hash of rest-client options that will be passed to all RestClient::Resource.new calls

  • :additional_params (Hash)

    a hash of query string params that will be passed on all calls

  • :eager_partial (Boolean, true)

    true if queries should consume partial feeds until the feed is complete, false if explicit calls to next must be performed



15
16
17
18
19
20
21
# File 'lib/ruby_odata/service.rb', line 15

def initialize(service_uri, options = {})
  @uri = service_uri.gsub!(/\/?$/, '')
  set_options! options
  default_instance_vars!
  set_namespaces
  build_collections_and_classes
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

- (Object) method_missing(name, *args)

Handles the dynamic AddTo<EntityName> methods as well as the collections on the service



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/ruby_odata/service.rb', line 24

def method_missing(name, *args)
  # Queries
  if @collections.include?(name.to_s)
    root = "/#{name.to_s}"
    root << "(#{args.join(',')})" unless args.empty?
    @query = QueryBuilder.new(root, @additional_params)
    return @query
  # Adds
  elsif name.to_s =~ /^AddTo(.*)/
    type = $1
    if @collections.include?(type)
      @save_operations << Operation.new("Add", $1, args[0])
    else
      super
    end
  elsif @function_imports.include?(name.to_s)
    execute_import_function(name.to_s, args)
  else
    super
  end
end

Instance Attribute Details

- (Object) class_metadata (readonly)

Returns the value of attribute class_metadata



4
5
6
# File 'lib/ruby_odata/service.rb', line 4

def 
  @class_metadata
end

- (Object) classes (readonly)

Returns the value of attribute classes



4
5
6
# File 'lib/ruby_odata/service.rb', line 4

def classes
  @classes
end

- (Object) collections (readonly)

Returns the value of attribute collections



4
5
6
# File 'lib/ruby_odata/service.rb', line 4

def collections
  @collections
end

- (Object) edmx (readonly)

Returns the value of attribute edmx



4
5
6
# File 'lib/ruby_odata/service.rb', line 4

def edmx
  @edmx
end

- (Object) function_imports (readonly)

Returns the value of attribute function_imports



4
5
6
# File 'lib/ruby_odata/service.rb', line 4

def function_imports
  @function_imports
end

- (Object) options (readonly)

Returns the value of attribute options



4
5
6
# File 'lib/ruby_odata/service.rb', line 4

def options
  @options
end

Instance Method Details

Adds a child object to a parent object's collection

Parameters:

  • parent (Object)

    the parent object

  • nav_prop (String)

    the name of the navigation property to add the child to

  • child (Object)

    the child object

Raises:

  • (NotSupportedError)

    if the parent isn't a tracked entity

  • (ArgumentError)

    if the nav_prop isn't a valid navigation property

  • (NotSupportedError)

    if the child isn't a tracked entity



160
161
162
163
164
165
166
# File 'lib/ruby_odata/service.rb', line 160

def add_link(parent, nav_prop, child)
  raise NotSupportedError, "You cannot add a link on an entity that isn't tracked (#{parent.class})" if parent.send(:__metadata).nil?
  raise ArgumentError, "'#{nav_prop}' is not a valid navigation property for #{parent.class}" unless parent.respond_to?(nav_prop.to_sym)
  raise ArgumentError, "'#{nav_prop}' is not a valid navigation property for #{parent.class}" unless @class_metadata[parent.class.to_s][nav_prop].nav_prop
  raise NotSupportedError, "You cannot add a link on a child entity that isn't tracked (#{child.class})" if child.send(:__metadata).nil?
  @save_operations << Operation.new("AddLink", nav_prop, parent, child)
end

- (Object) delete_object(obj)

Queues an object for deletion. To actually remove it from the server, you must call save_changes as well.

Parameters:

  • obj (Object)

    the object to mark for deletion

Raises:



51
52
53
54
55
56
57
58
# File 'lib/ruby_odata/service.rb', line 51

def delete_object(obj)
  type = obj.class.to_s
  if obj.respond_to?(:__metadata) && !obj.send(:__metadata).nil?
    @save_operations << Operation.new("Delete", type, obj)
  else
    raise OData::NotSupportedError.new "You cannot delete a non-tracked entity"
  end
end

- (Object) execute

Performs query operations (Read) against the server. Typically this returns an array of record instances, except in the case of count queries



99
100
101
102
103
# File 'lib/ruby_odata/service.rb', line 99

def execute
  result = RestClient::Resource.new(build_query_uri, @rest_options).get
  return Integer(result) if result =~ /^\d+$/
  handle_collection_result(result)
end

- (Object) load_property(obj, nav_prop)

Lazy loads a navigation property on a model

Parameters:

  • obj (Object)

    the object to fill

  • nav_prop (String)

    the navigation property to fill

Raises:

  • (NotSupportedError)

    if the obj isn't a tracked entity

  • (ArgumentError)

    if the nav_prop isn't a valid navigation property



143
144
145
146
147
148
149
150
# File 'lib/ruby_odata/service.rb', line 143

def load_property(obj, nav_prop)
  raise NotSupportedError, "You cannot load a property on an entity that isn't tracked" if obj.send(:__metadata).nil?
  raise ArgumentError, "'#{nav_prop}' is not a valid navigation property" unless obj.respond_to?(nav_prop.to_sym)
  raise ArgumentError, "'#{nav_prop}' is not a valid navigation property" unless @class_metadata[obj.class.to_s][nav_prop].nav_prop
  results = RestClient::Resource.new(build_load_property_uri(obj, nav_prop), @rest_options).get
  prop_results = build_classes_from_result(results)
  obj.send "#{nav_prop}=", (singular?(nav_prop) ? prop_results.first : prop_results)
end

- (Object) next

Retrieves the next resultset of a partial result (if any). Does not honor the :eager_partial option.



126
127
128
129
# File 'lib/ruby_odata/service.rb', line 126

def next
  return if not partial?
  handle_partial
end

- (Boolean) partial?

Does the most recent collection returned represent a partial collection? Will aways be false if a query hasn't executed, even if the query would have a partial

Returns:

  • (Boolean)


132
133
134
# File 'lib/ruby_odata/service.rb', line 132

def partial?
  @has_partial
end

- (Boolean) respond_to?(method)

Overridden to identify methods handled by method_missing

Returns:

  • (Boolean)


106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/ruby_odata/service.rb', line 106

def respond_to?(method)
  if @collections.include?(method.to_s)
    return true
  # Adds
  elsif method.to_s =~ /^AddTo(.*)/
    type = $1
    if @collections.include?(type)
      return true
    else
      super
    end
  # Function Imports
  elsif @function_imports.include?(method.to_s)
    return true
  else
    super
  end
end

- (Object) save_changes

Performs save operations (Create/Update/Delete) against the server



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/ruby_odata/service.rb', line 75

def save_changes
  return nil if @save_operations.empty?

  result = nil

  begin
    if @save_operations.length == 1
      result = single_save(@save_operations[0])
    else
      result = batch_save(@save_operations)
    end

    # TODO: We should probably perform a check here
    # to make sure everything worked before clearing it out
    @save_operations.clear

    return result
  rescue Exception => e
    handle_exception(e)
  end
end

- (Object) update_object(obj)

Queues an object for update. To actually update it on the server, you must call save_changes as well.

Parameters:

  • obj (Object)

    the object to queue for update

Raises:



65
66
67
68
69
70
71
72
# File 'lib/ruby_odata/service.rb', line 65

def update_object(obj)
  type = obj.class.to_s
  if obj.respond_to?(:__metadata) && !obj.send(:__metadata).nil?
    @save_operations << Operation.new("Update", type, obj)
  else
    raise OData::NotSupportedError.new "You cannot update a non-tracked entity"
  end
end