class Apipie::Application

Attributes

resource_descriptions[R]

Public Class Methods

new() click to toggle source
Calls superclass method
# File lib/apipie/application.rb, line 19
def initialize
  super
  init_env
end

Public Instance Methods

[](resource_name, method_name = nil)
active_dsl?() click to toggle source

Is there a reason to interpret the DSL for this run? with specific setting for some environment there is no reason the dsl should be interpreted (e.g. no validations and doc from cache)

# File lib/apipie/application.rb, line 334
def active_dsl?
  Apipie.configuration.validate? || ! Apipie.configuration.use_cache? || Apipie.configuration.force_dsl?
end
add_param_group(controller, name, &block) click to toggle source
# File lib/apipie/application.rb, line 137
def add_param_group(controller, name, &block)
  key = "#{controller.name}##{name}"
  @param_groups[key] = block
end
api_controllers_paths() click to toggle source
# File lib/apipie/application.rb, line 285
def api_controllers_paths
  Dir.glob(Apipie.configuration.api_controllers_matcher)
end
available_versions() click to toggle source
# File lib/apipie/application.rb, line 24
def available_versions
  @resource_descriptions.keys.sort
end
checksum() click to toggle source
# File lib/apipie/application.rb, line 327
def checksum
  @checksum ||= compute_checksum
end
compute_checksum() click to toggle source
# File lib/apipie/application.rb, line 311
def compute_checksum
  if Apipie.configuration.use_cache?
    file_base = File.join(Apipie.configuration.cache_dir, Apipie.configuration.doc_base_url)
    all_docs = {}
    Dir.glob(file_base + '/*.json').sort.each do |f|
      all_docs[File.basename(f, '.json')] = JSON.parse(File.read(f))
    end
  else
    load_documentation if available_versions == []
    all_docs = Apipie.available_versions.inject({}) do |all, version|
      all.update(version => Apipie.to_json(version))
    end
  end
  Digest::MD5.hexdigest(JSON.dump(all_docs))
end
controller_versions(controller) click to toggle source

recursively searches what versions has the controller specified in resource_description? It's used to derivate the default value of versions for methods.

# File lib/apipie/application.rb, line 123
def controller_versions(controller)
  ret = @controller_versions[controller]
  return ret unless ret.empty?
  if controller == ActionController::Base || controller.nil?
    return [Apipie.configuration.default_version]
  else
    return controller_versions(controller.superclass)
  end
end
define_method_description(controller, method_name, dsl_data) click to toggle source

create new method api description

# File lib/apipie/application.rb, line 72
def define_method_description(controller, method_name, dsl_data)
  return if ignored?(controller, method_name)
  ret_method_description = nil

  versions = dsl_data[:api_versions] || []
  versions = controller_versions(controller) if versions.empty?

  versions.each do |version|
    resource_name_with_version = "#{version}##{get_resource_name(controller)}"
    resource_description = get_resource_description(resource_name_with_version)

    if resource_description.nil?
      resource_description = define_resource_description(controller, version)
    end

    method_description = Apipie::MethodDescription.new(method_name, resource_description, dsl_data)

    # we create separate method description for each version in
    # case the method belongs to more versions. We return just one
    # becuase the version doesn't matter for the purpose it's used
    # (to wrap the original version with validators)
    ret_method_description ||= method_description
    resource_description.add_method_description(method_description)
  end

  return ret_method_description
end
define_resource_description(controller, version, dsl_data = nil) click to toggle source

create new resource api description

# File lib/apipie/application.rb, line 101
def define_resource_description(controller, version, dsl_data = nil)
  return if ignored?(controller)

  resource_name = get_resource_name(controller)
  resource_description = @resource_descriptions[version][resource_name]
  if resource_description
    # we already defined the description somewhere (probably in
    # some method. Updating just meta data from dsl
    resource_description.update_from_dsl_data(dsl_data) if dsl_data
  else
    resource_description = Apipie::ResourceDescription.new(controller, resource_name, dsl_data, version)

    Apipie.debug("@resource_descriptions[#{version}][#{resource_name}] = #{resource_description}")
    @resource_descriptions[version][resource_name] ||= resource_description
  end

  return resource_description
end
get_method_description(resource_name, method_name = nil) click to toggle source

get api for given method

There are two ways how this method can be used: 1) Specify both parameters

resource_name:
    controller class - UsersController
    string with resource name (plural) and version - "v1#users"
method_name: name of the method (string or symbol)

2) Specify only first parameter:

resource_name: string containing both resource and method name joined
with '#' symbol.
- "users#create" get default version
- "v2#users#create" get specific version
# File lib/apipie/application.rb, line 165
def get_method_description(resource_name, method_name = nil)
  if resource_name.is_a?(String)
    crumbs = resource_name.split('#')
    if method_name.nil?
      method_name = crumbs.pop
    end
    resource_name = crumbs.join("#")
    resource_description = get_resource_description(resource_name)
  elsif resource_name.respond_to? :apipie_resource_descriptions
    resource_description = get_resource_description(resource_name)
  else
    raise ArgumentError.new("Resource #{resource_name} does not exists.")
  end
  unless resource_description.nil?
    resource_description.method_description(method_name.to_sym)
  end
end
Also aliased as: []
get_method_descriptions(resource, method) click to toggle source

get all versions of method description

# File lib/apipie/application.rb, line 222
def get_method_descriptions(resource, method)
  get_resource_descriptions(resource).map do |resource_description|
    resource_description.method_description(method.to_sym)
  end.compact
end
get_param_group(controller, name) click to toggle source
# File lib/apipie/application.rb, line 142
def get_param_group(controller, name)
  key = "#{controller.name}##{name}"
  if @param_groups.has_key?(key)
    return @param_groups[key]
  else
    raise "param group #{key} not defined"
  end
end
get_resource_description(resource, version = nil) click to toggle source

options:

> “users”

> “v2#users”

> V2::UsersController

# File lib/apipie/application.rb, line 188
def get_resource_description(resource, version = nil)
  if resource.is_a?(String)
    crumbs = resource.split('#')
    if crumbs.size == 2
      version = crumbs.first
    end
    version ||= Apipie.configuration.default_version
    if @resource_descriptions.has_key?(version)
      return @resource_descriptions[version][crumbs.last]
    end
  else
    resource_name = get_resource_name(resource)
    if version
      resource_name = "#{version}##{resource_name}"
    end

    if resource_name.nil?
      return nil
    end
    resource_description = get_resource_description(resource_name)
    if resource_description && resource_description.controller == resource
      return resource_description
    end
  end
end
get_resource_descriptions(resource) click to toggle source

get all versions of resource description

# File lib/apipie/application.rb, line 215
def get_resource_descriptions(resource)
  available_versions.map do |version|
    get_resource_description(resource, version)
  end.compact
end
get_resource_name(klass) click to toggle source
# File lib/apipie/application.rb, line 338
def get_resource_name(klass)
  if klass.class == String
    klass
  elsif @controller_to_resource_id.has_key?(klass)
    @controller_to_resource_id[klass]
  elsif Apipie.configuration.namespaced_resources? && klass.respond_to?(:controller_path)
    return nil if klass == ActionController::Base
    path = klass.controller_path
    path.gsub(version_prefix(klass), "").gsub("/", "-")
  elsif klass.respond_to?(:controller_name)
    return nil if klass == ActionController::Base
    klass.controller_name
  else
    raise "Apipie: Can not resolve resource #{klass} name."
  end
end
init_env() click to toggle source

initialize variables for gathering dsl data

# File lib/apipie/application.rb, line 238
def init_env
  @resource_descriptions = HashWithIndifferentAccess.new { |h, version| h[version] = {} }
  @controller_to_resource_id = {}
  @param_groups = {}

  # what versions does the controller belong in (specified by resource_description)?
  @controller_versions = Hash.new { |h, controller| h[controller] = [] }
end
load_documentation() click to toggle source
# File lib/apipie/application.rb, line 304
def load_documentation
  if !@documentation_loaded || Apipie.configuration.reload_controllers?
    Apipie.reload_documentation
    @documentation_loaded = true
  end
end
locale() click to toggle source
# File lib/apipie/application.rb, line 355
def locale
  Apipie.configuration.locale.call(nil) if Apipie.configuration.locale
end
locale=(locale) click to toggle source
# File lib/apipie/application.rb, line 359
def locale=(locale)
  Apipie.configuration.locale.call(locale) if Apipie.configuration.locale
end
rails_routes(route_set = nil) click to toggle source
# File lib/apipie/application.rb, line 32
def rails_routes(route_set = nil)
  if route_set.nil? && @rails_routes
    return @rails_routes
  end
  route_set ||= Rails.application.routes
  # ensure routes are loaded
  Rails.application.reload_routes! unless Rails.application.routes.routes.any?

  flatten_routes = []

  route_set.routes.each do |route|
    if route.app.respond_to?(:routes) && route.app.routes.is_a?(ActionDispatch::Routing::RouteSet)
      # recursively go though the moutned engines
      flatten_routes.concat(rails_routes(route.app.routes))
    else
      flatten_routes << route
    end
  end

  @rails_routes = flatten_routes
end
recorded_examples() click to toggle source
# File lib/apipie/application.rb, line 247
def recorded_examples
  return @recorded_examples if @recorded_examples
  @recorded_examples = Apipie::Extractor::Writer.load_recorded_examples
end
reload_documentation() click to toggle source
# File lib/apipie/application.rb, line 289
def reload_documentation
  # don't load translated strings, we'll translate them later
  old_locale = locale
  locale = Apipie.configuration.default_locale

  rails_mark_classes_for_reload

  api_controllers_paths.each do |f|
    load_controller_from_file f
  end
  @checksum = nil if Apipie.configuration.update_checksum

  locale = old_locale
end
reload_examples() click to toggle source
# File lib/apipie/application.rb, line 252
def reload_examples
  @recorded_examples = nil
end
remove_method_description(resource, versions, method_name) click to toggle source
# File lib/apipie/application.rb, line 228
def remove_method_description(resource, versions, method_name)
  versions.each do |version|
    resource = get_resource_name(resource)
    if resource_description = get_resource_description("#{version}##{resource}")
      resource_description.remove_method_description(method_name)
    end
  end
end
route_app_controller(app, route, visited_apps = []) click to toggle source

the app might be nested when using contraints, namespaces etc. this method does in depth search for the route controller

# File lib/apipie/application.rb, line 56
def route_app_controller(app, route, visited_apps = [])
  if route.defaults[:controller]
    (route.defaults[:controller].camelize + "Controller").constantize
  end
end
routes_for_action(controller, method, args) click to toggle source
# File lib/apipie/application.rb, line 62
def routes_for_action(controller, method, args)
  routes = rails_routes.select do |route|
    controller == route_app_controller(route.app, route) &&
        method.to_s == route.defaults[:action]
  end

  Apipie.configuration.routes_formatter.format_routes(routes, args)
end
set_controller_versions(controller, versions) click to toggle source
# File lib/apipie/application.rb, line 133
def set_controller_versions(controller, versions)
  @controller_versions[controller] = versions
end
set_resource_id(controller, resource_id) click to toggle source
# File lib/apipie/application.rb, line 28
def set_resource_id(controller, resource_id)
  @controller_to_resource_id[controller] = resource_id
end
to_json(version, resource_name, method_name, lang) click to toggle source
# File lib/apipie/application.rb, line 256
def to_json(version, resource_name, method_name, lang)

  return unless valid_search_args?(version, resource_name, method_name)

  _resources = if resource_name.blank?
    # take just resources which have some methods because
    # we dont want to show eg ApplicationController as resource
    resource_descriptions[version].inject({}) do |result, (k,v)|
      result[k] = v.to_json(nil, lang) unless v._methods.blank?
      result
    end
  else
    [@resource_descriptions[version][resource_name].to_json(method_name, lang)]
  end

  url_args = Apipie.configuration.version_in_url ? version : ''

  {
    :docs => {
      :name => Apipie.configuration.app_name,
      :info => Apipie.app_info(version, lang),
      :copyright => Apipie.configuration.copyright,
      :doc_url => Apipie.full_url(url_args),
      :api_url => Apipie.api_base_url(version),
      :resources => _resources
    }
  }
end
translate(str, locale) click to toggle source
# File lib/apipie/application.rb, line 363
def translate(str, locale)
  if Apipie.configuration.translate
    Apipie.configuration.translate.call(str, locale)
  else
    str
  end
end

Private Instance Methods

get_base_url(version) click to toggle source
# File lib/apipie/application.rb, line 394
def get_base_url(version)
  Apipie.configuration.api_base_url[version]
end
get_resource_version(resource_description) click to toggle source
# File lib/apipie/application.rb, line 398
def get_resource_version(resource_description)
  if resource_description.respond_to? :_version
    resource_description._version
  else
    Apipie.configuration.default_version
  end
end
ignored?(controller, method = nil) click to toggle source
# File lib/apipie/application.rb, line 411
def ignored?(controller, method = nil)
  ignored = Apipie.configuration.ignored
  return true if ignored.include?(controller.name)
  return true if ignored.include?("#{controller.name}##{method}")
end
load_controller_from_file(controller_file) click to toggle source
# File lib/apipie/application.rb, line 406
def load_controller_from_file(controller_file)
  controller_class_name = controller_file.gsub(/\A.*\/app\/controllers\//,"").gsub(/\.\w*\Z/,"").camelize
  controller_class_name.constantize
end
rails_mark_classes_for_reload() click to toggle source

Since Rails 3.2, the classes are reloaded only on file change. We need to reload all the controller classes to rebuild the docs, therefore we just force to reload all the code. This happens only when reload_controllers is set to true and only when showing the documentation.

If cache_classes is set to false, it does nothing, as this would break loading of the controllers.

# File lib/apipie/application.rb, line 425
def rails_mark_classes_for_reload
  unless Rails.application.config.cache_classes
    Rails::VERSION::MAJOR == 4 ? ActionDispatch::Reloader.cleanup! : Rails.application.reloader.reload!
    init_env
    reload_examples
    Rails::VERSION::MAJOR == 4 ? ActionDispatch::Reloader.prepare! : Rails.application.reloader.prepare!
  end
end
valid_search_args?(version, resource_name, method_name) click to toggle source

Make sure that the version/resource_name/method_name are valid combination resource_name and method_name can be nil

# File lib/apipie/application.rb, line 375
def valid_search_args?(version, resource_name, method_name)
  return false unless self.resource_descriptions.has_key?(version)
  if resource_name
    return false unless self.resource_descriptions[version].has_key?(resource_name)
    if method_name
      resource_description = self.resource_descriptions[version][resource_name]
      return false unless resource_description.valid_method_name?(method_name)
    end
  end
  return true
end
version_prefix(klass) click to toggle source
# File lib/apipie/application.rb, line 387
def version_prefix(klass)
  version = controller_versions(klass).first
  base_url = get_base_url(version)
  return "/" if base_url.blank?
  base_url[1..-1] + "/"
end