class ZendeskAPI::Association

Represents an association between two resources @private

Attributes

options[R]

@return [Hash] Options passed into the association

Public Class Methods

class_from_namespace(klass_as_string) click to toggle source
# File lib/zendesk_api/association.rb, line 12
def class_from_namespace(klass_as_string)
  namespaces.each do |ns|
    if module_defines_class?(ns, klass_as_string)
      return ns.const_get(klass_as_string)
    end
  end

  nil
end
module_defines_class?(mod, klass_as_string) click to toggle source
# File lib/zendesk_api/association.rb, line 22
def module_defines_class?(mod, klass_as_string)
  mod.const_defined?(klass_as_string, false)
end
namespaces() click to toggle source
# File lib/zendesk_api/association.rb, line 8
def namespaces
  [ZendeskAPI] + ZendeskAPI::DataNamespace.descendants
end
new(options = {}) click to toggle source

Options to pass in

  • class - Required

  • parent - Parent instance

  • path - Optional path instead of resource name

# File lib/zendesk_api/association.rb, line 34
def initialize(options = {})
  @options = SilentMash.new(options)
end

Public Instance Methods

generate_path(*args) click to toggle source

Generate a path to the resource. id and <parent>_id attributes will be deleted from passed in options hash if they are used in the built path. Arguments that can be passed in: An instance, any resource instance Hash Options:

  • with_parent - Include the parent path (false by default)

  • with_id - Include the instance id, if possible (true)

# File lib/zendesk_api/association.rb, line 45
def generate_path(*args)
  options = SilentMash.new(:with_id => true)
  if args.last.is_a?(Hash)
    original_options = args.pop
    options.merge!(original_options)
  end

  instance = args.first

  namespace = @options[:class].to_s.split("::")
  namespace[-1] = @options[:class].resource_path
  # Remove components without path information
  ignorable_namespace_strings.each { |ns| namespace.delete(ns) }
  has_parent = namespace.size > 1 || (options[:with_parent] && @options.parent)

  if has_parent
    parent_class = @options.parent ? @options.parent.class : Association.class_from_namespace(ZendeskAPI::Helpers.modulize_string(namespace[0]))
    parent_namespace = build_parent_namespace(parent_class, instance, options, original_options)
    namespace[1..1] = parent_namespace if parent_namespace
    namespace[0] = parent_class.resource_path
  else
    namespace[0] = @options.path || @options[:class].resource_path
  end

  if id = extract_id(instance, options, original_options)
    namespace << id
  end

  namespace.join("/")
end
side_load(resources, side_loads) click to toggle source

Tries to place side loads onto given resources.

# File lib/zendesk_api/association.rb, line 77
def side_load(resources, side_loads)
  key = "#{options.name}_id"
  plural_key = "#{Inflection.singular options.name.to_s}_ids"

  resources.each do |resource|
    if resource.key?(plural_key) # Grab associations from child_ids field on resource
      side_load_from_child_ids(resource, side_loads, plural_key)
    elsif resource.key?(key) || options.singular
      side_load_from_child_or_parent_id(resource, side_loads, key)
    else # Grab associations from parent_id field from multiple child resources
      side_load_from_parent_id(resource, side_loads, key)
    end
  end
end

Private Instance Methods

_side_load(resource, side_loads) click to toggle source
# File lib/zendesk_api/association.rb, line 99
def _side_load(resource, side_loads)
  side_loads.map! do |side_load|
    resource.send(:wrap_resource, side_load, options)
  end

  ZendeskAPI::Collection.new(resource.client, options[:class]).tap do |collection|
    collection.replace(side_loads)
  end
end
build_parent_namespace(parent_class, instance, options, original_options) click to toggle source
# File lib/zendesk_api/association.rb, line 144
def build_parent_namespace(parent_class, instance, options, original_options)
  path = @options.path

  association_on_parent = parent_class.associations.detect { |a| a[:name] == @options[:name] }
  association_on_parent ||= parent_class.associations.detect do |a|
    !a[:inline] && a[:class] == @options[:class]
  end

  if association_on_parent
    path ||= association_on_parent[:path]
    path ||= association_on_parent[:name].to_s
  end

  path ||= @options[:class].resource_path

  [
    extract_parent_id(parent_class, instance, options, original_options),
    path
  ]
end
extract_id(instance, options, original_options) click to toggle source
# File lib/zendesk_api/association.rb, line 179
def extract_id(instance, options, original_options)
  if options[:with_id] && !@options[:class].ancestors.include?(SingularResource)
    if instance && instance.id
      instance.id
    elsif options[:id]
      original_options.delete(:id) || original_options.delete("id")
    end
  end
end
extract_parent_id(parent_class, instance, options, original_options) click to toggle source
# File lib/zendesk_api/association.rb, line 165
def extract_parent_id(parent_class, instance, options, original_options)
  parent_id_column = "#{parent_class.singular_resource_name}_id"

  if @options.parent
    @options.parent.id
  elsif instance
    instance.send(parent_id_column)
  elsif options[parent_id_column]
    original_options.delete(parent_id_column) || original_options.delete(parent_id_column.to_sym)
  else
    raise ArgumentError.new("#{@options[:class].resource_name} requires #{parent_id_column} or parent")
  end
end
ignorable_namespace_strings() click to toggle source

@return [Array<String>] [‘ZendeskAPI’, ‘Voice’, etc.. ]

# File lib/zendesk_api/association.rb, line 95
def ignorable_namespace_strings
  ZendeskAPI::DataNamespace.descendants.map { |klass| klass.to_s.split('::') }.flatten.uniq
end
side_load_from_child_ids(resource, side_loads, plural_key) click to toggle source
# File lib/zendesk_api/association.rb, line 117
def side_load_from_child_ids(resource, side_loads, plural_key)
  ids = resource.send(plural_key)

  resource.send("#{options.name}=", _side_load(resource, side_loads.select {|side_load|
    ids.include?(side_load[options.include_key])
  }))
end
side_load_from_child_or_parent_id(resource, side_loads, key) click to toggle source
# File lib/zendesk_api/association.rb, line 125
def side_load_from_child_or_parent_id(resource, side_loads, key)
  # Either grab association from child_id field on resource or parent_id on child resource
  if resource.key?(key)
    id = resource.send(key)
    include_key = options.include_key
  else
    id = resource.id
    include_key = "#{resource.class.singular_resource_name}_id"
  end

  return unless id

  side_load = side_loads.detect do |side_load|
    id == side_load[include_key]
  end

  resource.send("#{options.name}=", side_load) if side_load
end
side_load_from_parent_id(resource, side_loads, key) click to toggle source
# File lib/zendesk_api/association.rb, line 109
def side_load_from_parent_id(resource, side_loads, key)
  key = "#{resource.class.singular_resource_name}_id"

  resource.send("#{options.name}=", _side_load(resource, side_loads.select {|side_load|
    side_load[key] == resource.id
  }))
end