module Telnyx::APIOperations::NestedResource

Adds methods to help manipulate a subresource from its parent resource so that it's possible to do so from a static context (i.e. without a pre-existing collection of subresources on the parent).

For example, a transfer gains the static methods for reversals so that the methods `.create_reversal`, `.retrieve_reversal`, `.update_reversal`, etc. all become available. rubocop:disable Metrics/AbcSize rubocop:disable Metrics/MethodLength rubocop:disable Metrics/CyclomaticComplexity

Public Instance Methods

nested_resource_class_methods(resource, path: nil, operations: nil, instance_methods: {}) click to toggle source
# File lib/telnyx/api_operations/nested_resource.rb, line 16
def nested_resource_class_methods(resource, path: nil, operations: nil, instance_methods: {})
  path ||= "#{resource}s"
  path = Array(path).map { |el| CGI.escape(el) }.join("/")
  raise ArgumentError, "operations array required" if operations.nil?

  resource_url_method = :"#{resource}s_url"
  define_singleton_method(resource_url_method) do |id, nested_id = nil|
    # raise ArgumentError, "id is required" if id.nil?
    url = id.nil? ? "#{resource_url}/#{path}" : "#{resource_url}/#{CGI.escape(id)}/#{path}"
    url += "/#{CGI.escape(nested_id)}" unless nested_id.nil?
    url
  end

  # proxy class method to custom instance method
  define_instance_method = lambda do |target_name, operation|
    return unless instance_methods.keys.include? operation

    case operation
    when :create, :list
      define_method(instance_methods[operation] || target_name) do |*opts|
        self.class.send(target_name, id, *opts)
      end
    when :retrieve
      define_method(instance_methods[operation] || target_name) do |nested_id|
        self.class.send(target_name, id, nested_id)
      end
    when :update, :delete
      define_method(instance_methods[operation] || target_name) do |nested_id, *opts|
        self.class.send(target_name, id, nested_id, *opts)
      end
    end
  end

  operations.each do |operation|
    case operation
    when :create
      define_singleton_method(:"create_#{resource}") do |id, params = {}, opts = {}|
        url = send(resource_url_method, id)
        resp, opts = request(:post, url, params, opts)
        Util.convert_to_telnyx_object(resp.data, opts)
      end
      define_instance_method.call(:"create_#{resource}", operation)
    when :retrieve
      define_singleton_method(:"retrieve_#{resource}") do |id, nested_id, opts = {}|
        url = send(resource_url_method, id, nested_id)
        resp, opts = request(:get, url, {}, opts)
        Util.convert_to_telnyx_object(resp.data, opts)
      end
      define_instance_method.call(:"retrieve_#{resource}", operation)
    when :update
      define_singleton_method(:"update_#{resource}") do |id, nested_id, params = {}, opts = {}|
        url = send(resource_url_method, id, nested_id)
        resp, opts = request(:patch, url, params, opts)
        Util.convert_to_telnyx_object(resp.data, opts)
      end
      define_instance_method.call(:"update_#{resource}", operation)
    when :delete
      define_singleton_method(:"delete_#{resource}") do |id, nested_id, params = {}, opts = {}|
        url = send(resource_url_method, id, nested_id)
        resp, opts = request(:delete, url, params, opts)
        Util.convert_to_telnyx_object(resp.data, opts)
      end
      define_instance_method.call(:"delete_#{resource}", operation)
    when :list # TODO: Add a plain :get case here and refactor code that (mis)uses this.
      define_singleton_method(:"list_#{resource}s") do |id, params = {}, opts = {}|
        url = send(resource_url_method, id)
        resp, opts = request(:get, url, params, opts)
        Util.convert_to_telnyx_object(resp.data, opts)
      end
      define_instance_method.call(:"list_#{resource}s", operation)
    else
      raise ArgumentError, "Unknown operation: #{operation.inspect}"
    end
  end
end