speck_gem 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|