Module: Rubysite

Defined in:
lib/rubysite.rb,
lib/rubysite/version.rb

Overview

Provides a web interface for including modules

Defined Under Namespace

Classes: SiteError

Constant Summary collapse

VERSION =
"0.0.3"

Class Method Summary collapse

Class Method Details

.define_method_route(base, command, route_prefix = '/') ⇒ Array

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

Parameters:

  • base (Module)

    the Module which contains the specified command Method

  • command (Symbol)

    the symbol representing the name of the command for which an interface should be generated

  • route_prefix (String) (defaults to: '/')

    a route pattern to prefix on routes which will be generated in response to this call

Returns:

  • (Array)

    a String array listing the routes which were defined for the given base Module



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# 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 = '/') ⇒ Array

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

Parameters:

  • base (Module)

    the Module for which a web interface should be generated

  • route_prefix (String) (defaults to: '/')

    a route pattern to prefix on routes which will be generated in response to this call

Returns:

  • (Array)

    a String array listing the routes which were defined for the given base Module



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# 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) ⇒ Array

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.

Parameters:

  • base (Module)

    the Module for which a web interface should be generated

Returns:

  • (Array)

    a String array listing the routes which were defined for the given base Module



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# 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) ⇒ Object

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

Parameters:

  • base (Module)

    the module which invoked ‘include Rubysite’



15
16
17
18
19
20
21
22
# 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 = []) ⇒ Object

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

Parameters:

  • base (Module)

    the module which invoked ‘include Rubysite’

  • args (Array) (defaults to: [])

    a String Array representing environment settings for the web server



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 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