kenji 0.4 → 0.5
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/Rakefile +5 -0
- data/lib/kenji/controller.rb +37 -0
- data/lib/kenji/version.rb +1 -1
- data/lib/kenji.rb +20 -4
- data/spec/1/controllers/main.rb +19 -0
- data/spec/2/controllers/_.rb +9 -0
- data/spec/2/controllers/child.rb +8 -0
- data/spec/kenji_spec.rb +65 -0
- metadata +58 -59
data/Gemfile
CHANGED
data/Rakefile
CHANGED
data/lib/kenji/controller.rb
CHANGED
@@ -68,12 +68,46 @@ module Kenji
|
|
68
68
|
nil # void method
|
69
69
|
end
|
70
70
|
|
71
|
+
# This lets us pass the routing down to another controller for a sub-path.
|
72
|
+
#
|
73
|
+
# class MyController < Kenji::Controller
|
74
|
+
# pass '/admin/*', AdminController
|
75
|
+
# # regular routes
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
def self.pass(path, controller)
|
79
|
+
node = (@passes ||= {})
|
80
|
+
segments = path.split('/')
|
81
|
+
segments = segments.drop(1) if segments.first == '' # discard leading /'s empty segment
|
82
|
+
segments.each do |segment|
|
83
|
+
node = (node[segment.to_sym] ||= {})
|
84
|
+
break if segment == '*'
|
85
|
+
end
|
86
|
+
node[:@controller] = controller
|
87
|
+
end
|
88
|
+
|
71
89
|
|
72
90
|
# Most likely only used by Kenji itself.
|
73
91
|
# Override to implement your own routing, if you'd like.
|
92
|
+
#
|
74
93
|
def call(method, path)
|
75
94
|
segments = path.split('/')
|
76
95
|
segments = segments.drop(1) if segments.first == '' # discard leading /'s empty segment
|
96
|
+
|
97
|
+
# check for passes
|
98
|
+
node = self.class.passes
|
99
|
+
remaining_segments = segments.dup
|
100
|
+
while s = remaining_segments.shift
|
101
|
+
next unless node[s.to_sym]
|
102
|
+
node = node[s.to_sym]
|
103
|
+
break
|
104
|
+
end
|
105
|
+
if node[:@controller]
|
106
|
+
instance = node[:@controller].new
|
107
|
+
return instance.call(method, remaining_segments.join('/'))
|
108
|
+
end
|
109
|
+
|
110
|
+
# regular routing
|
77
111
|
node = self.class.routes[method]
|
78
112
|
variables = []
|
79
113
|
searching = true
|
@@ -114,6 +148,9 @@ module Kenji
|
|
114
148
|
def self.routes
|
115
149
|
@routes || {}
|
116
150
|
end
|
151
|
+
def self.passes
|
152
|
+
@passes || {}
|
153
|
+
end
|
117
154
|
end
|
118
155
|
end
|
119
156
|
|
data/lib/kenji/version.rb
CHANGED
data/lib/kenji.rb
CHANGED
@@ -8,6 +8,13 @@ module Kenji
|
|
8
8
|
|
9
9
|
attr_reader :env, :root
|
10
10
|
|
11
|
+
# Setting `kenji.status = 203` will affect the status code of the response.
|
12
|
+
attr_accessor :status
|
13
|
+
|
14
|
+
# Methods for rack!
|
15
|
+
|
16
|
+
# Constructor...
|
17
|
+
#
|
11
18
|
def initialize(env, root)
|
12
19
|
@headers = {
|
13
20
|
'Content-Type' => 'application/json'
|
@@ -17,6 +24,8 @@ module Kenji
|
|
17
24
|
@env = env
|
18
25
|
end
|
19
26
|
|
27
|
+
# This method does all the work!
|
28
|
+
#
|
20
29
|
def call
|
21
30
|
path = @env['PATH_INFO']
|
22
31
|
|
@@ -28,6 +37,7 @@ module Kenji
|
|
28
37
|
# new routing code
|
29
38
|
segments = path.split('/')
|
30
39
|
segments = segments.drop(1) if segments.first == '' # discard leading /'s empty segment
|
40
|
+
segments.unshift('')
|
31
41
|
|
32
42
|
acc = ''; out = 'null'
|
33
43
|
while head = segments.shift
|
@@ -56,6 +66,7 @@ module Kenji
|
|
56
66
|
# Sets one or multiple headers, as named arametres. eg.
|
57
67
|
#
|
58
68
|
# kenji.header 'Content-Type' => 'hello/world'
|
69
|
+
#
|
59
70
|
def header(hash={})
|
60
71
|
hash.each do |key, value|
|
61
72
|
@headers[key] = value
|
@@ -64,19 +75,21 @@ module Kenji
|
|
64
75
|
|
65
76
|
# Fetch (and cache) the json input to the request
|
66
77
|
# Return a Hash
|
78
|
+
#
|
67
79
|
def input_as_json
|
68
80
|
return @json_input if @json_input
|
69
81
|
require 'json'
|
70
82
|
raw = @env['rack.input'].read if @env['rack.input']
|
71
83
|
begin
|
72
84
|
return @json_input = JSON.parse(raw)
|
73
|
-
rescue JSON::ParserError
|
85
|
+
rescue JSON::ParserError
|
74
86
|
end if raw
|
75
87
|
{} # default return value
|
76
88
|
end
|
77
89
|
|
78
90
|
# Respond to the request
|
79
|
-
|
91
|
+
#
|
92
|
+
def respond(code, message, hash={})
|
80
93
|
@status = code
|
81
94
|
response = { # default structure. TODO: figure out if i really want to keep this
|
82
95
|
:status => code,
|
@@ -89,13 +102,16 @@ module Kenji
|
|
89
102
|
|
90
103
|
|
91
104
|
# Private methods
|
105
|
+
private
|
92
106
|
|
93
107
|
# Will attempt to fetch the controller, and verify that it is a implements call
|
94
|
-
|
108
|
+
#
|
109
|
+
def controller_for(subpath)
|
110
|
+
subpath = '/_' if subpath == '/'
|
95
111
|
path = "#{@root}controllers#{subpath}.rb"
|
96
112
|
return nil unless File.exists?(path)
|
97
113
|
require path
|
98
|
-
controller_name = subpath.split('/').last
|
114
|
+
controller_name = subpath.split('/').last.sub(/^_/, 'Root')
|
99
115
|
controller_class = Object.const_get(controller_name.to_s.to_camelcase+'Controller')
|
100
116
|
return unless controller_class.method_defined?(:call) && controller_class.instance_method(:call).arity == 2 # ensure protocol compliance
|
101
117
|
controller = controller_class.new
|
data/spec/kenji_spec.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
|
2
|
+
require 'rack'
|
3
|
+
require 'rack/test'
|
4
|
+
require 'rspec'
|
5
|
+
|
6
|
+
require 'kenji'
|
7
|
+
|
8
|
+
|
9
|
+
# NOTE: these tests make use of the controllers defined in test/controllers.
|
10
|
+
|
11
|
+
def app_for(path)
|
12
|
+
lambda do |env|
|
13
|
+
Kenji::Kenji.new(env, File.dirname(__FILE__)+'/'+path).call
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Kenji do
|
18
|
+
|
19
|
+
include Rack::Test::Methods
|
20
|
+
def app; app_for('1'); end
|
21
|
+
|
22
|
+
|
23
|
+
it 'should return "null" for unknown routes' do
|
24
|
+
get '/sdlkjhb'
|
25
|
+
last_response.body.should == 'null'
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should route a GET call to a defined get call' do
|
29
|
+
get '/main/hello'
|
30
|
+
expected_response = {status: 200, hello: :world}.to_json
|
31
|
+
last_response.body.should == expected_response
|
32
|
+
end
|
33
|
+
|
34
|
+
[:post, :put, :delete].each do |method|
|
35
|
+
|
36
|
+
it "should route a #{method.to_s.upcase} to a defined #{method.to_s} call" do
|
37
|
+
send(method, '/main')
|
38
|
+
expected_response = {status: 1337}.to_json
|
39
|
+
last_response.body.should == expected_response
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should return "null" for unsupported methods' do
|
44
|
+
post '/main/hello'
|
45
|
+
last_response.body.should == 'null'
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
describe Kenji do
|
51
|
+
include Rack::Test::Methods
|
52
|
+
def app; app_for('2'); end
|
53
|
+
|
54
|
+
it 'should use root controller' do
|
55
|
+
get '/'
|
56
|
+
expected_response = {status: 200, controller_used: :root}.to_json
|
57
|
+
last_response.body.should == expected_response
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should pass routing down to child controllers' do
|
61
|
+
get '/child/foo'
|
62
|
+
expected_response = {status: 200, foo: :bar}.to_json
|
63
|
+
last_response.body.should == expected_response
|
64
|
+
end
|
65
|
+
end
|
metadata
CHANGED
@@ -1,57 +1,56 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: kenji
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 4
|
8
|
-
version: "0.4"
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.5'
|
5
|
+
prerelease:
|
9
6
|
platform: ruby
|
10
|
-
authors:
|
7
|
+
authors:
|
11
8
|
- Kenneth Ballenegger
|
12
9
|
autorequire:
|
13
10
|
bindir: bin
|
14
11
|
cert_chain: []
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
dependencies:
|
19
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2012-04-05 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
20
15
|
name: json
|
21
|
-
|
22
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
23
17
|
none: false
|
24
|
-
requirements:
|
25
|
-
- -
|
26
|
-
- !ruby/object:Gem::Version
|
27
|
-
|
28
|
-
- 0
|
29
|
-
version: "0"
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
30
22
|
type: :runtime
|
31
|
-
version_requirements: *id001
|
32
|
-
- !ruby/object:Gem::Dependency
|
33
|
-
name: rack
|
34
23
|
prerelease: false
|
35
|
-
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
25
|
none: false
|
37
|
-
requirements:
|
38
|
-
- -
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
|
41
|
-
|
42
|
-
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rack
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
43
38
|
type: :runtime
|
44
|
-
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
45
46
|
description: A lightweight Ruby web framework.
|
46
|
-
email:
|
47
|
+
email:
|
47
48
|
- kenneth@ballenegger.com
|
48
|
-
executables:
|
49
|
+
executables:
|
49
50
|
- kenji-init
|
50
51
|
extensions: []
|
51
|
-
|
52
52
|
extra_rdoc_files: []
|
53
|
-
|
54
|
-
files:
|
53
|
+
files:
|
55
54
|
- .gitignore
|
56
55
|
- Gemfile
|
57
56
|
- LICENSE
|
@@ -77,37 +76,37 @@ files:
|
|
77
76
|
- lib/kenji/controller.rb
|
78
77
|
- lib/kenji/string_extensions.rb
|
79
78
|
- lib/kenji/version.rb
|
80
|
-
|
79
|
+
- spec/1/controllers/main.rb
|
80
|
+
- spec/2/controllers/_.rb
|
81
|
+
- spec/2/controllers/child.rb
|
82
|
+
- spec/kenji_spec.rb
|
81
83
|
homepage: https://github.com/kballenegger/kenji
|
82
84
|
licenses: []
|
83
|
-
|
84
85
|
post_install_message:
|
85
86
|
rdoc_options: []
|
86
|
-
|
87
|
-
require_paths:
|
87
|
+
require_paths:
|
88
88
|
- lib
|
89
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
90
|
none: false
|
91
|
-
requirements:
|
92
|
-
- -
|
93
|
-
- !ruby/object:Gem::Version
|
94
|
-
|
95
|
-
|
96
|
-
version: "0"
|
97
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ! '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
96
|
none: false
|
99
|
-
requirements:
|
100
|
-
- -
|
101
|
-
- !ruby/object:Gem::Version
|
102
|
-
|
103
|
-
- 0
|
104
|
-
version: "0"
|
97
|
+
requirements:
|
98
|
+
- - ! '>='
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
105
101
|
requirements: []
|
106
|
-
|
107
102
|
rubyforge_project:
|
108
|
-
rubygems_version: 1.
|
103
|
+
rubygems_version: 1.8.24
|
109
104
|
signing_key:
|
110
105
|
specification_version: 3
|
111
106
|
summary: Kenji
|
112
|
-
test_files:
|
113
|
-
|
107
|
+
test_files:
|
108
|
+
- spec/1/controllers/main.rb
|
109
|
+
- spec/2/controllers/_.rb
|
110
|
+
- spec/2/controllers/child.rb
|
111
|
+
- spec/kenji_spec.rb
|
112
|
+
has_rdoc:
|