tap-server 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/History +4 -0
  2. data/MIT-LICENSE +17 -15
  3. data/README +2 -11
  4. data/cmd/server.rb +27 -41
  5. data/lib/tap/controller.rb +22 -31
  6. data/lib/tap/controllers/app.rb +20 -116
  7. data/lib/tap/controllers/data.rb +16 -1
  8. data/lib/tap/controllers/server.rb +58 -15
  9. data/lib/tap/generator/generators/controller.rb +23 -0
  10. data/lib/tap/server.rb +75 -53
  11. data/lib/tap/tasks/echo.rb +1 -1
  12. data/templates/tap/generator/generators/controller/resource.erb +14 -0
  13. data/templates/tap/generator/generators/controller/test.erb +0 -0
  14. data/templates/tap/generator/generators/controller/view.erb +1 -0
  15. data/views/configurable/configurations.erb +57 -0
  16. data/views/configurable/default.erb +1 -0
  17. data/views/layout.erb +5 -2
  18. data/views/tap/{task → app/api}/help.erb +6 -4
  19. data/views/tap/controller/help.erb +4 -2
  20. data/views/tap/controllers/app/index.erb +47 -0
  21. data/views/tap/controllers/data/_upload.erb +1 -1
  22. data/views/tap/controllers/data/index.erb +16 -5
  23. data/views/tap/controllers/server/index.erb +10 -33
  24. data/views/tap/signals/signal/get.erb +1 -0
  25. data/views/tap/signals/signal/index.erb +4 -0
  26. data/views/tap/signals/signal/post.erb +1 -0
  27. metadata +18 -26
  28. data/lib/tap/controllers/schema.rb +0 -202
  29. data/lib/tap/server/runner.rb +0 -71
  30. data/public/javascripts/prototype.js +0 -4221
  31. data/public/javascripts/tap.js +0 -112
  32. data/views/configurable/_configs.erb +0 -33
  33. data/views/configurable/_flag.erb +0 -2
  34. data/views/configurable/_list_select.erb +0 -6
  35. data/views/configurable/_select.erb +0 -5
  36. data/views/configurable/_switch.erb +0 -2
  37. data/views/tap/controllers/app/_action.erb +0 -3
  38. data/views/tap/controllers/app/build.erb +0 -18
  39. data/views/tap/controllers/app/enque.erb +0 -13
  40. data/views/tap/controllers/app/info.erb +0 -21
  41. data/views/tap/controllers/app/tail.erb +0 -8
  42. data/views/tap/controllers/data/_index_entry.erb +0 -1
  43. data/views/tap/controllers/schema/_build.erb +0 -6
  44. data/views/tap/controllers/schema/_index_entry.erb +0 -6
  45. data/views/tap/controllers/schema/entry.erb +0 -144
  46. data/views/tap/task/input.erb +0 -17
  47. data/views/tap/tasks/load/input.erb +0 -11
@@ -61,6 +61,7 @@ module Tap
61
61
  # POST /projects?_method=put&id=id
62
62
  def destroy(id)
63
63
  data.destroy(type, id)
64
+ deselect([id])
64
65
  redirect uri
65
66
  end
66
67
 
@@ -72,7 +73,21 @@ module Tap
72
73
  end
73
74
 
74
75
  def select(ids=[])
75
- data.cache[type] = ids
76
+ current = data.cache[type] ||= []
77
+ data.cache[type] = current | ids
78
+ redirect uri
79
+ end
80
+
81
+ def deselect(ids=[])
82
+ if current = data.cache[type]
83
+ data.cache[type] = current - ids
84
+ end
85
+ redirect uri
86
+ end
87
+
88
+ def destroy_all(ids=[])
89
+ ids.each {|id| data.destroy(type, id) }
90
+ deselect(ids)
76
91
  redirect uri
77
92
  end
78
93
 
@@ -16,7 +16,24 @@ module Tap
16
16
  include Utils
17
17
 
18
18
  def index
19
- render('index.erb', :layout => true)
19
+ env = server.env
20
+ env_keys = env.minihash(true)
21
+ constants = env.constants
22
+ manifests = env.collect do |current|
23
+ types = {}
24
+ constants.entries(current).minimap.each do |key, const|
25
+ const.types.keys.each do |type|
26
+ (types[type] ||= []) << [key, const]
27
+ end
28
+ end
29
+
30
+ types = types.to_a.sort_by {|type, minimap| type }
31
+ types.empty? ? nil : [env_keys[current], types]
32
+ end
33
+
34
+ render 'index.erb', :locals => {
35
+ :manifests => manifests.compact
36
+ }, :layout => true
20
37
  end
21
38
 
22
39
  # Returns pong
@@ -55,11 +72,12 @@ module Tap
55
72
  end
56
73
  end
57
74
 
58
- def help(type=nil, *key)
59
- if constant = server.env[type][key.join('/')]
60
- module_render 'help.erb', constant
75
+ def help(*key)
76
+ if constant = server.env[key.join('/')]
77
+ path = server.module_path('help.erb', constant)
78
+ render :file => path, :locals => {:obj => constant}
61
79
  else
62
- "unknown #{type}: #{key.join('/')}"
80
+ "unknown constant: #{key.join('/')}"
63
81
  end
64
82
  end
65
83
 
@@ -67,11 +85,31 @@ module Tap
67
85
  set :define_action, false
68
86
 
69
87
  def call(rack_env)
70
- path = rack_env['tap.server'].env.path(:public, rack_env['PATH_INFO']) {|file| File.file?(file) }
71
- if path
72
- static_file(path)
88
+ server = rack_env['tap.server']
89
+ env = server ? server.env : nil
90
+ path_info = rack_env['PATH_INFO']
91
+
92
+ # serve static files
93
+ path = env.path(:public, path_info) {|file| File.file?(file) }
94
+ return static_file(path) if path
95
+
96
+ # route to a controller
97
+ blank, path, path_info = path_info.split("/", 3)
98
+ constant = env ? env.constants.seek(unescape(path)) : nil
99
+
100
+ if constant
101
+ # adjust rack_env if route routes to a controller
102
+ rack_env['SCRIPT_NAME'] = "#{rack_env['SCRIPT_NAME'].chomp('/')}/#{path}"
103
+ rack_env['PATH_INFO'] = "/#{path_info}"
104
+
105
+ constant.unload if server.development
106
+ controller = constant.constantize
107
+ controller == Server ? super : controller.call(rack_env)
73
108
  else
74
- super
109
+ response = Rack::Response.new
110
+ response.status = 302
111
+ response['Location'] = ["/server#{rack_env['PATH_INFO']}".chomp("/")]
112
+ response.finish
75
113
  end
76
114
  end
77
115
 
@@ -87,15 +125,20 @@ module Tap
87
125
  end
88
126
 
89
127
  # Returns a help uri for the specified resource, currently only sketched out.
90
- def help_uri(type, key)
91
- uri("help/#{type}/#{key}")
128
+ def help_uri(key)
129
+ uri("help/#{key}")
92
130
  end
93
131
 
94
- # Stops the server.
95
- def stop!
96
- server.stop!
132
+ def template
133
+ %Q{<% if !minimap.empty? && count > 1 %>
134
+ <h2><%= env_key %></h2>
135
+ <li>
136
+ <ul><% minimap.each do |key, entry| %>
137
+ <li><%= key %> (<a href="help/<%= key %>">?</a>)</li><% end %>
138
+ </ul>
139
+ </li>
140
+ <% end %>}
97
141
  end
98
-
99
142
  end
100
143
  end
101
144
  end
@@ -0,0 +1,23 @@
1
+ require 'tap/generator/generators/resource'
2
+
3
+ module Tap
4
+ module Generator
5
+ module Generators
6
+ # :startdoc::generator generates a controller
7
+ #
8
+ # Generates a new Tap::Controller and an associated test file.
9
+ class Controller < Resource
10
+
11
+ def manifest(m, const_name)
12
+ const = super
13
+
14
+ views_dir = path('views', "#{const.path}")
15
+ m.directory File.dirname(views_dir)
16
+ m.template path(views_dir, "index.erb"), "view.erb"
17
+
18
+ const
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,12 +1,20 @@
1
+ require 'rack'
1
2
  require 'tap'
2
3
  require 'tap/server/data'
3
- require 'tap/server/runner'
4
4
  require 'tap/server/server_error'
5
5
 
6
6
  module Tap
7
7
  # ::configurable
8
8
  class Server
9
- include Runner
9
+ include Rack::Utils
10
+ include Configurable
11
+
12
+ config :servers, %w[thin mongrel webrick], # the server handlers
13
+ :long => :server,
14
+ &c.list
15
+
16
+ config :host, '127.0.0.1', &c.string # the server host
17
+ config :port, 8080, &c.integer_or_nil # the server port
10
18
 
11
19
  # Server implements a secret for HTTP administration of the server (ex
12
20
  # remote shutdown). Under many circumstances this functionality is
@@ -16,22 +24,34 @@ module Tap
16
24
 
17
25
  config :development, false, &c.flag
18
26
 
19
- config :router, true, &c.switch
20
-
21
- nest :env, Tap::Env, :type => :hidden
22
-
23
- nest :app, Tap::App, :type => :hidden
24
-
25
27
  nest :data, Data, :type => :hidden
26
28
 
27
- attr_accessor :controller
29
+ attr_reader :app
30
+ attr_reader :controller
28
31
 
29
- attr_accessor :thread
32
+ def initialize(config={}, app=Tap::App.instance, &block)
33
+ @handler = nil
34
+ @controller = block
35
+
36
+ @app = app
37
+ initialize_config(config)
38
+ end
39
+
40
+ def env
41
+ app.env
42
+ end
30
43
 
31
- def initialize(controller=nil, config={})
44
+ def bind(controller)
45
+ if controller.kind_of?(String)
46
+ controller = app.resolve(controller)
47
+ end
48
+
49
+ unless controller.respond_to?(:call)
50
+ raise "invalid controller: #{controller.inspect}"
51
+ end
52
+
32
53
  @controller = controller
33
- @thread = nil
34
- super(config)
54
+ self
35
55
  end
36
56
 
37
57
  # Returns true if input is equal to the secret, if a secret is set. Used
@@ -41,36 +61,18 @@ module Tap
41
61
  secret != nil && input == secret
42
62
  end
43
63
 
44
- def route(rack_env)
45
- return controller unless router
46
-
47
- # route to a controller
48
- blank, path, path_info = rack_env['PATH_INFO'].split("/", 3)
49
- controller = lookup_controller(unescape(path))
50
-
51
- if controller
52
- # adjust rack_env if route routes to a controller
53
- rack_env['SCRIPT_NAME'] = ["#{rack_env['SCRIPT_NAME'].chomp('/')}/#{path}"]
54
- rack_env['PATH_INFO'] = ["/#{path_info}"]
55
- else
56
- # use default controller
57
- controller = self.controller
58
- path = nil
59
- end
60
-
61
- rack_env['tap.controller_path'] = path
62
- controller
64
+ def template_path(path)
65
+ app.env.path(:views, path) {|file| File.file?(file) }
63
66
  end
64
-
67
+
68
+ def module_path(path, klass)
69
+ app.env.module_path(:views, klass.ancestors, path) {|file| File.file?(file) }
70
+ end
71
+
65
72
  # The {Rack}[http://rack.rubyforge.org/doc/] interface method.
66
73
  def call(rack_env)
67
74
  # handle the request
68
75
  rack_env['tap.server'] = self
69
-
70
- unless controller = route(rack_env)
71
- raise ServerError.new("404 Error: could not route to controller", 404)
72
- end
73
-
74
76
  controller.call(rack_env)
75
77
  rescue ServerError
76
78
  $!.response
@@ -78,27 +80,47 @@ module Tap
78
80
  ServerError.response($!)
79
81
  end
80
82
 
81
- def run!
82
- super(self)
83
+ # Runs self as configured, on the specified server, host, and port. Use an
84
+ # INT signal to interrupt.
85
+ def run!(handler=rack_handler)
86
+ return self if @handler
87
+
88
+ handler.run(self, :Host => host, :Port => port) do |handler|
89
+ @handler = handler
90
+ trap(:INT) { stop! }
91
+ yield if block_given?
92
+ end
93
+
94
+ self
95
+ end
96
+
97
+ # Stops the server if running (ie a handler is set).
98
+ def stop!
99
+ if @handler
100
+ # Use thins' hard #stop! if available, otherwise just #stop
101
+ @handler.respond_to?(:stop!) ? @handler.stop! : @handler.stop
102
+ @handler = nil
103
+
104
+ yield if block_given?
105
+ end
106
+
107
+ self
83
108
  end
84
109
 
85
110
  protected
86
111
 
87
- def lookup_controller(key) # :nodoc:
88
- if development
89
- # unload the controller in development mode so that
90
- # controllers will be reloaded each request
91
-
92
- env.reset
93
- if const = env.seek(:controller, key)
94
- const.unload
95
- const.constantize
96
- else
97
- nil
112
+ # Looks up and returns the first available Rack::Handler as listed in the
113
+ # servers configuration. (Note rack_handler returns a handler class, not
114
+ # an instance). Adapted from Sinatra.detect_rack_handler
115
+ def rack_handler # :nodoc:
116
+ servers.each do |server_name|
117
+ begin
118
+ return Rack::Handler.get(server_name)
119
+ rescue LoadError
120
+ rescue NameError
98
121
  end
99
- else
100
- env[:controller][key]
101
122
  end
123
+ raise "Server handler (#{servers.join(',')}) not found."
102
124
  end
103
125
  end
104
126
  end
@@ -15,7 +15,7 @@ module Tap
15
15
  #config :sym, :sym, &c.symbol # sym
16
16
  config :integer, 10, &c.integer # integer
17
17
  config :numeric, 10, &c.numeric # numeric
18
- config :float, 10, &c.float # float
18
+ config :float, 10.0, &c.float # float
19
19
 
20
20
  config :string_or_nil, nil, &c.string_or_nil # string_or_nil (nil)
21
21
  #config :sym_or_nil, nil, &c.symbol_or_nil # symbol_or_nil (nil)
@@ -0,0 +1,14 @@
1
+ require 'tap/controller'
2
+
3
+ <% redirect do |target| %># :startdoc::controller <replace with summary>
4
+ # <replace with description>
5
+
6
+ # <%= const.name %> Documentation
7
+ class <%= const.name %> < Tap::Controller
8
+
9
+ # Methods define actions on the controller
10
+ def index
11
+ render 'index.erb', :locals => {:obj => 'moon'}, :layout => true
12
+ end
13
+
14
+ end <% module_nest(const.nesting, ' ') { target } end %>
@@ -0,0 +1 @@
1
+ Goodnight <%%= obj %>!
@@ -0,0 +1,57 @@
1
+ <dl>
2
+ <% configurations.each_pair do |key, config| %>
3
+ <% next if config[:type] == :hidden %>
4
+ <% name = "#{name_base}[#{key.inspect}]" %>
5
+ <% value = values[key] %>
6
+
7
+ <% if config.is_nest? %>
8
+ <dt class="name"><%= key %></dt>
9
+ <dd class="nested-configs">
10
+ <%= module_render("configurations.erb", obj, :locals => {
11
+ :name_base => name,
12
+ :configurations => config.default(false).delegates,
13
+ :values => value
14
+ }) %>
15
+ </dd>
16
+ <% next %>
17
+ <% end %>
18
+
19
+ <dt><%= key %></dt>
20
+ <dd>
21
+ <% case config[:type] %>
22
+ <% when :flag %>
23
+ <input name="<%= name %>" type="hidden" value="false" />
24
+ <input name="<%= name %>" type="checkbox" value="true" <%= value ? 'checked="true"' : '' %> />
25
+
26
+ <% when :switch %>
27
+ <input name="<%= name %>" type="radio" value="true" <%= value ? 'checked="true" ' : '' %>>on</input>
28
+ <input name="<%= name %>" type="radio" value="false" <%= !value ? 'checked="true" ' : '' %>>off</input>
29
+
30
+ <% when :select %>
31
+ <select name="<%= name %>">
32
+ <% (config[:options] || []).each do |option| %>
33
+ <option value="<%= option %>" <%= value == option ? "selected='true' " : ""%>><%= option %></option>
34
+ <% end %>
35
+ </select>
36
+
37
+ <% when :list_select %>
38
+ <input type="hidden" name="<%= name %>[]" value="#" />
39
+ <select name="<%= name %>[]" multiple="true">
40
+ <% (config[:options] || []).each do |option| %>
41
+ <option value="<%= option %>" <%= value && value.include?(option) ? "selected='true' " : ""%>><%= option %></option>
42
+ <% end %>
43
+ </select>
44
+
45
+ <% when :hidden %>
46
+ <% next %>
47
+ <% else %>
48
+ <%= render(
49
+ :file => module_path("#{config[:type]}.erb", obj.class) || template_path("configurable/default.erb"),
50
+ :locals => {
51
+ :name => name,
52
+ :config => config,
53
+ :value => value}) %>
54
+ <% end %>
55
+ </dd>
56
+ <% end %>
57
+ </dl>
@@ -0,0 +1 @@
1
+ <input name="<%= name %>" type="text" value="<%= value %>" />
@@ -2,10 +2,13 @@
2
2
  <head>
3
3
  <title>Tap (Server)</title>
4
4
  <link rel="stylesheet" type="text/css" href="/stylesheets/tap.css" />
5
- <script src="/javascripts/prototype.js"></script>
6
- <script src="/javascripts/tap.js"></script>
5
+ <!-- <script src="/javascripts/tap.js"></script> -->
7
6
  </head>
8
7
  <body>
9
8
  <%= content %>
9
+
10
+ <ul>
11
+ <li><a href="/">Home</a></li>
12
+ </ul>
10
13
  </body>
11
14
  </html>
@@ -2,16 +2,18 @@
2
2
 
3
3
  <ul>
4
4
  <li class="source_file">
5
- <h2>Source File</h2>
6
- <p><%= obj.source_file %><p>
5
+ <h2>Registered As</h2>
6
+ <ul><% Lazydoc::Document[obj.to_s].each_pair do |type, comment| %>
7
+ <li><%= type %> (<%= comment.document.source_file %>)</li><% end %>
8
+ </ul>
7
9
  </li>
8
10
  <li>
9
11
  <h2>Summary</h2>
10
- <%= obj.desc.subject %>
12
+ <%= obj.desc ? obj.desc.subject : nil %>
11
13
  </li>
12
14
  <li>
13
15
  <h2>Documentation</h2>
14
- <pre class="desc"><%= obj.desc.wrap %></pre>
16
+ <pre class="desc"><%= obj.desc ? obj.desc.wrap : nil %></pre>
15
17
  </li>
16
18
  <li>
17
19
  <h2>Signature</h2>