module Rubysite

Provides a web interface for including modules

Constants

VERSION

Public Class Methods

define_method_route(base, command, route_prefix='/') click to toggle source

Defines the route for the given command on the given base. The resulting route will be prefixed with the given route_prefix.

@param [Module] base the Module which contains the specified command Method @param [Symbol] command the symbol representing the name of the command for which an interface should be generated @param [String] route_prefix a route pattern to prefix on routes which will be generated in response to this call @return [Array] a String array listing the routes which were defined for the given base Module

# File lib/rubysite.rb, line 146
def self.define_method_route(base, command, route_prefix='/')
  base = Kernel.const_get(base.to_sym) if base.class == String
  defined_route = "#{route_prefix}/#{command.to_s}"
  docs = Rubycom::Documentation.get_doc(base.public_method(command))
  param_defs = Rubycom::Arguments.get_param_definitions(base.public_method(command))
  route_params = param_defs.map { |key, val_hsh| (val_hsh[:type] == :opt) ? {":#{key}?" => val_hsh[:default]} : {":#{key}" => val_hsh[:default]} }.reduce(&:merge) || {}
  Sinatra::Base::get "#{defined_route}/?" do
    begin
      rubysite_out = ''
      def rubysite_out.write(data)
        self << data
      end
      rubysite_err = ''
      def rubysite_err.write(data)
        self << data
      end
      o_stdout, $stdout = $stdout, rubysite_out
      o_stderr, $stderr = $stderr, rubysite_err

      puts Rubycom.call_method(base, command, params.map { |key, val| "--#{key}=#{val}" })

      layout = {
          name: "#{base}",
          back_link: route_prefix,
          nav_entries: [
              {link: route_prefix, link_name: route_prefix.split('/').last || 'Home', doc: 'Parent Module'},
              {link: "/help", link_name: "Help", doc: 'Interface documentation'}
          ]
      }
      result = {
          params: params,
          query: request.query_string,
          param_defs: param_defs,
          inputs: route_params.merge(params),
          docs: docs,
          output: rubysite_out,
          error: rubysite_err
      }
      erb(:"method/result", locals: {layout: layout, result: result})

    rescue Exception => e
      layout = {
          name: "#{base}",
          back_link: route_prefix,
          nav_entries: [
              {link: route_prefix, link_name: route_prefix.split('/').last || 'Home', doc: 'Parent Module'},
              {link: "/help", link_name: "Help", doc: 'Interface documentation'}
          ]
      }
      error = {
          base: base,
          message: e.message
      }
      erb(:"method/error", locals: {layout: layout, error: error})
    ensure
      $stdout = o_stdout
      $stderr = o_stderr
    end
  end
  defined_route
end
define_module_route(base, route_prefix='/') click to toggle source

Recursively defines routes for the web service according to the commands included in the given base Module. Starts at the given route_prefix.

@param [Module] base the Module for which a web interface should be generated @param [String] route_prefix a route pattern to prefix on routes which will be generated in response to this call @return [Array] a String array listing the routes which were defined for the given base Module

# File lib/rubysite.rb, line 103
def self.define_module_route(base, route_prefix='/')
  base = Kernel.const_get(base.to_sym) if base.class == String
  defined_routes = ["#{route_prefix.chomp('/')}/#{base.to_s}"]

  commands = Rubycom::Commands.get_top_level_commands(base).select { |sym| sym != :Rubysite } || []

  commands = commands.map { |command_sym|
    if base.included_modules.map { |mod| mod.name.to_sym }.include?(command_sym)
      defined_routes << Rubysite.define_module_route(base.included_modules.select { |mod| mod.name == command_sym.to_s }.first, defined_routes[0])
    else
      defined_routes << Rubysite.define_method_route(base, command_sym, defined_routes[0])
    end
    {
        link: "#{defined_routes[0]}/#{command_sym.to_s}",
        link_name: "#{command_sym.to_s}",
        doc: Rubycom::Documentation.get_command_summary(base, command_sym, Rubycom::Documentation.get_separator(command_sym, Rubycom::Commands.get_longest_command_name(base).length)).gsub(command_sym.to_s, '')
    }
  } || []

  Sinatra::Base::get "#{defined_routes[0]}/?" do
    layout = {
        name: "#{base}",
        back_link: route_prefix,
        doc: Rubycom::Documentation.get_module_doc(base.to_s),
        nav_entries: [
            {link: route_prefix, link_name: route_prefix.split('/').last || 'Home', doc: 'Back'},
        ] + commands + [ {link: "/help", link_name: "Help", doc: 'Interface documentation'} ]
    }
    command_list = {
        command_list: commands
    }
    erb(:"module/command_list", locals: {layout: layout, command_list: command_list})
  end

  defined_routes.flatten
end
define_routes(base) click to toggle source

Recursively defines routes for the web service according to the commands included in the given base Module. Starts at ‘/’. Additionally defines any default routes required by the web service.

@param [Module] base the Module for which a web interface should be generated @return [Array] a String array listing the routes which were defined for the given base Module

# File lib/rubysite.rb, line 54
def self.define_routes(base)
  base = Kernel.const_get(base.to_sym) if base.class == String
  site_map = ['/', '/css', '/help'] + Rubysite.define_module_route(base)

  Sinatra::Base::get "/?" do
    layout = {
        name: "#{base}",
        doc: "A Rubysite generated service",
        nav_entries: [
            {link: '/', link_name: 'Home', doc: 'Home'},
            {link: "/#{base}", link_name: "#{base}", doc: Rubycom::Documentation.get_module_doc(base)},
            {link: "/help", link_name: "Help", doc: 'Interface documentation'}
        ]
    }
    erb(:index, locals: {layout: layout})
  end

  Sinatra::Base::get "/css/:css_name?" do |css_name|
    css_sym = css_name.to_sym rescue :default
    css_file = settings.css_files[css_sym] || settings.css_files[:default]
    File.read(css_file)
  end

  Sinatra::Base::get "/help" do
    layout = {
        name: "Help",
        back_link: "/",
        doc: "Help page",
        nav_entries: [
            {link: '/', link_name: 'Home', doc: 'Home'},
            {link: "/#{base}", link_name: "#{base}", doc: Rubycom::Documentation.get_module_doc(base)},
            {link: "/help", link_name: "Help", doc: 'Interface documentation'}
        ]
    }
    help = {
        site_map: site_map.flatten
    }
    erb(:help, locals: {layout: layout, help: help})
  end

  site_map.flatten
end
included(base) click to toggle source

Detects that Rubysite was included in another module and calls Rubysite#run

@param [Module] base the module which invoked ‘include Rubysite’

# File lib/rubysite.rb, line 15
def self.included(base)
  base_file_path = caller.first.gsub(/:\d+:.+/, '')
  if base.class == Module && (base_file_path == $0 || Rubycom.is_executed_by_gem?(base_file_path))
    base.module_eval {
      Rubysite.run(base, ARGV)
    }
  end
end
run(base, args=[]) click to toggle source

Defines routes for all commands found in the including module and starts the web server

@param [Module] base the module which invoked ‘include Rubysite’ @param [Array] args a String Array representing environment settings for the web server

# File lib/rubysite.rb, line 28
def self.run(base, args=[])
  args = [args] if args.class == String
  base = Kernel.const_get(base.to_sym) if base.class == String
  begin
    raise SiteError, "Invalid base class invocation: #{base}" if base.nil?
    Sinatra::Base::set :port, '8080'
    Sinatra::Base::set :port, args[1] if !args[0].nil? && args[0] == '--port'
    Sinatra::Base::set :port, args[0].split('=').last if !args[0].nil? && args[0].include?('--port=')
    Sinatra::Base::set :root, Proc.new { File.join(File.expand_path(File.dirname(__FILE__)), 'rubysite') }
    Sinatra::Base::set :public_folder, Proc.new { File.join(File.expand_path(File.dirname(__FILE__)), 'rubysite', 'public') }
    Sinatra::Base::set :views, Proc.new { File.join(File.expand_path(File.dirname(__FILE__)), 'rubysite', 'views') }
    Sinatra::Base::set :css_files, {default: File.join(File.expand_path(File.dirname(__FILE__)), 'rubysite', 'public', 'css', 'default.css')}

    Rubysite.define_routes(base)

    Sinatra::Base::run!
  rescue SiteError => e
    $stderr.puts e
  end
end