class Assembla::API

Core class responsible for api interface operations

Responsible for providing inspection of api methods

Attributes

root[R]
root?[R]
current_options[RW]

Public Class Methods

after_callbacks() click to toggle source

List of after callbacks

@api public

# File lib/assembla_api/api.rb, line 89
def self.after_callbacks
  @after_callbacks ||= []
end
after_request(callback, params = {}) click to toggle source

After request filter

@api public

# File lib/assembla_api/api.rb, line 103
def self.after_request(callback, params = {})
  after_callbacks << params.merge(callback: callback)
end
before_callbacks() click to toggle source

List of before callbacks

@api public

# File lib/assembla_api/api.rb, line 82
def self.before_callbacks
  @before_callbacks ||= []
end
before_request(callback, params = {}) click to toggle source

Before request filter

@api public

# File lib/assembla_api/api.rb, line 96
def self.before_request(callback, params = {})
  before_callbacks << params.merge(callback: callback)
end
clear_request_methods!() click to toggle source
# File lib/assembla_api/api.rb, line 157
def self.clear_request_methods!
  @request_methods = nil
end
extend_with_actions(child_class) click to toggle source

Returns all API public methods for a given class.

@return [nil]

@api public

# File lib/assembla_api/api/actions.rb, line 11
    def self.extend_with_actions(child_class)
      child_class.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
        def self.actions
          self.new.api_methods_in(#{child_class}) +
          self.new.module_methods_in(#{child_class})
        end

        def actions
          api_methods_in(#{child_class}) + module_methods_in(#{child_class})
        end
      RUBY_EVAL
    end
extra_methods() click to toggle source
# File lib/assembla_api/api.rb, line 138
def self.extra_methods
  ['actions']
end
extract_class_name(name, options) click to toggle source

Extracts class name from options

@param [Hash] options @option options [String] :full_name

the full name for the class

@option options [Boolean] :root

if the class is at the root or not

@return [String]

@api private

# File lib/assembla_api/api.rb, line 328
def self.extract_class_name(name, options)
  converted  = options.fetch(:full_name, name).to_s
  converted  = converted.split('_').map(&:capitalize).join
  class_name = options.fetch(:root, false) ? '': "#{self.name}::"
  class_name += converted
  class_name
end
inherited(child_class) click to toggle source
Calls superclass method
# File lib/assembla_api/api.rb, line 116
def self.inherited(child_class)
  before_callbacks.reverse_each { |callback|
    child_class.before_callbacks.unshift(callback)
  }
  after_callbacks.reverse_each { |callback|
    child_class.after_callbacks.unshift(callback)
  }
  extend_with_actions(child_class)
  unless child_class.instance_variable_defined?(:@root)
    child_class.instance_variable_set(:@root, false)
  end
  super
end
internal_methods() click to toggle source
# File lib/assembla_api/api.rb, line 132
def self.internal_methods
  api = self
  api = api.superclass until api.root?
  api.public_instance_methods(true)
end
method_added(method_name) click to toggle source
# File lib/assembla_api/api.rb, line 161
def self.method_added(method_name)
  method_name = method_name.to_s.gsub(/_with(out)?_callback_.*$/, '')
  # Only subclasses matter
  return if self.root?
  return if extra_methods.include?(method_name)
  # Only public methods are of interest
  return unless request_methods.include?(method_name)
  # Do not redefine
  return if (@__methods_added ||= []).include?(method_name)

  class_name     = self.name.to_s.split('::').last.downcase
  with_method    = "#{method_name}_with_callback_#{class_name}"
  without_method = "#{method_name}_without_callback_#{class_name}"

  return if public_method_defined?(with_method)

  [method_name, with_method, without_method].each do |met|
    @__methods_added << met
  end
  return if public_method_defined?(with_method)

  define_method(with_method) do |*args, &block|
    send(:execute, without_method, *args, &block)
  end
  alias_method without_method, method_name
  alias_method method_name, with_method
  clear_request_methods!
end
namespace(*names) click to toggle source

Defines a namespace

@param [Array] names

the name for the scope

@return [self]

@api public

# File lib/assembla_api/api.rb, line 303
def self.namespace(*names)
  options = names.last.is_a?(Hash) ? names.pop : {}
  names   = names.map(&:to_sym)
  name    = names.pop
  return if public_method_defined?(name)

  class_name = extract_class_name(name, options)
  define_method(name) do |*args, &block|
    options = args.last.is_a?(Hash) ? args.pop : {}
    API::Factory.new(class_name, current_options.merge(options), &block)
  end
  self
end
new(options={}, &block) click to toggle source

Create new API

@api public

# File lib/assembla_api/api.rb, line 45
def initialize(options={}, &block)
  setup(options)
  yield_or_eval(&block) if block_given?
end
request_methods() click to toggle source

Find all the api methods that should be considred by request callbacks.

@return [Set]

@api private

# File lib/assembla_api/api.rb, line 148
def self.request_methods
  @request_methods ||= begin
    methods = (public_instance_methods(true) -
               internal_methods +
               public_instance_methods(false)).uniq.map(&:to_s)
    Set.new(methods - extra_methods)
  end
end
root!() click to toggle source
# File lib/assembla_api/api.rb, line 112
def self.root!
  @root = true
end

Public Instance Methods

api_methods_in(klass) click to toggle source

Finds api methods in a class

@param [Class] klass

The klass to inspect for methods.

@api private

# File lib/assembla_api/api/actions.rb, line 30
def api_methods_in(klass)
  methods = klass.send(:instance_methods, false) - [:actions]
  methods.sort.each_with_object([]) do |method_name, accumulator|
    unless method_name.to_s.include?('with') ||
           method_name.to_s.include?('without')
      accumulator << method_name
    end
    accumulator
  end
end
arguments(args=(not_set = true), options={}, &block) click to toggle source

Acts as setter and getter for api requests arguments parsing.

Returns Arguments instance.

# File lib/assembla_api/api.rb, line 247
def arguments(args=(not_set = true), options={}, &block)
  if not_set
    @arguments
  else
    @arguments = Arguments.new(options.merge!(api: self)).parse(*args, &block)
  end
end
execute(action, *args, &block) click to toggle source

Execute action

@param [Symbol] action

@api private

# File lib/assembla_api/api.rb, line 220
def execute(action, *args, &block)
  action_name = action.to_s.gsub(/_with(out)?_callback_.*$/, '')
  result = nil
  run_callbacks(action_name) do
    result = send(action, *args, &block)
  end
  result
end
filter_callbacks(kind, action_name) click to toggle source

Filter callbacks based on kind

@param [Symbol] kind

one of :before or :after

@return [Array]

@api private

# File lib/assembla_api/api.rb, line 198
def filter_callbacks(kind, action_name)
  matched_callbacks = self.class.send("#{kind}_callbacks").select do |callback|
    callback[:only].nil? || callback[:only].include?(action_name)
  end
end
module_methods_in(klass) click to toggle source

Finds methods included through class modules

@param [Class] klass

The klass to inspect for methods.

@api private

# File lib/assembla_api/api/actions.rb, line 47
def module_methods_in(klass)
  klass.included_modules.each_with_object([]) do |mod, accumulator|
    if mod.to_s =~ /#{klass}/
      mod.instance_methods(false).each do |method|
        accumulator << method
      end
    end
    accumulator
  end
end
process_basic_auth(auth) click to toggle source

Extract login and password from basic_auth parameter

# File lib/assembla_api/api.rb, line 69
def process_basic_auth(auth)
  case auth
  when String
    self.login, self.password = auth.split(':', 2)
  when Hash
    self.login    = auth[:login]
    self.password = auth[:password]
  end
end
run_callbacks(action_name) { || ... } click to toggle source

Run all callbacks associated with this action

@apram [Symbol] action_name

@api private

# File lib/assembla_api/api.rb, line 209
def run_callbacks(action_name, &block)
  filter_callbacks(:before, action_name).each { |hook| send hook[:callback] }
  yield if block_given?
  filter_callbacks(:after, action_name).each { |hook| send hook[:callback] }
end
set(option, value=(not_set=true), ignore_setter=false, &block) click to toggle source

Set a configuration option for a given namespace

@param [String] option @param [Object] value @param [Boolean] ignore_setter

@return [self]

@api public

# File lib/assembla_api/api.rb, line 278
def set(option, value=(not_set=true), ignore_setter=false, &block)
  raise ArgumentError, 'value not set' if block and !not_set
  return self if !not_set and value.nil?

  if not_set
    set_options option
    return self
  end

  if respond_to?("#{option}=") and not ignore_setter
    return __send__("#{option}=", value)
  end

  define_accessors option, value
  self
end
setup(options={}) click to toggle source

Configure options and process basic authorization

@api private

# File lib/assembla_api/api.rb, line 58
def setup(options={})
  options = Assembla.configuration.fetch.merge(options)
  self.current_options = options
  Assembla.configuration.property_names.each do |key|
    send("#{key}=", options[key])
  end
  process_basic_auth(options[:basic_auth])
end
with(args) click to toggle source

Scope for passing request required arguments.

# File lib/assembla_api/api.rb, line 257
def with(args)
  case args
  when Hash
    set args
  when /.*\/.*/i
    user, repo = args.split('/')
    set :user => user, :repo => repo
  else
    ::Kernel.raise ArgumentError, 'This api does not support passed in arguments'
  end
end
yield_or_eval() { |self| ... } click to toggle source
# File lib/assembla_api/api.rb, line 50
def yield_or_eval(&block)
  return unless block
  block.arity > 0 ? yield(self) : self.instance_eval(&block)
end

Private Instance Methods

define_accessors(option, value) click to toggle source

Define setters and getters

@api private

# File lib/assembla_api/api.rb, line 351
def define_accessors(option, value)
  setter = proc { |val|  set option, val, true }
  getter = proc { value }

  define_singleton_method("#{option}=", setter) if setter
  define_singleton_method(option, getter) if getter
end
define_singleton_method(method_name, content=Proc.new) click to toggle source

Dynamically define a method for setting request option

@api private

# File lib/assembla_api/api.rb, line 362
def define_singleton_method(method_name, content=Proc.new)
  (class << self; self; end).class_eval do
    undef_method(method_name) if method_defined?(method_name)
    if String === content
      class_eval("def #{method_name}() #{content}; end")
    else
      define_method(method_name, &content)
    end
  end
end
set_options(options) click to toggle source

Set multiple options

@api private

# File lib/assembla_api/api.rb, line 341
def set_options(options)
  unless options.respond_to?(:each)
    raise ArgumentError, 'cannot iterate over value'
  end
  options.each { |key, value| set(key, value) }
end