pendragon 0.3.0 → 0.4.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.
- checksums.yaml +4 -4
- data/.travis.yml +7 -0
- data/Gemfile.lock +3 -3
- data/README.md +163 -63
- data/Rakefile +7 -1
- data/lib/pendragon/compile_helpers.rb +30 -23
- data/lib/pendragon/configuration.rb +15 -7
- data/lib/pendragon/error_handler.rb +4 -0
- data/lib/pendragon/matcher.rb +3 -3
- data/lib/pendragon/padrino/router.rb +3 -19
- data/lib/pendragon/route.rb +40 -17
- data/lib/pendragon/router.rb +79 -57
- data/lib/pendragon/version.rb +1 -1
- data/test/padrino_test.rb +11 -10
- data/test/pendragon_configuration.rb +31 -0
- data/test/pendragon_test.rb +78 -8
- metadata +17 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 34a16924c1d2032821eab7f8e670a9823cfe9e6e
|
4
|
+
data.tar.gz: f28901a7ae7bb3dd844b31fd09e65140ab40f700
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69305896d92e425a2901eb8670b644a55d1a22ddab91c33058889fcf7dae1bdcf6c288e0831cc98967cbe65838f182047e825f67cee641b631a39f92c74cf941
|
7
|
+
data.tar.gz: 6be88a0862cdcabe0206bdf3612869b4eb13f890478c4d16336bd2da4cf21c1132f8c561e0bc865d5ec8518b0cc2107d89f498cbc94ecf384bf47d28c8981d9a
|
data/.travis.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -8,7 +8,7 @@ PATH
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
activesupport (4.0.
|
11
|
+
activesupport (4.0.3)
|
12
12
|
i18n (~> 0.6, >= 0.6.4)
|
13
13
|
minitest (~> 4.2)
|
14
14
|
multi_json (~> 1.3)
|
@@ -17,11 +17,11 @@ GEM
|
|
17
17
|
atomic (1.1.14)
|
18
18
|
haml (4.0.5)
|
19
19
|
tilt
|
20
|
-
http_router (0.11.
|
20
|
+
http_router (0.11.1)
|
21
21
|
rack (>= 1.0.0)
|
22
22
|
url_mount (~> 0.2.1)
|
23
23
|
i18n (0.6.9)
|
24
|
-
metaclass (0.0.
|
24
|
+
metaclass (0.0.4)
|
25
25
|
minitest (4.7.5)
|
26
26
|
mocha (1.0.0)
|
27
27
|
metaclass (~> 0.0.1)
|
data/README.md
CHANGED
@@ -1,136 +1,236 @@
|
|
1
1
|
# Pendragon
|
2
2
|
|
3
|
-
[](https://travis-ci.org/namusyaka/pendragon)
|
3
|
+
[](https://travis-ci.org/namusyaka/pendragon) [](http://badge.fury.io/rb/pendragon)
|
4
4
|
|
5
|
-
|
5
|
+
Pendragon provides an HTTP router for use in Rack and Padrino.
|
6
|
+
As a Rack application, it makes it easy to define complicated routing.
|
7
|
+
As a Padrino plugin, your application uses Pendragon instead of http_router.
|
8
|
+
Therefore, some bugs of http_router will be fixed.
|
6
9
|
|
7
|
-
|
10
|
+
*If you want to use in Ruby1.9, you can do it by using [mustermann/1.9-support branch](https://github.com/rkh/mustermann/tree/1.9-support).*
|
8
11
|
|
9
|
-
|
12
|
+
```ruby
|
13
|
+
Pendragon.new do
|
14
|
+
get("/"){ "hello world" }
|
15
|
+
get("/foo/:bar", name: :foo) do |params|
|
16
|
+
"foo is #{params[:bar]}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
```
|
10
20
|
|
11
21
|
## Installation
|
12
22
|
|
13
|
-
|
23
|
+
Depends on [rack](https://github.com/rack/rack) and [mustermann](https://github.com/rkh/mustermann).
|
14
24
|
|
15
|
-
`gem
|
25
|
+
`gem install pendragon`
|
16
26
|
|
17
|
-
|
27
|
+
## Usage
|
18
28
|
|
19
|
-
|
29
|
+
### Configuration
|
20
30
|
|
21
|
-
|
31
|
+
|name |types |default|description |
|
32
|
+
|:---------------|:------|:------|:-------------------------|
|
33
|
+
|enable_compiler |boolean|false|The performance will be improved. However, it will increase the first load time.|
|
34
|
+
|auto_rack_format|boolean|true|If disable this param, the block of route should return the response of valid rack format.|
|
22
35
|
|
23
|
-
|
24
|
-
|
25
|
-
* Route priority will not work (Might support in the future).
|
26
|
-
* Duplicated routes will not work correctly.
|
27
|
-
* MethodNotAllowed will not work.
|
28
|
-
|
29
|
-
This implementation was inspired by [rack-multiplexer](https://github.com/r7kamura/rack-multiplexer).
|
36
|
+
#### `enable_compiler`
|
30
37
|
|
31
38
|
```ruby
|
39
|
+
# Performance will be improved!
|
32
40
|
Pendragon.configure do |config|
|
33
|
-
config.enable_compiler = true
|
41
|
+
config.enable_compiler = true
|
34
42
|
end
|
35
43
|
```
|
36
44
|
|
37
|
-
|
45
|
+
*The compiler mode was inspired by [rack-multiplexer](https://github.com/r7kamura/rack-multiplexer). Thank you!*
|
38
46
|
|
39
|
-
|
47
|
+
#### `auto_rack_format`
|
40
48
|
|
41
49
|
```ruby
|
42
|
-
|
50
|
+
# Enable the param (default)
|
51
|
+
Pendragon.new do
|
52
|
+
get("/"){ "hey" }
|
53
|
+
end
|
43
54
|
|
44
|
-
|
45
|
-
|
46
|
-
|
55
|
+
Pendragon.configure do |config|
|
56
|
+
config.auto_rack_format = false
|
57
|
+
end
|
58
|
+
# Disable the param
|
59
|
+
Pendragon.new do
|
60
|
+
get("/"){ [200, {"Content-Type" => "text/html;charset=utf-8"}, ["hey"]] }
|
47
61
|
end
|
62
|
+
```
|
63
|
+
|
64
|
+
### Register the route
|
65
|
+
|
66
|
+
It has some methods to register a route. For example, `#get`, `#post` and `#delete` are so.
|
67
|
+
This section introduces all those methods.
|
48
68
|
|
49
|
-
|
50
|
-
|
69
|
+
#### `add(verb, path, option, &block)`
|
70
|
+
|
71
|
+
The method is the basis of the registration method of all.
|
72
|
+
In comparison with other registration methods, one argument is increased.
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
Pendragon.new do
|
76
|
+
# The two approach have the same meaning.
|
77
|
+
add(:get, "/"){ "hello world" }
|
78
|
+
get("/"){ "hello world" }
|
51
79
|
end
|
80
|
+
```
|
81
|
+
|
82
|
+
#### `get(path, option, &block)`, `post`, `delete`, `put` and `head`
|
83
|
+
|
84
|
+
Basically the usage is the same with `#add`.
|
85
|
+
You may as well use those methods instead of `#add` because those methods are easy to understand.
|
52
86
|
|
53
|
-
|
54
|
-
|
87
|
+
```ruby
|
88
|
+
Pendragon.new do
|
89
|
+
get("/"){ "hello world" }
|
90
|
+
post("/"){ "hello world" }
|
91
|
+
delete("/"){ "hello world" }
|
92
|
+
put("/"){ "hello world" }
|
93
|
+
head("/"){ "hello world" }
|
55
94
|
end
|
95
|
+
```
|
96
|
+
|
97
|
+
##### Path
|
98
|
+
|
99
|
+
The path must be an instance of String (this must be complied with the Mustermann::Sinatra's rule) or Regexp.
|
100
|
+
|
101
|
+
##### Route options
|
102
|
+
|
103
|
+
|name|types |description |
|
104
|
+
|:----|:------|:-------------------------|
|
105
|
+
|name |symbol |specify the name of route for `Pendragon::Router#path` method.|
|
106
|
+
|order|integer|specify the order for the prioritized routes.|
|
107
|
+
|capture|hash|specify the capture for matching condition. [more information here](https://github.com/rkh/mustermann)|
|
108
|
+
|status|integer|specify the status code of response|
|
109
|
+
|header|hash|specify the header of response|
|
56
110
|
|
111
|
+
##### Block Parameters
|
57
112
|
|
58
|
-
|
59
|
-
|
113
|
+
The block is allowed to pass a parameter.
|
114
|
+
It will be an instance of Hash.
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
pendragon = Pendragon.new do
|
118
|
+
get("/:id/:foo/:bar"){|params| params.inspect }
|
60
119
|
end
|
61
120
|
|
62
|
-
|
121
|
+
request = Rack::MockRequest.env_for("/123/hey/ho")
|
122
|
+
pendragon.recognize(request).first.call #=> '{id: "123", foo: "hey", bar: "ho"}'
|
63
123
|
```
|
64
124
|
|
65
|
-
|
125
|
+
### Recognize the route
|
126
|
+
|
127
|
+
The route registered can be recognized by several methods.
|
66
128
|
|
67
|
-
|
129
|
+
#### `recognize(request)`
|
130
|
+
|
131
|
+
This method returns all the routes that match the conditions.
|
132
|
+
The format of returns will be such as `[[Pendragon::Route, params], ...]`.
|
133
|
+
The request must be an instance of `Rack::Request` or Hash created by `Rack::MockRequest.env_for`.
|
68
134
|
|
69
135
|
```ruby
|
70
136
|
pendragon = Pendragon.new
|
137
|
+
index = pendragon.get("/"){ "hello world" }
|
138
|
+
foo = pendragon.get("/foo/:bar"){ "foo is bar" }
|
71
139
|
|
72
|
-
|
73
|
-
|
74
|
-
|
140
|
+
mock_request = Rack::MockRequest.env_for("/")
|
141
|
+
route, params = pendragon.recognize(mock_request).first
|
142
|
+
|
143
|
+
route.path == index.path #=> true
|
144
|
+
params #=> {}
|
145
|
+
|
146
|
+
mock_request = Rack::MockRequest.env_for("/foo/baz")
|
147
|
+
route, params = pendragon.recognize(mock_request).first
|
148
|
+
|
149
|
+
route.path == foo.path #=> true
|
150
|
+
params #=> {bar: "baz"}
|
75
151
|
```
|
76
152
|
|
77
|
-
|
153
|
+
#### `recognize_path(path_info)`
|
78
154
|
|
79
|
-
|
80
|
-
|
155
|
+
Recognizes a route from `path_info`.
|
156
|
+
The method uses `#recognize`, but return value is not same with it.
|
157
|
+
Maybe this is useful if you set the name to the route.
|
81
158
|
|
82
|
-
|
83
|
-
|
159
|
+
```ruby
|
160
|
+
pendragon = Pendragon.new do
|
161
|
+
get("/", name: :index){ "hello world" }
|
162
|
+
get("/:id", name: :foo){ "fooooo" }
|
84
163
|
end
|
164
|
+
|
165
|
+
pendragon.recognize_path("/") #=> [:index, {}]
|
166
|
+
pendragon.recognize_path("/hey") #=> [:foo, {id: "hey"}]
|
85
167
|
```
|
86
168
|
|
87
|
-
|
169
|
+
#### `path(name, *args)`
|
88
170
|
|
89
|
-
|
90
|
-
|
171
|
+
Recognizes a route from route's name, and expands the path from parameters.
|
172
|
+
If you pass a name that does not exist, Pendragon raises `InvalidRouteException`.
|
173
|
+
The parameters that is not required to expand will be treated as query.
|
91
174
|
|
92
|
-
|
93
|
-
|
175
|
+
```ruby
|
176
|
+
pendragon = Pendragon.new do
|
177
|
+
get("/", name: :index){ "hello world" }
|
178
|
+
get("/:id", name: :foo){ "fooooo" }
|
94
179
|
end
|
95
180
|
|
96
|
-
pendragon.
|
97
|
-
|
98
|
-
|
181
|
+
pendragon.path(:index) #=> "/"
|
182
|
+
pendragon.path(:foo, id: "123") #=> "/123"
|
183
|
+
pendragon.path(:foo, id: "123", bar: "hey") #=> "/123?bar=hey"
|
99
184
|
```
|
100
185
|
|
101
|
-
###
|
186
|
+
### Prioritized Routes
|
102
187
|
|
103
|
-
|
104
|
-
|
188
|
+
Pendragon supports for respecting route order.
|
189
|
+
If you want to use this, you should pass the `:order` option to the registration method.
|
105
190
|
|
106
|
-
|
107
|
-
|
191
|
+
```ruby
|
192
|
+
pendragon = Pendragon.new do
|
193
|
+
get("/", order: 1){ "two" }
|
194
|
+
get("/", order: 0){ "one" }
|
195
|
+
get("/", order: 2){ "three" }
|
108
196
|
end
|
109
|
-
|
197
|
+
|
198
|
+
request = Rack::MockRequest.env_for("/")
|
199
|
+
pendragon.recognize(request).map{|route, _| route.call } #=> ["one", "two", "three"]
|
110
200
|
```
|
111
201
|
|
112
|
-
###
|
202
|
+
### Passing
|
113
203
|
|
114
|
-
|
115
|
-
pendragon = Pendragon.new
|
204
|
+
A route can punt processing to the next matching route using `throw :pass`
|
116
205
|
|
117
|
-
|
118
|
-
|
206
|
+
```ruby
|
207
|
+
pendragon = Pendragon.new do
|
208
|
+
foo = nil
|
209
|
+
get("/"){ foo = "yay"; throw :pass }
|
210
|
+
get("/"){ foo }
|
119
211
|
end
|
120
|
-
users.name = :users
|
121
212
|
|
122
|
-
|
213
|
+
request = Rack::MockRequest.env_for("/")
|
214
|
+
pendragon.call(request) #=> [200, {"Content-Type"=>"text/html;charset=utf-8"}, ["yay"]]
|
123
215
|
```
|
124
216
|
|
125
|
-
|
217
|
+
### With Padrino
|
218
|
+
|
219
|
+
Add `register Pendragon::Padrino` to your padrino application.
|
220
|
+
Of course, Pendragon has compatibility with Padrino Routing.
|
126
221
|
|
127
|
-
If you use Pendragon, your application does not use http_router.
|
128
222
|
|
129
223
|
```ruby
|
130
224
|
require 'pendragon/padrino'
|
131
225
|
|
132
226
|
class App < Padrino::Application
|
133
227
|
register Pendragon::Padrino
|
228
|
+
|
229
|
+
##
|
230
|
+
# Also, your app's performance will be improved by using compiler mode.
|
231
|
+
# Pendragon.configure do |config|
|
232
|
+
# config.enable_compiler = true
|
233
|
+
# end
|
134
234
|
|
135
235
|
get :index do
|
136
236
|
"hello pendragon!"
|
data/Rakefile
CHANGED
@@ -15,5 +15,11 @@ Rake::TestTask.new(:test_with_compiler) do |test|
|
|
15
15
|
test.verbose = true
|
16
16
|
end
|
17
17
|
|
18
|
-
|
18
|
+
Rake::TestTask.new(:configuration) do |test|
|
19
|
+
test.libs << 'test'
|
20
|
+
test.test_files = Dir['test/**/*_configuration.rb']
|
21
|
+
test.verbose = true
|
22
|
+
end
|
23
|
+
|
24
|
+
task :test => [:test_without_compiler, :test_with_compiler, :configuration]
|
19
25
|
task :default => :test
|
@@ -2,40 +2,47 @@
|
|
2
2
|
module Pendragon
|
3
3
|
module CompileHelpers
|
4
4
|
def compile!
|
5
|
-
|
6
|
-
@routes.
|
5
|
+
return if compiled?
|
6
|
+
@regexps = @routes.map.with_index do |route, index|
|
7
7
|
regexp = route.matcher.handler
|
8
8
|
regexp = regexp.to_regexp if route.matcher.mustermann?
|
9
|
-
|
10
|
-
|
9
|
+
route.index = index
|
10
|
+
/(?<_#{index}>#{regexp})/
|
11
11
|
end
|
12
|
-
@
|
12
|
+
@regexps = compile(@regexps)
|
13
|
+
end
|
14
|
+
|
15
|
+
def compile(regexps, paths = [])
|
16
|
+
return paths if regexps.length.zero?
|
17
|
+
paths << Regexp.union(regexps)
|
18
|
+
regexps.shift
|
19
|
+
compile(regexps, paths)
|
13
20
|
end
|
14
21
|
|
15
22
|
def compiled?
|
16
|
-
!!@
|
23
|
+
!!@regexps
|
17
24
|
end
|
18
25
|
|
19
26
|
def recognize_by_compiling_regexp(request)
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
+
prepare! unless prepared?
|
28
|
+
pattern, verb, params = parse_request(request)
|
29
|
+
candidacies = match_with(pattern)
|
30
|
+
raise_exception(404) if candidacies.empty?
|
31
|
+
candidacies, allows = candidacies.partition{|route| route.verb == verb }
|
32
|
+
raise_exception(405, verbs: allows.map(&:verb)) if candidacies.empty?
|
33
|
+
candidacies.map{|route| [route, params_for(route, pattern, params)]}
|
34
|
+
end
|
27
35
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
36
|
+
def match_with(pattern)
|
37
|
+
offset = 0
|
38
|
+
conditions = [pattern]
|
39
|
+
conditions << pattern[0..-2] if pattern != "/" && pattern.end_with?("/")
|
40
|
+
loop.with_object([]) do |_, candidacies|
|
41
|
+
return candidacies unless conditions.any?{|x| @regexps[offset] === x }
|
42
|
+
route = @routes[offset..-1].detect{|route| Regexp.last_match("_#{route.index}") }
|
43
|
+
candidacies << route
|
44
|
+
offset = route.index + 1
|
37
45
|
end
|
38
|
-
[[route, params]]
|
39
46
|
end
|
40
47
|
end
|
41
48
|
end
|
@@ -1,25 +1,33 @@
|
|
1
1
|
module Pendragon
|
2
2
|
class Configuration
|
3
3
|
|
4
|
+
# Define the accessor as boolean method
|
5
|
+
def self.attr_boolean_accessor(*keys)
|
6
|
+
keys.each do |key|
|
7
|
+
attr_accessor key
|
8
|
+
define_method("#{key}?"){ !!__send__(key) }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
4
12
|
# Enables to compile the routes
|
5
13
|
# Improve the performance by using this option,
|
6
14
|
# but some features will not work correctly.
|
7
15
|
# @see Pendragon::Router#compile
|
8
|
-
|
16
|
+
attr_boolean_accessor :enable_compiler
|
17
|
+
|
18
|
+
# Automatically convert response into Rack format.
|
19
|
+
# Default value is `true`.
|
20
|
+
attr_boolean_accessor :auto_rack_format
|
9
21
|
|
10
22
|
# Constructs an instance of Pendragon::Configuration
|
11
23
|
def initialize
|
12
|
-
@enable_compiler
|
24
|
+
@enable_compiler = false
|
25
|
+
@auto_rack_format = true
|
13
26
|
end
|
14
27
|
|
15
28
|
# Returns an instance variable
|
16
29
|
def [](variable_name)
|
17
30
|
instance_variable_get("@#{variable_name}")
|
18
31
|
end
|
19
|
-
|
20
|
-
# Returns a boolean of @enable_compiler
|
21
|
-
def enable_compiler?
|
22
|
-
!!@enable_compiler
|
23
|
-
end
|
24
32
|
end
|
25
33
|
end
|
@@ -34,6 +34,10 @@ module Pendragon
|
|
34
34
|
class MethodNotAllowed < ErrorHandler
|
35
35
|
set :status, 405
|
36
36
|
set :body, "Method Not Allowed"
|
37
|
+
|
38
|
+
def initialize(verbs)
|
39
|
+
default_response[1].merge!("Allow" => verbs.map{|verb| verb.upcase } * ", ")
|
40
|
+
end
|
37
41
|
end
|
38
42
|
|
39
43
|
class BadRequest < ErrorHandler
|
data/lib/pendragon/matcher.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'mustermann'
|
1
|
+
require 'mustermann/sinatra'
|
2
2
|
|
3
3
|
module Pendragon
|
4
4
|
class Matcher
|
@@ -22,7 +22,7 @@ module Pendragon
|
|
22
22
|
# @return [Nil] If the pattern doesn't matched this route, return a nil.
|
23
23
|
#
|
24
24
|
def match(pattern)
|
25
|
-
pattern = pattern[0..-2] if mustermann? and pattern != "/" and pattern
|
25
|
+
pattern = pattern[0..-2] if mustermann? and pattern != "/" and pattern.end_with?("/")
|
26
26
|
handler.match(pattern)
|
27
27
|
end
|
28
28
|
|
@@ -59,7 +59,7 @@ module Pendragon
|
|
59
59
|
@handler ||=
|
60
60
|
case @path
|
61
61
|
when String
|
62
|
-
Mustermann.new(@path, :capture => @capture)
|
62
|
+
Mustermann::Sinatra.new(@path, :capture => @capture)
|
63
63
|
when Regexp
|
64
64
|
/^(?:#{@path})$/
|
65
65
|
end
|
@@ -13,32 +13,16 @@ module Pendragon
|
|
13
13
|
|
14
14
|
def call(env)
|
15
15
|
request = Rack::Request.new(env)
|
16
|
-
|
17
|
-
prepare! unless prepared?
|
16
|
+
raise_exception(400) unless valid_verb?(request.request_method)
|
18
17
|
[200, {}, recognize(request)]
|
19
18
|
rescue BadRequest, NotFound, MethodNotAllowed
|
20
19
|
$!.call
|
21
20
|
end
|
22
21
|
|
23
22
|
def path(name, *args)
|
24
|
-
|
25
|
-
|
26
|
-
@routes.each do |route|
|
27
|
-
next unless route.options[:name] == name
|
28
|
-
matcher = route.matcher
|
29
|
-
if !args.empty? and matcher.mustermann?
|
30
|
-
matcher_names = matcher.names
|
31
|
-
params_for_expand = Hash[matcher_names.map{|matcher_name|
|
32
|
-
[matcher_name.to_sym, (params[matcher_name.to_sym] || args.shift)]
|
33
|
-
}]
|
34
|
-
params_for_expand.merge!(Hash[params.select{|k, v| !matcher_names.include?(name.to_sym) }])
|
35
|
-
args = saved_args.dup
|
36
|
-
else
|
37
|
-
params_for_expand = params.dup
|
38
|
-
end
|
39
|
-
return matcher.mustermann? ? matcher.expand(params_for_expand) : route.path_for_generation
|
23
|
+
extract_with_name(name, *args) do |route, params, matcher|
|
24
|
+
matcher.mustermann? ? matcher.expand(params) : route.path_for_generation
|
40
25
|
end
|
41
|
-
raise InvalidRouteException
|
42
26
|
end
|
43
27
|
end
|
44
28
|
end
|
data/lib/pendragon/route.rb
CHANGED
@@ -1,21 +1,25 @@
|
|
1
1
|
module Pendragon
|
2
2
|
class Route
|
3
3
|
|
4
|
-
##
|
5
4
|
# The accessors are useful to access from Pendragon::Router
|
6
|
-
attr_accessor :
|
5
|
+
attr_accessor :name, :capture, :order, :options
|
7
6
|
|
8
|
-
##
|
9
7
|
# For compile option
|
10
8
|
attr_accessor :index
|
11
9
|
|
12
|
-
|
10
|
+
# The verb should be read from Pendragon::Router
|
11
|
+
attr_reader :verb, :block
|
12
|
+
|
13
|
+
# The router will be treated in this class.
|
14
|
+
attr_writer :router
|
15
|
+
|
13
16
|
# Constructs a new instance of Pendragon::Route
|
14
17
|
def initialize(path, verb, options = {}, &block)
|
15
18
|
@block = block if block_given?
|
16
|
-
@path, @verb
|
19
|
+
@path, @verb = path, verb
|
17
20
|
@capture = {}
|
18
21
|
@order = 0
|
22
|
+
merge_with_options!(options)
|
19
23
|
end
|
20
24
|
|
21
25
|
def matcher
|
@@ -24,7 +28,7 @@ module Pendragon
|
|
24
28
|
end
|
25
29
|
|
26
30
|
def arity
|
27
|
-
block.arity
|
31
|
+
@block.arity
|
28
32
|
end
|
29
33
|
|
30
34
|
def call(*args)
|
@@ -35,19 +39,10 @@ module Pendragon
|
|
35
39
|
matcher.match(pattern)
|
36
40
|
end
|
37
41
|
|
38
|
-
def name
|
39
|
-
@options[:name]
|
40
|
-
end
|
41
|
-
|
42
|
-
def name=(value)
|
43
|
-
warn "[DEPRECATION] 'name=' is depreacted. Please use 'options[:name]=' instead"
|
44
|
-
@options[:name] = value
|
45
|
-
end
|
46
|
-
|
47
42
|
def to(&block)
|
48
43
|
@block = block if block_given?
|
49
|
-
@order = router.current
|
50
|
-
router.increment_order!
|
44
|
+
@order = @router.current
|
45
|
+
@router.increment_order!
|
51
46
|
end
|
52
47
|
|
53
48
|
def path(*args)
|
@@ -56,5 +51,33 @@ module Pendragon
|
|
56
51
|
params.delete(:captures)
|
57
52
|
matcher.expand(params) if matcher.mustermann?
|
58
53
|
end
|
54
|
+
|
55
|
+
def params(pattern, parameters = {})
|
56
|
+
match_data, params = match(pattern), {}
|
57
|
+
if match_data.names.empty?
|
58
|
+
params.merge!(:captures => match_data.captures) unless match_data.captures.empty?
|
59
|
+
params
|
60
|
+
else
|
61
|
+
params = matcher.handler.params(pattern, :captures => match_data) || params
|
62
|
+
symbolize(params).merge(parameters){|key, old, new| old || new }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def symbolize(parameters)
|
67
|
+
parameters.inject({}){|result, (key, val)| result[key.to_sym] = val; result }
|
68
|
+
end
|
69
|
+
|
70
|
+
def merge_with_options!(options)
|
71
|
+
@options = {} unless @options
|
72
|
+
options.each_pair do |key, value|
|
73
|
+
accessor?(key) ? __send__("#{key}=", value) : (@options[key] = value)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def accessor?(key)
|
78
|
+
respond_to?("#{key}=") && respond_to?(key)
|
79
|
+
end
|
80
|
+
|
81
|
+
private :symbolize, :merge_with_options!, :accessor?
|
59
82
|
end
|
60
83
|
end
|
data/lib/pendragon/router.rb
CHANGED
@@ -33,15 +33,22 @@ module Pendragon
|
|
33
33
|
# @return the Rack style response
|
34
34
|
def call(env)
|
35
35
|
request = Rack::Request.new(env)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
[200, {'Content-Type' => 'text/html;charset=utf-8'}, Array(body)]
|
36
|
+
raise_exception(400) unless valid_verb?(request.request_method)
|
37
|
+
recognize(request).each do |route, params|
|
38
|
+
catch(:pass){ return invoke(route, params) }
|
39
|
+
end
|
41
40
|
rescue BadRequest, NotFound, MethodNotAllowed
|
42
41
|
$!.call
|
43
42
|
end
|
44
43
|
|
44
|
+
def invoke(route, params)
|
45
|
+
response = route.arity != 0 ? route.call(params) : route.call
|
46
|
+
return response unless Pendragon.configuration.auto_rack_format?
|
47
|
+
status = route.options[:status] || 200
|
48
|
+
header = {'Content-Type' => 'text/html;charset=utf-8'}.merge(route.options[:header] || {})
|
49
|
+
[status, header, Array(response)]
|
50
|
+
end
|
51
|
+
|
45
52
|
# Provides some methods intuitive than #add
|
46
53
|
# Basic usage is the same as #add
|
47
54
|
# @see Pendragon::Router#add
|
@@ -70,15 +77,17 @@ module Pendragon
|
|
70
77
|
# This method is executed only once in the initial load
|
71
78
|
def prepare!
|
72
79
|
@prepared = true
|
73
|
-
@routes.sort_by!(&:order)
|
74
|
-
if Pendragon.configuration.enable_compiler?
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
80
|
+
@routes.sort_by!(&:order)
|
81
|
+
self.class.setup_compiler! && compile! if Pendragon.configuration.enable_compiler?
|
82
|
+
end
|
83
|
+
|
84
|
+
# Setups the compiler by using CompileHelpers
|
85
|
+
# @see Pendragon::CompileHelpers
|
86
|
+
def self.setup_compiler!
|
87
|
+
include CompileHelpers
|
88
|
+
alias_method :old_recognize, :recognize
|
89
|
+
alias_method :recognize, :recognize_by_compiling_regexp
|
90
|
+
true
|
82
91
|
end
|
83
92
|
|
84
93
|
# @return [Boolean] the router is already prepared?
|
@@ -95,19 +104,9 @@ module Pendragon
|
|
95
104
|
# @param request [Rack::Request]
|
96
105
|
# @return [Array]
|
97
106
|
def recognize(request)
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
if match_data.names.empty?
|
102
|
-
params[:captures] = match_data.captures
|
103
|
-
else
|
104
|
-
params.merge!(match_data.names.inject({}){|result, name|
|
105
|
-
result[name.to_sym] = match_data[name] ? Rack::Utils.unescape(match_data[name]) : nil
|
106
|
-
result
|
107
|
-
}).merge!(request_params){|key, self_val, new_val| self_val || new_val }
|
108
|
-
end
|
109
|
-
[route, params]
|
110
|
-
end
|
107
|
+
prepare! unless prepared?
|
108
|
+
pattern, verb, params = parse_request(request)
|
109
|
+
fetch(pattern, verb){|route| [route, params_for(route, pattern, params)] }
|
111
110
|
end
|
112
111
|
|
113
112
|
# Recognizes a given path
|
@@ -115,7 +114,7 @@ module Pendragon
|
|
115
114
|
# @return [Array]
|
116
115
|
def recognize_path(path_info)
|
117
116
|
route, params = recognize(Rack::MockRequest.env_for(path_info)).first
|
118
|
-
[route.
|
117
|
+
[route.name, params]
|
119
118
|
end
|
120
119
|
|
121
120
|
# Returns a expanded path matched with the conditions as arguments
|
@@ -126,23 +125,9 @@ module Pendragon
|
|
126
125
|
# router.path(:index, :id => 1) #=> "/1"
|
127
126
|
# router.path(:index, :id => 2, :foo => "bar") #=> "/1?foo=bar"
|
128
127
|
def path(name, *args)
|
129
|
-
|
130
|
-
|
131
|
-
@routes.each do |route|
|
132
|
-
next unless route.options[:name] == name
|
133
|
-
matcher = route.matcher
|
134
|
-
if !args.empty? and matcher.mustermann?
|
135
|
-
matcher_names = matcher.names
|
136
|
-
params_for_expand = Hash[matcher_names.map{|matcher_name|
|
137
|
-
[matcher_name.to_sym, (params[matcher_name.to_sym] || args.shift)]}]
|
138
|
-
params_for_expand.merge!(Hash[params.select{|k, v| !matcher_names.include?(name.to_sym) }])
|
139
|
-
args = saved_args.dup
|
140
|
-
else
|
141
|
-
params_for_expand = params.dup
|
142
|
-
end
|
143
|
-
return matcher.mustermann? ? matcher.expand(params_for_expand) : route.path
|
128
|
+
extract_with_name(name, *args) do |route, params, matcher|
|
129
|
+
matcher.mustermann? ? matcher.expand(params) : route.path
|
144
130
|
end
|
145
|
-
raise InvalidRouteException
|
146
131
|
end
|
147
132
|
|
148
133
|
private
|
@@ -153,19 +138,12 @@ module Pendragon
|
|
153
138
|
end
|
154
139
|
|
155
140
|
# @!visibility private
|
156
|
-
def
|
157
|
-
|
158
|
-
|
159
|
-
result =
|
160
|
-
|
161
|
-
|
162
|
-
end.compact
|
163
|
-
|
164
|
-
if result.empty?
|
165
|
-
raise MethodNotAllowed.new(selected_routes.map(&:verb))
|
166
|
-
else
|
167
|
-
result
|
168
|
-
end
|
141
|
+
def fetch(pattern, verb)
|
142
|
+
_routes = routes.select{|route| route.match(pattern) }
|
143
|
+
raise_exception(404) if _routes.empty?
|
144
|
+
result = _routes.map{|route| yield(route) if verb == route.verb }.compact
|
145
|
+
raise_exception(405, :verbs => _routes.map(&:verb)) if result.empty?
|
146
|
+
result
|
169
147
|
end
|
170
148
|
|
171
149
|
# @!visibility private
|
@@ -184,5 +162,49 @@ module Pendragon
|
|
184
162
|
result
|
185
163
|
end
|
186
164
|
end
|
165
|
+
|
166
|
+
# @!visibility private
|
167
|
+
def params_for(route, pattern, params)
|
168
|
+
route.params(pattern, params)
|
169
|
+
end
|
170
|
+
|
171
|
+
# @!visibility private
|
172
|
+
# @example
|
173
|
+
# extract_with_name(:index) do |route, params|
|
174
|
+
# route.matcher.mustermann? ? route.matcher.expand(params) : route.path
|
175
|
+
# end
|
176
|
+
def extract_with_name(name, *args)
|
177
|
+
params = args.delete_at(args.last.is_a?(Hash) ? -1 : 0) || {}
|
178
|
+
saved_args = args.dup
|
179
|
+
@routes.each do |route|
|
180
|
+
next unless route.name == name
|
181
|
+
matcher = route.matcher
|
182
|
+
if !args.empty? and matcher.mustermann?
|
183
|
+
matcher_names = matcher.names
|
184
|
+
params_for_expand = Hash[matcher_names.map{|matcher_name|
|
185
|
+
[matcher_name.to_sym, (params[matcher_name.to_sym] || args.shift)]}]
|
186
|
+
params_for_expand.merge!(Hash[params.select{|k, v| !matcher_names.include?(name.to_sym) }])
|
187
|
+
args = saved_args.dup
|
188
|
+
else
|
189
|
+
params_for_expand = params.dup
|
190
|
+
end
|
191
|
+
return yield(route, params_for_expand, matcher)
|
192
|
+
end
|
193
|
+
raise InvalidRouteException
|
194
|
+
end
|
195
|
+
|
196
|
+
# @!visibility private
|
197
|
+
def raise_exception(error_code, options = {})
|
198
|
+
raise ->(error_code) {
|
199
|
+
case error_code
|
200
|
+
when 400
|
201
|
+
BadRequest
|
202
|
+
when 404
|
203
|
+
NotFound
|
204
|
+
when 405
|
205
|
+
MethodNotAllowed.new(options[:verbs])
|
206
|
+
end
|
207
|
+
}.(error_code)
|
208
|
+
end
|
187
209
|
end
|
188
210
|
end
|
data/lib/pendragon/version.rb
CHANGED
data/test/padrino_test.rb
CHANGED
@@ -148,7 +148,6 @@ describe "Pendragon::Padrino" do
|
|
148
148
|
end
|
149
149
|
|
150
150
|
should "match user agents" do
|
151
|
-
skip if enable_compiler?
|
152
151
|
app = mock_app do
|
153
152
|
get("/main", :agent => /IE/){ "hello IE" }
|
154
153
|
get("/main"){ "hello" }
|
@@ -595,7 +594,6 @@ describe "Pendragon::Padrino" do
|
|
595
594
|
end
|
596
595
|
|
597
596
|
should '405 on wrong request_method' do
|
598
|
-
skip if enable_compiler?
|
599
597
|
mock_app do
|
600
598
|
post('/bar'){ "bar" }
|
601
599
|
end
|
@@ -603,6 +601,15 @@ describe "Pendragon::Padrino" do
|
|
603
601
|
assert_equal 405, status
|
604
602
|
end
|
605
603
|
|
604
|
+
should "set Allow header when occur 405" do
|
605
|
+
mock_app do
|
606
|
+
post("/bar"){}
|
607
|
+
put("/bar"){}
|
608
|
+
end
|
609
|
+
get "/bar"
|
610
|
+
assert_equal "POST, PUT", response.headers['Allow']
|
611
|
+
end
|
612
|
+
|
606
613
|
should 'respond to' do
|
607
614
|
mock_app do
|
608
615
|
get(:a, :provides => :js){ "js" }
|
@@ -847,7 +854,6 @@ describe "Pendragon::Padrino" do
|
|
847
854
|
|
848
855
|
|
849
856
|
should 'respect priorities' do
|
850
|
-
skip if enable_compiler?
|
851
857
|
route_order = []
|
852
858
|
mock_app do
|
853
859
|
get(:index, :priority => :normal) { route_order << :normal; pass }
|
@@ -1083,7 +1089,6 @@ describe "Pendragon::Padrino" do
|
|
1083
1089
|
end
|
1084
1090
|
|
1085
1091
|
should "transitions to the next matching route on pass" do
|
1086
|
-
skip if enable_compiler?
|
1087
1092
|
mock_app do
|
1088
1093
|
get '/:foo' do
|
1089
1094
|
pass
|
@@ -1263,7 +1268,6 @@ describe "Pendragon::Padrino" do
|
|
1263
1268
|
end
|
1264
1269
|
|
1265
1270
|
should 'allows custom route-conditions to be set via route options using two routes' do
|
1266
|
-
skip if enable_compiler?
|
1267
1271
|
protector = Module.new do
|
1268
1272
|
def protect(*args)
|
1269
1273
|
condition { authorize(params["user"], params["password"]) }
|
@@ -1329,7 +1333,6 @@ describe "Pendragon::Padrino" do
|
|
1329
1333
|
end
|
1330
1334
|
|
1331
1335
|
should "allow passing & halting in before filters" do
|
1332
|
-
skip if enable_compiler?
|
1333
1336
|
mock_app do
|
1334
1337
|
controller do
|
1335
1338
|
before { env['QUERY_STRING'] == 'secret' or pass }
|
@@ -1813,10 +1816,8 @@ describe "Pendragon::Padrino" do
|
|
1813
1816
|
post '/hi.json', {'_method'=>'PUT'}
|
1814
1817
|
assert_equal 200, status
|
1815
1818
|
assert_equal 'hi', body
|
1816
|
-
|
1817
|
-
|
1818
|
-
assert_equal 405, status
|
1819
|
-
end
|
1819
|
+
post '/hi.json'
|
1820
|
+
assert_equal 405, status
|
1820
1821
|
end
|
1821
1822
|
|
1822
1823
|
should 'parse nested params' do
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.expand_path('../../lib/pendragon', __FILE__)
|
2
|
+
$:.unshift(File.dirname(__FILE__))
|
3
|
+
require 'helper'
|
4
|
+
|
5
|
+
describe Pendragon::Configuration do
|
6
|
+
setup{ @pendragon = pendragon }
|
7
|
+
teardown{ Pendragon.reset_configuration! }
|
8
|
+
|
9
|
+
describe "auto_rack_format" do
|
10
|
+
should "set `true` as default value" do
|
11
|
+
@pendragon.get("/"){ "hey" }
|
12
|
+
get "/"
|
13
|
+
assert_equal "hey", body
|
14
|
+
assert_equal true, Pendragon.configuration.auto_rack_format?
|
15
|
+
end
|
16
|
+
|
17
|
+
should "not serialize for rack format if `auto_rack_format` is false" do
|
18
|
+
Pendragon.configure do |config|
|
19
|
+
config.auto_rack_format = false
|
20
|
+
end
|
21
|
+
|
22
|
+
@pendragon.get("/"){ "hey" }
|
23
|
+
assert_raises(Rack::Lint::LintError){ get "/" }
|
24
|
+
|
25
|
+
@pendragon.post("/"){ [200, {'Content-Type' => 'text/html;charset=utf-8'}, ["hey"]] }
|
26
|
+
post "/"
|
27
|
+
assert_equal "hey", body
|
28
|
+
assert_equal false, Pendragon.configuration.auto_rack_format?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/test/pendragon_test.rb
CHANGED
@@ -82,7 +82,68 @@ describe Pendragon do
|
|
82
82
|
head("/")
|
83
83
|
assert_equal "", body
|
84
84
|
end
|
85
|
+
|
86
|
+
should "support for correct options" do
|
87
|
+
named_route = @pendragon.get("/name/:name", name: :named_route){}
|
88
|
+
incorrect_route = @pendragon.get("/router", router: :incorrect!){}
|
89
|
+
status_route = @pendragon.get("/router", status: 200){}
|
90
|
+
assert_equal :named_route, named_route.name
|
91
|
+
assert_equal "/name/foo", @pendragon.path(:named_route, name: :foo)
|
92
|
+
assert_equal true, incorrect_route.instance_variable_get(:@router).instance_of?(Pendragon::Router)
|
93
|
+
end
|
94
|
+
|
95
|
+
should "allow to throw :pass for routing like journey" do
|
96
|
+
foo = nil
|
97
|
+
@pendragon.get("/"){ foo = "yay"; throw :pass }
|
98
|
+
@pendragon.get("/"){ foo }
|
99
|
+
get "/"
|
100
|
+
assert_equal "yay", body
|
101
|
+
end
|
85
102
|
end
|
103
|
+
|
104
|
+
describe "route options" do
|
105
|
+
should "support for :capture option" do
|
106
|
+
capture = {foo: /\d+/, bar: "bar"}
|
107
|
+
route = @pendragon.get("/:foo/:bar", capture: capture){}
|
108
|
+
assert_equal route.capture, capture
|
109
|
+
assert_equal nil, route.match("/foo/bar")
|
110
|
+
assert_equal nil, route.match("/123/baz")
|
111
|
+
assert_equal true, route.match("/123/bar").instance_of?(MatchData)
|
112
|
+
end
|
113
|
+
|
114
|
+
should "support for :name option" do
|
115
|
+
route = @pendragon.get("/name/:name", name: :named_route){}
|
116
|
+
assert_equal :named_route, route.name
|
117
|
+
assert_equal "/name/foo", @pendragon.path(:named_route, name: :foo)
|
118
|
+
end
|
119
|
+
|
120
|
+
should "not support for :router option" do
|
121
|
+
route = @pendragon.get("/router", router: :incorrect!){}
|
122
|
+
assert_equal true, route.instance_variable_get(:@router).instance_of?(Pendragon::Router)
|
123
|
+
end
|
124
|
+
|
125
|
+
should "support for :order option" do
|
126
|
+
@pendragon.get("/", order: 2){ "three" }
|
127
|
+
@pendragon.get("/", order: 0){ "one" }
|
128
|
+
@pendragon.get("/", order: 1){ "two" }
|
129
|
+
request = Rack::MockRequest.env_for("/")
|
130
|
+
assert_equal ["one", "two", "three"], @pendragon.recognize(request).map{|route, _| route.call }
|
131
|
+
end
|
132
|
+
|
133
|
+
should "support for :status option" do
|
134
|
+
@pendragon.get("/", status: 201){ "hey" }
|
135
|
+
get "/"
|
136
|
+
assert_equal 201, status
|
137
|
+
end
|
138
|
+
|
139
|
+
should "support for :header option" do
|
140
|
+
header = {"Content-Type" => "text/plain;"}
|
141
|
+
@pendragon.get("/", header: header){ "hey" }
|
142
|
+
get "/"
|
143
|
+
assert_equal header.merge("Content-Length" => "3"), headers
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
86
147
|
describe "regexp routing" do
|
87
148
|
before(:each){ @pendragon.reset! }
|
88
149
|
|
@@ -107,18 +168,18 @@ describe Pendragon do
|
|
107
168
|
foo_bar = @pendragon.add(:post, "/foo/bar", :name => :foo_bar){}
|
108
169
|
users = @pendragon.add(:get, "/users/:user_id", :name => :users){}
|
109
170
|
|
110
|
-
assert_equal @pendragon.path(:index)
|
111
|
-
assert_equal @pendragon.path(:foo_bar)
|
112
|
-
assert_equal @pendragon.path(:users, :user_id => 1)
|
113
|
-
assert_equal @pendragon.path(:users, :user_id => 1, :query => "string")
|
171
|
+
assert_equal "/", @pendragon.path(:index)
|
172
|
+
assert_equal "/foo/bar", @pendragon.path(:foo_bar)
|
173
|
+
assert_equal "/users/1", @pendragon.path(:users, :user_id => 1)
|
174
|
+
assert_equal "/users/1?query=string", @pendragon.path(:users, :user_id => 1, :query => "string")
|
114
175
|
end
|
115
176
|
|
116
177
|
should "regexp" do
|
117
178
|
index = @pendragon.add(:get, /.+?/, :name => :index){}
|
118
179
|
foo_bar = @pendragon.add(:post, /\d+/, :name => :foo_bar){}
|
119
180
|
|
120
|
-
assert_equal @pendragon.path(:index)
|
121
|
-
assert_equal @pendragon.path(:foo_bar)
|
181
|
+
assert_equal /.+?/, @pendragon.path(:index)
|
182
|
+
assert_equal /\d+/, @pendragon.path(:foo_bar)
|
122
183
|
end
|
123
184
|
end
|
124
185
|
|
@@ -132,8 +193,17 @@ describe Pendragon do
|
|
132
193
|
assert_equal "foo", body
|
133
194
|
post("/")
|
134
195
|
assert_equal "bar", body
|
135
|
-
assert_equal @app.path(:foo)
|
136
|
-
assert_equal @app.path(:bar)
|
196
|
+
assert_equal "/", @app.path(:foo)
|
197
|
+
assert_equal "/", @app.path(:bar)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
describe "header" do
|
202
|
+
should "set Allow header when occur 405" do
|
203
|
+
@pendragon.get("/"){}
|
204
|
+
@pendragon.put("/"){}
|
205
|
+
post "/"
|
206
|
+
assert_equal "GET, PUT", response.header['Allow']
|
137
207
|
end
|
138
208
|
end
|
139
209
|
end
|
metadata
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pendragon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- namusyaka
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-04-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 1.3.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 1.3.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
@@ -42,56 +42,56 @@ dependencies:
|
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: 0.8.7
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 0.8.7
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rack-test
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: 0.5.0
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 0.5.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: mocha
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: 0.10.0
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 0.10.0
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: haml
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
@@ -114,7 +114,7 @@ executables: []
|
|
114
114
|
extensions: []
|
115
115
|
extra_rdoc_files: []
|
116
116
|
files:
|
117
|
-
- .travis.yml
|
117
|
+
- ".travis.yml"
|
118
118
|
- Gemfile
|
119
119
|
- Gemfile.lock
|
120
120
|
- README.md
|
@@ -137,6 +137,7 @@ files:
|
|
137
137
|
- test/compile_helper.rb
|
138
138
|
- test/helper.rb
|
139
139
|
- test/padrino_test.rb
|
140
|
+
- test/pendragon_configuration.rb
|
140
141
|
- test/pendragon_test.rb
|
141
142
|
homepage: https://github.com/namusyaka/pendragon
|
142
143
|
licenses:
|
@@ -148,17 +149,17 @@ require_paths:
|
|
148
149
|
- lib
|
149
150
|
required_ruby_version: !ruby/object:Gem::Requirement
|
150
151
|
requirements:
|
151
|
-
- -
|
152
|
+
- - ">="
|
152
153
|
- !ruby/object:Gem::Version
|
153
154
|
version: '0'
|
154
155
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
155
156
|
requirements:
|
156
|
-
- -
|
157
|
+
- - ">="
|
157
158
|
- !ruby/object:Gem::Version
|
158
159
|
version: '0'
|
159
160
|
requirements: []
|
160
161
|
rubyforge_project:
|
161
|
-
rubygems_version: 2.
|
162
|
+
rubygems_version: 2.2.2
|
162
163
|
signing_key:
|
163
164
|
specification_version: 4
|
164
165
|
summary: Provides an HTTP router for use in Rack and Padrino.
|