Class: OandaAPI::Client::NamespaceProxy

Inherits:
Object
  • Object
show all
Defined in:
lib/oanda_api/client/namespace_proxy.rb

Overview

A client proxy and method-chaining enabler.

Examples:

Example usage

client  = OandaAPI::Client::TokenClient.new :practice, token
 = client.(1234) # => OandaAPI::Client::NamespaceProxy
.get                    # => OandaAPI::Resource::Account
.orders.get             # => OandaAPI::Resource::ResourceCollection

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client, namespace_segment, conditions) ⇒ NamespaceProxy


31
32
33
34
35
36
37
38
39
40
# File 'lib/oanda_api/client/namespace_proxy.rb', line 31

def initialize(client, namespace_segment, conditions)
  fail ArgumentError, "expecting an OandaAPI::Client instance" unless
    client && client.is_a?(OandaAPI::Client) || client.is_a?(OandaAPI::Streaming::Client)
  fail ArgumentError, "expecting a namespace value" if namespace_segment.to_s.empty?

  @client = client
  @conditions = {}
  @namespace_segments = [Utils.pluralize(namespace_segment)]
  extract_key_and_conditions conditions
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(sym, *args) {|OandaAPI::ResourceBase| ... } ⇒ void, ...

Executes an API request and returns a resource object, or returns a clone of self for method chaining.

Yields:


104
105
106
107
108
109
110
111
112
113
114
# File 'lib/oanda_api/client/namespace_proxy.rb', line 104

def method_missing(sym, *args, &block)
  # Check for terminating method
  if [:create, :close, :delete, :get, :update, :stream].include?(sym)
    @client.execute_request sym, namespace, conditions, &block
  else
    ns = self.clone
    ns.namespace_segments << Utils.pluralize(sym)
    ns.extract_key_and_conditions args.first
    ns
  end
end

Instance Attribute Details

#conditionsHash


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
110
111
112
113
114
115
# File 'lib/oanda_api/client/namespace_proxy.rb', line 18

class NamespaceProxy
  attr_accessor :conditions, :namespace_segments

  # @param [OandaAPI::Client] client
  #
  # @param [String] namespace_segment a _segment_ in a resource's URI. An
  #   ordered list of segments, joined, creates a path to a resource URI.
  #
  # @param [Hash] conditions an optional list of parameters that typically
  #   specifies conditions and filters for a resource request. A _"key"_
  #   or _"id"_ is a condition that identifies a particular resource. If a
  #   key condition is included, it is extracted and added as a namespace
  #   segment. See {#extract_key_and_conditions}.
  def initialize(client, namespace_segment, conditions)
    fail ArgumentError, "expecting an OandaAPI::Client instance" unless
      client && client.is_a?(OandaAPI::Client) || client.is_a?(OandaAPI::Streaming::Client)
    fail ArgumentError, "expecting a namespace value" if namespace_segment.to_s.empty?

    @client = client
    @conditions = {}
    @namespace_segments = [Utils.pluralize(namespace_segment)]
    extract_key_and_conditions conditions
  end

  # Returns a deep clone of `self`.
  # @return [NamespaceProxy]
  def clone
    ns = self.dup
    ns.conditions = conditions.dup
    ns.namespace_segments = namespace_segments.dup
    ns
  end

  # Returns the namespace (URI path to a resource).
  # @return [String]
  def namespace
    "/" + @namespace_segments.join("/")
  end

  # Extracts a _key_ parameter from the arguments.
  # If a key is found, it's appended to the list namespace segments. Non-key
  # parameters are merged into the {#conditions} collection. A parameter is a
  # key if it's named ":id", or if there is only a single scalar argument.
  #
  # @example "key" parameters
  #  client  = OandaAPI::Client::TokenClient.new :practice, token
  #  account = client.account(1234)                  # 1234 is a _key_ (accountId)
  #  account.namespace                               # => /accounts/1234
  #
  #  order = account.order(instrument: "USD_JPY",
  #                              type: "market",
  #                             units: 10_000,
  #                              side: "buy").create # No key parameters here
  #
  #  position = account.position("USD_JPY").get      # USD_JPY is a key
  #
  # @param conditions either a hash of parameter values, single scalar value, or nil.
  #
  # @return [void]
  def extract_key_and_conditions(conditions)
    key =
      case
      when conditions && conditions.is_a?(Hash)
        @conditions.merge! Utils.rubyize_keys(conditions)
        @conditions.delete :id
      when conditions
        conditions
      end
    @namespace_segments << key if key
  end

  # Executes an API request and returns a resource object, or returns a
  # clone of `self` for method chaining.
  #
  # @yield [OandaAPI::ResourceBase] if the method is `:stream`.
  #
  # @return [void] if the method is `:stream`.
  #
  # @return [OandaAPI::Client::NamespaceProxy] if the method is used
  #   for chaining.
  #
  # @return [OandaAPI::ResourceBase] if the method is one of the supported
  #   _terminating_ methods (`:create`, `:close`, `:delete`, `:get`, `:update`).
  #
  # @return [OandaAPI::ResourceCollection] if the method is `:get` and the
  #   API returns a collection of resources.
  def method_missing(sym, *args, &block)
    # Check for terminating method
    if [:create, :close, :delete, :get, :update, :stream].include?(sym)
      @client.execute_request sym, namespace, conditions, &block
    else
      ns = self.clone
      ns.namespace_segments << Utils.pluralize(sym)
      ns.extract_key_and_conditions args.first
      ns
    end
  end
end

#namespace_segmentsArray<String>


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
110
111
112
113
114
115
# File 'lib/oanda_api/client/namespace_proxy.rb', line 18

class NamespaceProxy
  attr_accessor :conditions, :namespace_segments

  # @param [OandaAPI::Client] client
  #
  # @param [String] namespace_segment a _segment_ in a resource's URI. An
  #   ordered list of segments, joined, creates a path to a resource URI.
  #
  # @param [Hash] conditions an optional list of parameters that typically
  #   specifies conditions and filters for a resource request. A _"key"_
  #   or _"id"_ is a condition that identifies a particular resource. If a
  #   key condition is included, it is extracted and added as a namespace
  #   segment. See {#extract_key_and_conditions}.
  def initialize(client, namespace_segment, conditions)
    fail ArgumentError, "expecting an OandaAPI::Client instance" unless
      client && client.is_a?(OandaAPI::Client) || client.is_a?(OandaAPI::Streaming::Client)
    fail ArgumentError, "expecting a namespace value" if namespace_segment.to_s.empty?

    @client = client
    @conditions = {}
    @namespace_segments = [Utils.pluralize(namespace_segment)]
    extract_key_and_conditions conditions
  end

  # Returns a deep clone of `self`.
  # @return [NamespaceProxy]
  def clone
    ns = self.dup
    ns.conditions = conditions.dup
    ns.namespace_segments = namespace_segments.dup
    ns
  end

  # Returns the namespace (URI path to a resource).
  # @return [String]
  def namespace
    "/" + @namespace_segments.join("/")
  end

  # Extracts a _key_ parameter from the arguments.
  # If a key is found, it's appended to the list namespace segments. Non-key
  # parameters are merged into the {#conditions} collection. A parameter is a
  # key if it's named ":id", or if there is only a single scalar argument.
  #
  # @example "key" parameters
  #  client  = OandaAPI::Client::TokenClient.new :practice, token
  #  account = client.account(1234)                  # 1234 is a _key_ (accountId)
  #  account.namespace                               # => /accounts/1234
  #
  #  order = account.order(instrument: "USD_JPY",
  #                              type: "market",
  #                             units: 10_000,
  #                              side: "buy").create # No key parameters here
  #
  #  position = account.position("USD_JPY").get      # USD_JPY is a key
  #
  # @param conditions either a hash of parameter values, single scalar value, or nil.
  #
  # @return [void]
  def extract_key_and_conditions(conditions)
    key =
      case
      when conditions && conditions.is_a?(Hash)
        @conditions.merge! Utils.rubyize_keys(conditions)
        @conditions.delete :id
      when conditions
        conditions
      end
    @namespace_segments << key if key
  end

  # Executes an API request and returns a resource object, or returns a
  # clone of `self` for method chaining.
  #
  # @yield [OandaAPI::ResourceBase] if the method is `:stream`.
  #
  # @return [void] if the method is `:stream`.
  #
  # @return [OandaAPI::Client::NamespaceProxy] if the method is used
  #   for chaining.
  #
  # @return [OandaAPI::ResourceBase] if the method is one of the supported
  #   _terminating_ methods (`:create`, `:close`, `:delete`, `:get`, `:update`).
  #
  # @return [OandaAPI::ResourceCollection] if the method is `:get` and the
  #   API returns a collection of resources.
  def method_missing(sym, *args, &block)
    # Check for terminating method
    if [:create, :close, :delete, :get, :update, :stream].include?(sym)
      @client.execute_request sym, namespace, conditions, &block
    else
      ns = self.clone
      ns.namespace_segments << Utils.pluralize(sym)
      ns.extract_key_and_conditions args.first
      ns
    end
  end
end

Instance Method Details

#cloneNamespaceProxy

Returns a deep clone of self.


44
45
46
47
48
49
# File 'lib/oanda_api/client/namespace_proxy.rb', line 44

def clone
  ns = self.dup
  ns.conditions = conditions.dup
  ns.namespace_segments = namespace_segments.dup
  ns
end

#extract_key_and_conditions(conditions) ⇒ void

This method returns an undefined value.

Extracts a key parameter from the arguments. If a key is found, it's appended to the list namespace segments. Non-key parameters are merged into the #conditions collection. A parameter is a key if it's named ":id", or if there is only a single scalar argument.

Examples:

"key" parameters

client  = OandaAPI::Client::TokenClient.new :practice, token
 = client.(1234)                  # 1234 is a _key_ (accountId)
.namespace                               # => /accounts/1234

order = .order(instrument: "USD_JPY",
                            type: "market",
                           units: 10_000,
                            side: "buy").create # No key parameters here

position = .position("USD_JPY").get      # USD_JPY is a key

77
78
79
80
81
82
83
84
85
86
87
# File 'lib/oanda_api/client/namespace_proxy.rb', line 77

def extract_key_and_conditions(conditions)
  key =
    case
    when conditions && conditions.is_a?(Hash)
      @conditions.merge! Utils.rubyize_keys(conditions)
      @conditions.delete :id
    when conditions
      conditions
    end
  @namespace_segments << key if key
end

#namespaceString

Returns the namespace (URI path to a resource).


53
54
55
# File 'lib/oanda_api/client/namespace_proxy.rb', line 53

def namespace
  "/" + @namespace_segments.join("/")
end