speck_gem 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +5 -0
- data/Gemfile.lock +16 -0
- data/README.md +99 -0
- data/Rakefile +11 -0
- data/app/Gemfile +2 -0
- data/app/config.rb +3 -0
- data/app/exception.html.erb +2 -0
- data/app/routes.rb +0 -0
- data/app/server.log +5 -0
- data/app/server.log.20130511 +0 -0
- data/lib/speck/config.rb +67 -0
- data/lib/speck/controller.rb +76 -0
- data/lib/speck/exception.rb +17 -0
- data/lib/speck/log.rb +37 -0
- data/lib/speck/router.rb +115 -0
- data/lib/speck.rb +4 -0
- data/server.log +1 -0
- data/speck.gemspec +10 -0
- data/test/config.rb +0 -0
- data/test/controller_example.rb +51 -0
- data/test/controllers.rb +60 -0
- data/test/exception.rb +11 -0
- data/test/logger.rb +7 -0
- data/test/partial_example.html.erb +1 -0
- data/test/router.rb +66 -0
- data/test/routes_example.rb +16 -0
- data/test/template2_example.html.erb +2 -0
- data/test/template_example.html.erb +1 -0
- metadata +72 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/README.md
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
Speck
|
2
|
+
=====
|
3
|
+
|
4
|
+
Ruby Microframework.
|
5
|
+
|
6
|
+
Getting Started
|
7
|
+
===============
|
8
|
+
1. make filesystem seen in app directory
|
9
|
+
2. require gem
|
10
|
+
|
11
|
+
|
12
|
+
Routing
|
13
|
+
=======
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
# routes.rb
|
17
|
+
|
18
|
+
match '/','Home' do
|
19
|
+
get '' => 'index'
|
20
|
+
post 'login' => 'authenticate'
|
21
|
+
end
|
22
|
+
|
23
|
+
match '/vacations','Vacation' do
|
24
|
+
get '' => 'index', '/:id'=>'show'
|
25
|
+
put '/:id' => 'update'
|
26
|
+
post '/:id' => 'edit'
|
27
|
+
|
28
|
+
match '/:id1/photos','Photo' do
|
29
|
+
get '' => 'index', '/:id2' => 'show'
|
30
|
+
put '/:id2' => 'update'
|
31
|
+
post '/:id2' => 'edit'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
36
|
+
Controllers
|
37
|
+
===========
|
38
|
+
```ruby
|
39
|
+
class Photo < Speck::Controller
|
40
|
+
def index
|
41
|
+
session[:user] = params[:user]
|
42
|
+
render('home.html.erb')
|
43
|
+
end
|
44
|
+
|
45
|
+
def show
|
46
|
+
@user = session[:user]
|
47
|
+
@photo = fetch_photo(params[:id])
|
48
|
+
render('photo.html.erb')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
```
|
53
|
+
|
54
|
+
Templates
|
55
|
+
=========
|
56
|
+
Speck uses the tilt gem for template rendering. Many templating languages are supported. Below is an example using erb.
|
57
|
+
```html
|
58
|
+
<h1><%= @user %></h1>
|
59
|
+
|
60
|
+
<% @photos.each do |photo| %>
|
61
|
+
<% @id = photo.id %>
|
62
|
+
<% @location = photo.location %>
|
63
|
+
<% @file = photo.file_path %>
|
64
|
+
<%= render('photo_partial.html.erb') %>
|
65
|
+
<% end %>
|
66
|
+
|
67
|
+
```
|
68
|
+
and photo_partial.html.erb
|
69
|
+
```html
|
70
|
+
<h3><%= @id %></h3>
|
71
|
+
<p><%= @location %></p>
|
72
|
+
<img src='<%= @file %>' />
|
73
|
+
```
|
74
|
+
There are helper functions for paths, javascrpit, and css.
|
75
|
+
|
76
|
+
App Structure
|
77
|
+
=============
|
78
|
+
```
|
79
|
+
/app
|
80
|
+
/assets
|
81
|
+
/controllers
|
82
|
+
/views
|
83
|
+
config.rb
|
84
|
+
exception.html.erb
|
85
|
+
Gemfile
|
86
|
+
routes.rb
|
87
|
+
server.log
|
88
|
+
```
|
89
|
+
|
90
|
+
Rake Commands
|
91
|
+
=============
|
92
|
+
* rake test: runs the gem's test suite
|
93
|
+
|
94
|
+
TODO
|
95
|
+
====
|
96
|
+
* test config
|
97
|
+
* test session persistence
|
98
|
+
* app structure
|
99
|
+
* rake task for building app structure
|
data/Rakefile
ADDED
data/app/Gemfile
ADDED
data/app/config.rb
ADDED
data/app/routes.rb
ADDED
File without changes
|
data/app/server.log
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
# Logfile created on 2013-05-12 23:40:45 -0400 by logger.rb/31641
|
2
|
+
E, [2013-05-12T23:40:45.944095 #43403] ERROR -- : [2013-05-12 23:40:45 -0400] 500: Missing rack.input
|
3
|
+
|
4
|
+
E, [2013-05-12T23:42:06.077617 #43650] ERROR -- : [2013-05-12 23:42:06 -0400] 500: Missing rack.input
|
5
|
+
|
File without changes
|
data/lib/speck/config.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'rack'
|
2
|
+
|
3
|
+
|
4
|
+
module Speck
|
5
|
+
class Config
|
6
|
+
private_class_method :new
|
7
|
+
|
8
|
+
def self.app_root
|
9
|
+
if Dir.pwd[-3,3] == 'app'
|
10
|
+
dir = Dir.pwd
|
11
|
+
else
|
12
|
+
dir = Dir.pwd+'/app'
|
13
|
+
end
|
14
|
+
@@app_root ||= dir
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.set_app_root(root)
|
18
|
+
@@app_root = root
|
19
|
+
end
|
20
|
+
|
21
|
+
def set_app_server(type)
|
22
|
+
@@server = type
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.app_server
|
26
|
+
@@server ||= Rack::Handler::WEBrick
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.app_port
|
30
|
+
@@port ||= 5000
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.set_app_port(port)
|
34
|
+
@@port = port
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.app_middleware
|
38
|
+
@@middleware ||= [[Rack::Static,{:urls => ["/assets"]}],
|
39
|
+
[Rack::Session::Cookie, {:key => 'rack.session',
|
40
|
+
:path => '/',
|
41
|
+
:expire_after => 2592000,
|
42
|
+
:secret => 'SECRETKEY1111'}]]
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.add_app_middleware(middleware, options)
|
46
|
+
nxt = [middleware, options]
|
47
|
+
if app_middleware.nil?
|
48
|
+
@@middleware = [nxt]
|
49
|
+
else
|
50
|
+
@@middleware << nxt
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.launch
|
55
|
+
app = Rack::Builder.app do
|
56
|
+
Speck::Config.app_middleware.each do |middleware|
|
57
|
+
use middleware[0], middleware[1]
|
58
|
+
end
|
59
|
+
Signal.trap('INT') {
|
60
|
+
Speck::Config.app_server.shutdown
|
61
|
+
}
|
62
|
+
run Speck::Router.new
|
63
|
+
end
|
64
|
+
app_server.run(app, :Port => app_port)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'tilt'
|
2
|
+
|
3
|
+
module Speck
|
4
|
+
|
5
|
+
class Controller
|
6
|
+
|
7
|
+
def initialize(session, params)
|
8
|
+
@__session = session
|
9
|
+
@__params = params
|
10
|
+
end
|
11
|
+
|
12
|
+
def link(path,text)
|
13
|
+
"<a href='#{path}'>#{text}</a>"
|
14
|
+
end
|
15
|
+
|
16
|
+
def asset(filename)
|
17
|
+
path('asset',filename)
|
18
|
+
end
|
19
|
+
|
20
|
+
def controller(filename)
|
21
|
+
path('controller',filename)
|
22
|
+
end
|
23
|
+
|
24
|
+
def view(filename)
|
25
|
+
path('view',filename)
|
26
|
+
end
|
27
|
+
|
28
|
+
def path(type,filename)
|
29
|
+
case type
|
30
|
+
when /app/
|
31
|
+
Config.app_root+'/'+filename
|
32
|
+
when /asset/
|
33
|
+
'/assets/'+filename
|
34
|
+
when /controller/
|
35
|
+
Config.app_root+'/controllers/'+filename
|
36
|
+
when /view/
|
37
|
+
Config.app_root+'/views/'+filename
|
38
|
+
else
|
39
|
+
message = "#{type} is not a valid type! Valid types are 'app','asset','controller','view'!"
|
40
|
+
raise Speck_Exception.new(message)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def js(filename)
|
45
|
+
if filename =~ /\.js/
|
46
|
+
js = path('assets',filename)
|
47
|
+
else
|
48
|
+
js = path('assets',filename+'.js')
|
49
|
+
end
|
50
|
+
"<script src='#{js}' type='text/javascript' charset='utf-8'></script>"
|
51
|
+
end
|
52
|
+
|
53
|
+
def css(filename)
|
54
|
+
if filename =~ /\.css/
|
55
|
+
style = path('assets',filename)
|
56
|
+
else
|
57
|
+
style = path('assets',filename+'.css')
|
58
|
+
end
|
59
|
+
"<link rel='STYLESHEET' href='#{style}' type='text/css'>"
|
60
|
+
end
|
61
|
+
|
62
|
+
def render(template_path)
|
63
|
+
Log.render(template_path)
|
64
|
+
Tilt.new(template_path).render(self)
|
65
|
+
end
|
66
|
+
|
67
|
+
def session
|
68
|
+
@__session
|
69
|
+
end
|
70
|
+
|
71
|
+
def params
|
72
|
+
@__params
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Speck
|
2
|
+
class Speck_Exception < RuntimeError
|
3
|
+
end
|
4
|
+
|
5
|
+
class Routing_Exception < Speck_Exception
|
6
|
+
attr_reader :status, :message
|
7
|
+
|
8
|
+
def initialize(status, message)
|
9
|
+
@status = status
|
10
|
+
@message = message
|
11
|
+
end
|
12
|
+
|
13
|
+
def render()
|
14
|
+
Tilt.new(Config.app_root+'/exception.html.erb').render(self)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/speck/log.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Speck
|
4
|
+
class Log
|
5
|
+
|
6
|
+
def self.log
|
7
|
+
@log ||= Logger.new(Config.app_root+'/server.log', shift_age = 'weekly')
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.render(path)
|
11
|
+
write(Logger::INFO, "Renderig: #{path}")
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.request(request)
|
15
|
+
write(Logger::INFO,"Starting: #{request.request_method} #{request.fullpath}")
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.dispatch(controller,action,params)
|
19
|
+
write(Logger::INFO,"Dispatching: #{controller}.#{action} with #{params}")
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.exception(status,message)
|
23
|
+
write(Logger::WARN,"#{status}: #{message}")
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.error(error)
|
27
|
+
puts error.backtrace
|
28
|
+
write(Logger::ERROR,"500: #{error.message}")
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.write(severity,msg)
|
32
|
+
out = "[#{Time.now}] #{msg}\n"
|
33
|
+
puts out
|
34
|
+
log.add(severity,message=out)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/speck/router.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'rack'
|
2
|
+
require 'speck/controller'
|
3
|
+
require 'speck/log'
|
4
|
+
require 'speck/exception'
|
5
|
+
require 'speck/config'
|
6
|
+
|
7
|
+
Dir[Speck::Config.app_root+"/controllers/*.rb"].each {|file| require file }
|
8
|
+
|
9
|
+
|
10
|
+
module Speck
|
11
|
+
class Router
|
12
|
+
|
13
|
+
attr_reader :routes
|
14
|
+
|
15
|
+
@@HTTP_REQUESTS = [:GET, :PUT, :POST, :DELETE]
|
16
|
+
|
17
|
+
def initialize(path=nil)
|
18
|
+
@routes = {}
|
19
|
+
@controller = []
|
20
|
+
@base = ''
|
21
|
+
@@HTTP_REQUESTS.each{ |req| @routes[req] = {}}
|
22
|
+
build_routes(path)
|
23
|
+
end
|
24
|
+
|
25
|
+
def build_routes(path=nil)
|
26
|
+
path ||= Config.app_root+'/routes.rb'
|
27
|
+
instance_eval(File.read(path))
|
28
|
+
end
|
29
|
+
|
30
|
+
def match(base,controller, &block)
|
31
|
+
@base << base
|
32
|
+
@controller << controller
|
33
|
+
instance_eval(&block)
|
34
|
+
@controller.pop()
|
35
|
+
@base.chomp!(base)
|
36
|
+
end
|
37
|
+
|
38
|
+
def call(env)
|
39
|
+
@request = Rack::Request.new(env)
|
40
|
+
@response = process
|
41
|
+
@response.finish
|
42
|
+
end
|
43
|
+
|
44
|
+
def symbolize_keys(hash)
|
45
|
+
hash.keys.each do |key|
|
46
|
+
hash[(key.to_sym rescue key) || key] = hash.delete(key)
|
47
|
+
end
|
48
|
+
hash
|
49
|
+
end
|
50
|
+
|
51
|
+
def controller_action_params
|
52
|
+
routes = @routes[@request.request_method.to_sym]
|
53
|
+
valid_routes = routes.keys.select{ |route| matching? route}
|
54
|
+
raise Routing_Exception.new(404,'Page not found!') if valid_routes.empty?
|
55
|
+
controller, action = routes[valid_routes.first]
|
56
|
+
params = extract_params(valid_routes.first)
|
57
|
+
params.merge!(symbolize_keys(@request.params)) if @request.form_data?
|
58
|
+
[controller, action, params]
|
59
|
+
end
|
60
|
+
|
61
|
+
def matching?(route)
|
62
|
+
route_list = route.split('/')
|
63
|
+
path_list = @request.path.split('/')
|
64
|
+
return false unless path_list.length == route_list.length
|
65
|
+
path_list.length.times { |i| return false unless route_list[i][0] == ":" or route_list[i] == path_list[i]}
|
66
|
+
true
|
67
|
+
end
|
68
|
+
|
69
|
+
def extract_params(route)
|
70
|
+
route_list = route.split('/')
|
71
|
+
path_list = @request.path.split('/')
|
72
|
+
|
73
|
+
params = {}
|
74
|
+
path_list.length.times do |i|
|
75
|
+
params[route_list[i].sub(":","").to_sym] = path_list[i] if route_list[i][0] == ":"
|
76
|
+
end
|
77
|
+
params
|
78
|
+
end
|
79
|
+
|
80
|
+
def process
|
81
|
+
Log.request(@request)
|
82
|
+
begin
|
83
|
+
controller, action, params = controller_action_params
|
84
|
+
Log.dispatch(controller,action,params)
|
85
|
+
session = @request.env['rack.session']
|
86
|
+
session[:init] = true #forces session loading
|
87
|
+
body = Kernel.const_get(controller).new(session|| {}, params).send(action)
|
88
|
+
status = 200
|
89
|
+
rescue Routing_Exception => ex
|
90
|
+
Log.exception(ex.status, ex.message)
|
91
|
+
body = ex.render
|
92
|
+
status = ex.status
|
93
|
+
rescue RuntimeError => e
|
94
|
+
Log.error(e)
|
95
|
+
ex = Routing_Exception.new(500,'Server Error!')
|
96
|
+
body = ex.render
|
97
|
+
status = 500
|
98
|
+
end
|
99
|
+
resp = Rack::Response.new(body=body, status=status)
|
100
|
+
end
|
101
|
+
|
102
|
+
def add_route(request_type, bindings)
|
103
|
+
bindings.each { |route, action| @routes[request_type][@base+route] = [@controller.last,action] }
|
104
|
+
end
|
105
|
+
|
106
|
+
def method_missing(name, *args, &block)
|
107
|
+
if @@HTTP_REQUESTS.include?(name.upcase)
|
108
|
+
add_route(name.upcase,args[0])
|
109
|
+
else
|
110
|
+
super(name, *args, &block)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
data/lib/speck.rb
ADDED
data/server.log
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Logfile created on 2013-05-12 22:35:54 -0400 by logger.rb/31641
|
data/speck.gemspec
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'speck_gem'
|
3
|
+
s.version = '1.0.0'
|
4
|
+
s.date = '2013-04-06'
|
5
|
+
s.summary = "See documentation"
|
6
|
+
s.description = "A simple ruby web framework"
|
7
|
+
s.authors = ["David Thomas"]
|
8
|
+
s.email = 'davidthomas5412@gmail.com'
|
9
|
+
s.files = `git ls-files`.split("\n") - %w[.gitignore]
|
10
|
+
end
|
data/test/config.rb
ADDED
File without changes
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'speck'
|
2
|
+
|
3
|
+
class Location < Speck::Controller
|
4
|
+
def index
|
5
|
+
"index called"
|
6
|
+
end
|
7
|
+
|
8
|
+
def show
|
9
|
+
"id: #{params[:id]}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def template
|
13
|
+
@msg = 'template message'
|
14
|
+
render('test/template_example.html.erb')
|
15
|
+
end
|
16
|
+
|
17
|
+
def template_with_partial
|
18
|
+
@title = "template title"
|
19
|
+
@body = "partial body"
|
20
|
+
render('test/template2_example.html.erb')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Book < Speck::Controller
|
25
|
+
def show
|
26
|
+
"id: #{params[:id]}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
class Home < Speck::Controller
|
32
|
+
def index
|
33
|
+
"index body"
|
34
|
+
end
|
35
|
+
|
36
|
+
def authenticate
|
37
|
+
raise RuntimeError
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Vacation < Speck::Controller
|
42
|
+
def show
|
43
|
+
"id: #{params[:id]}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Photo < Speck::Controller
|
48
|
+
def show
|
49
|
+
"id1: #{params[:id1]} id2: #{params[:id2]}"
|
50
|
+
end
|
51
|
+
end
|
data/test/controllers.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require File.dirname(File.expand_path(__FILE__))+'/controller_example.rb'
|
2
|
+
|
3
|
+
def assert_contain(actual, expected)
|
4
|
+
actual =~ expected
|
5
|
+
end
|
6
|
+
|
7
|
+
setup do
|
8
|
+
Speck::Log.stubs(:render)
|
9
|
+
end
|
10
|
+
|
11
|
+
test "controller dispatching actions" do
|
12
|
+
assert_equal Location.new({},{}).send('index'), "index called"
|
13
|
+
assert_equal Location.new({},{:id => 99}).send('show'), "id: 99"
|
14
|
+
end
|
15
|
+
|
16
|
+
test "controller rendering with instance variables" do
|
17
|
+
assert_contain Location.new({},{}).send('template'), /template message/
|
18
|
+
end
|
19
|
+
|
20
|
+
test "controller classes don't share param state" do
|
21
|
+
assert_equal Location.new({},{:id => 0}).send('show'), "id: 0"
|
22
|
+
assert_equal Book.new({},{:id => 1}).send('show'), "id: 1"
|
23
|
+
end
|
24
|
+
|
25
|
+
test "recursive rendering of partials" do
|
26
|
+
assert_contain Location.new({},{}).send('template_with_partial'), /template title/
|
27
|
+
assert_contain Location.new({},{}).send('template_with_partial'), /partial body/
|
28
|
+
end
|
29
|
+
|
30
|
+
test "session persists accross requests" do
|
31
|
+
end
|
32
|
+
|
33
|
+
test "path" do
|
34
|
+
loc = Location.new({},{})
|
35
|
+
root = Speck::Config.app_root
|
36
|
+
assert_equal loc.path('app','config.rb'), root+'/config.rb'
|
37
|
+
assert_equal loc.path('views','photo.html.erb'), root+'/views/photo.html.erb'
|
38
|
+
assert_equal loc.path('asset','jquery.js'), '/assets/jquery.js'
|
39
|
+
end
|
40
|
+
|
41
|
+
test "invalid path raises speck exception" do
|
42
|
+
loc = Location.new({},{})
|
43
|
+
assert_raise Speck::Speck_Exception do
|
44
|
+
loc.path('veew','')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
test "javascript helper" do
|
49
|
+
loc = Location.new({},{})
|
50
|
+
root = Speck::Config.app_root
|
51
|
+
expected = "<script src='/assets/jquery.js' type='text/javascript' charset='utf-8'></script>"
|
52
|
+
assert_equal loc.js('jquery'), expected
|
53
|
+
end
|
54
|
+
|
55
|
+
test "css helper" do
|
56
|
+
loc = Location.new({},{})
|
57
|
+
root = Speck::Config.app_root
|
58
|
+
expected = "<link rel='STYLESHEET' href='/assets/style.css' type='text/css'>"
|
59
|
+
assert_equal loc.css('style'), expected
|
60
|
+
end
|
data/test/exception.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
setup do
|
2
|
+
Speck::Config.set_app_root('app')
|
3
|
+
end
|
4
|
+
|
5
|
+
test "404 routing exception" do
|
6
|
+
ex = Speck::Routing_Exception.new(404,'Page not found!')
|
7
|
+
assert_equal ex.status, 404
|
8
|
+
assert_equal ex.message, 'Page not found!'
|
9
|
+
assert_equal ex.render, "<h1>404</h1>
|
10
|
+
<p>Page not found!</p>"
|
11
|
+
end
|
data/test/logger.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
<%= @body %>
|
data/test/router.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
test = File.dirname(File.expand_path(__FILE__))
|
2
|
+
require test+'/controller_example.rb'
|
3
|
+
|
4
|
+
### To test response
|
5
|
+
module Rack
|
6
|
+
class Response
|
7
|
+
attr_reader :body
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def expect_request
|
12
|
+
Speck::Log.expects(:request)
|
13
|
+
Speck::Log.expects(:dispatch)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_response(r,env,status,body)
|
17
|
+
expect_request
|
18
|
+
env['rack.session'] ={}
|
19
|
+
resp = r.call(env)
|
20
|
+
assert_equal resp[2].body(), [body]
|
21
|
+
assert_equal resp[0], status
|
22
|
+
end
|
23
|
+
|
24
|
+
setup do
|
25
|
+
Speck::Router.new(test+'/routes_example.rb')
|
26
|
+
end
|
27
|
+
|
28
|
+
test 'routes controller action' do |r|
|
29
|
+
assert_equal r.routes[:GET]['/'], ['Home','index']
|
30
|
+
assert_equal r.routes[:POST]['/login'], ['Home','authenticate']
|
31
|
+
end
|
32
|
+
|
33
|
+
test 'nested routes' do |r|
|
34
|
+
assert_equal r.routes[:GET]['/vacations/:id1/photos'], ['Photo','index']
|
35
|
+
end
|
36
|
+
|
37
|
+
test 'route with param' do |r|
|
38
|
+
assert_equal r.routes[:PUT]['/vacations/:id'], ['Vacation','update']
|
39
|
+
end
|
40
|
+
|
41
|
+
test 'handle example request' do |r|
|
42
|
+
env = {"PATH_INFO"=>"/", "REQUEST_METHOD"=>"GET"}
|
43
|
+
test_response(r,env,200,"index body")
|
44
|
+
end
|
45
|
+
|
46
|
+
test 'handle exmple request with parameters' do |r|
|
47
|
+
env = {"PATH_INFO"=>"/vacations/99", "REQUEST_METHOD"=>"GET"}
|
48
|
+
test_response(r,env,200,"id: 99")
|
49
|
+
end
|
50
|
+
|
51
|
+
test 'handle nested route request with multiple parameters' do |r|
|
52
|
+
env = {"PATH_INFO"=>"/vacations/1/photos/2", "REQUEST_METHOD"=>"GET"}
|
53
|
+
test_response(r,env,200,"id1: 1 id2: 2")
|
54
|
+
end
|
55
|
+
|
56
|
+
test 'handle 404' do |r|
|
57
|
+
env = {"PATH_INFO"=>"facebook", "REQUEST_METHOD"=>"GET"}
|
58
|
+
Speck::Log.expects(:exception)
|
59
|
+
test_response(r,env,404,"<h1>404</h1>\n<p>Page not found!</p>")
|
60
|
+
end
|
61
|
+
|
62
|
+
test 'handle 500' do |r|
|
63
|
+
env = {"PATH_INFO"=>"/login", "REQUEST_METHOD"=>"POST"}
|
64
|
+
Speck::Log.expects(:error)
|
65
|
+
test_response(r,env,500,"<h1>500</h1>\n<p>Server Error!</p>")
|
66
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
match '/','Home' do
|
2
|
+
get '' => 'index'
|
3
|
+
post 'login' => 'authenticate'
|
4
|
+
end
|
5
|
+
|
6
|
+
match '/vacations','Vacation' do
|
7
|
+
get '' => 'index', '/:id'=>'show'
|
8
|
+
put '/:id' => 'update'
|
9
|
+
post '/:id' => 'edit'
|
10
|
+
|
11
|
+
match '/:id1/photos','Photo' do
|
12
|
+
get '' => 'index', '/:id2' => 'show'
|
13
|
+
put '/:id2' => 'update'
|
14
|
+
post '/:id2' => 'edit'
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<p><%= @message %></p>
|
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: speck_gem
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- David Thomas
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-04-06 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: A simple ruby web framework
|
15
|
+
email: davidthomas5412@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- Gemfile
|
21
|
+
- Gemfile.lock
|
22
|
+
- README.md
|
23
|
+
- Rakefile
|
24
|
+
- app/Gemfile
|
25
|
+
- app/config.rb
|
26
|
+
- app/exception.html.erb
|
27
|
+
- app/routes.rb
|
28
|
+
- app/server.log
|
29
|
+
- app/server.log.20130511
|
30
|
+
- lib/speck.rb
|
31
|
+
- lib/speck/config.rb
|
32
|
+
- lib/speck/controller.rb
|
33
|
+
- lib/speck/exception.rb
|
34
|
+
- lib/speck/log.rb
|
35
|
+
- lib/speck/router.rb
|
36
|
+
- server.log
|
37
|
+
- speck.gemspec
|
38
|
+
- test/config.rb
|
39
|
+
- test/controller_example.rb
|
40
|
+
- test/controllers.rb
|
41
|
+
- test/exception.rb
|
42
|
+
- test/logger.rb
|
43
|
+
- test/partial_example.html.erb
|
44
|
+
- test/router.rb
|
45
|
+
- test/routes_example.rb
|
46
|
+
- test/template2_example.html.erb
|
47
|
+
- test/template_example.html.erb
|
48
|
+
homepage:
|
49
|
+
licenses: []
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options: []
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ! '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
requirements: []
|
67
|
+
rubyforge_project:
|
68
|
+
rubygems_version: 1.8.24
|
69
|
+
signing_key:
|
70
|
+
specification_version: 3
|
71
|
+
summary: See documentation
|
72
|
+
test_files: []
|