flame 3.4.0 → 3.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/flame/application.rb +18 -5
- data/lib/flame/controller.rb +8 -8
- data/lib/flame/cookies.rb +18 -0
- data/lib/flame/dispatcher.rb +57 -77
- data/lib/flame/errors.rb +4 -4
- data/lib/flame/render.rb +21 -11
- data/lib/flame/response.rb +11 -0
- data/lib/flame/route.rb +63 -15
- data/lib/flame/router.rb +38 -32
- data/lib/flame/static.rb +32 -0
- data/lib/flame/validators.rb +20 -6
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: edd8f37ca2180414b5428f5d5bbb5cf146daa356
|
4
|
+
data.tar.gz: 1f79bd46b74f82ac879c470dc2df4d59d2120adc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 907034532dbbd46fad3ecb8963579a4ec92f161b0aad1c798a663aea55b46e38efa1b6a4e549d6a1706b5cd42973fb130878ac7b56d96e491ff0e027ec742a87
|
7
|
+
data.tar.gz: 19b1337d223b707b2ed27b692d718746f895fc7d439ee3bf296742889dcc19525ffe49b1f5a46943b2cadeb6e5d285d82bb80ca7fb9cf703d46ec6a6e01d9340
|
data/lib/flame/application.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require_relative 'router'
|
2
|
-
require_relative 'request'
|
3
2
|
require_relative 'dispatcher'
|
4
3
|
|
5
4
|
module Flame
|
@@ -25,22 +24,32 @@ module Flame
|
|
25
24
|
)
|
26
25
|
end
|
27
26
|
|
28
|
-
def
|
29
|
-
@app
|
30
|
-
|
27
|
+
def initialize(app = nil)
|
28
|
+
@app = app
|
29
|
+
router.routes.map! do |route|
|
30
|
+
route[:hooks] = router.find_hooks(route)
|
31
|
+
route.freeze
|
32
|
+
end
|
33
|
+
router.freeze
|
31
34
|
end
|
32
35
|
|
33
36
|
## Init function
|
34
37
|
def call(env)
|
38
|
+
@app.call(env) if @app.respond_to? :call
|
35
39
|
Flame::Dispatcher.new(self, env).run!
|
36
40
|
end
|
37
41
|
|
42
|
+
def self.call(env)
|
43
|
+
@app ||= new
|
44
|
+
@app.call env
|
45
|
+
end
|
46
|
+
|
38
47
|
def self.mount(ctrl, path = nil, &block)
|
39
48
|
router.add_controller(ctrl, path, block)
|
40
49
|
end
|
41
50
|
|
42
51
|
def self.helpers(*modules)
|
43
|
-
modules.empty? ? (@helpers ||= []) :
|
52
|
+
modules.empty? ? (@helpers ||= []) : helpers.concat(modules).uniq!
|
44
53
|
end
|
45
54
|
|
46
55
|
## Router for routing
|
@@ -48,6 +57,10 @@ module Flame
|
|
48
57
|
@router ||= Flame::Router.new(self)
|
49
58
|
end
|
50
59
|
|
60
|
+
def router
|
61
|
+
self.class.router
|
62
|
+
end
|
63
|
+
|
51
64
|
def self.default_config_dirs(root_dir:)
|
52
65
|
{
|
53
66
|
root_dir: File.realpath(root_dir),
|
data/lib/flame/controller.rb
CHANGED
@@ -29,7 +29,7 @@ module Flame
|
|
29
29
|
)
|
30
30
|
template.render(cache: config[:environment] == 'production')
|
31
31
|
end
|
32
|
-
|
32
|
+
alias render view
|
33
33
|
|
34
34
|
## Helpers from Flame::Dispatcher
|
35
35
|
def method_missing(m, *args, &block)
|
@@ -37,14 +37,14 @@ module Flame
|
|
37
37
|
@dispatcher.send(m, *args, &block)
|
38
38
|
end
|
39
39
|
|
40
|
-
|
40
|
+
class << self
|
41
|
+
using GorillaPatch::StringExt
|
41
42
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
.unshift(nil)[(last ? -1 : 0)..-1].join('/')
|
43
|
+
def default_path(last = false)
|
44
|
+
(name.split('::').last.underscore.split('_') - %w(index controller ctrl))
|
45
|
+
.join('/').split('/')
|
46
|
+
.unshift(nil)[(last ? -1 : 0)..-1].join('/')
|
47
|
+
end
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Flame
|
2
|
+
## Helper class for cookies
|
3
|
+
class Cookies
|
4
|
+
def initialize(request_cookies, response)
|
5
|
+
@request_cookies = request_cookies
|
6
|
+
@response = response
|
7
|
+
end
|
8
|
+
|
9
|
+
def [](key)
|
10
|
+
@request_cookies[key.to_s]
|
11
|
+
end
|
12
|
+
|
13
|
+
def []=(key, new_value)
|
14
|
+
return @response.delete_cookie(key.to_s, path: '/') if new_value.nil?
|
15
|
+
@response.set_cookie(key.to_s, value: new_value, path: '/')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/flame/dispatcher.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
require 'gorilla-patch/hash'
|
2
2
|
|
3
|
+
require_relative 'cookies'
|
4
|
+
require_relative 'request'
|
5
|
+
require_relative 'response'
|
6
|
+
require_relative 'static'
|
7
|
+
|
3
8
|
module Flame
|
4
9
|
## Helpers for dispatch Flame::Application#call
|
5
10
|
class Dispatcher
|
@@ -7,26 +12,28 @@ module Flame
|
|
7
12
|
|
8
13
|
using GorillaPatch::HashExt
|
9
14
|
|
15
|
+
include Flame::Dispatcher::Static
|
16
|
+
|
10
17
|
def initialize(app, env)
|
11
18
|
@app = app
|
19
|
+
@env = env
|
12
20
|
@request = Flame::Request.new(env)
|
13
|
-
@response =
|
21
|
+
@response = Flame::Response.new
|
14
22
|
end
|
15
23
|
|
16
24
|
def run!
|
17
|
-
|
25
|
+
catch :halt do
|
18
26
|
try_route ||
|
19
|
-
|
20
|
-
|
21
|
-
|
27
|
+
try_static ||
|
28
|
+
try_static(File.join(__dir__, '..', '..', 'public')) ||
|
29
|
+
try_error(404)
|
22
30
|
end
|
23
|
-
# p body
|
24
|
-
response.write body
|
25
31
|
response.finish
|
26
32
|
end
|
27
33
|
|
28
34
|
def status(value = nil)
|
29
35
|
response.status ||= 200
|
36
|
+
response.headers['X-Cascade'] = 'pass' if value == 404
|
30
37
|
value ? response.status = value : response.status
|
31
38
|
end
|
32
39
|
|
@@ -53,26 +60,37 @@ module Flame
|
|
53
60
|
path.empty? ? '/' : path
|
54
61
|
end
|
55
62
|
|
56
|
-
def halt(new_status, body = nil, new_headers = {})
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
if body.nil? &&
|
61
|
-
!Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(status)
|
62
|
-
body = Rack::Utils::HTTP_STATUS_CODES[status]
|
63
|
+
def halt(new_status = nil, body = nil, new_headers = {})
|
64
|
+
case new_status
|
65
|
+
when String then body = new_status
|
66
|
+
when Integer then status new_status
|
63
67
|
end
|
64
|
-
|
68
|
+
# new_status.is_a?(String) ? () : (status new_status)
|
69
|
+
body = default_body if body.nil? && response.body.empty?
|
70
|
+
response.body = body if body
|
71
|
+
response.headers.merge!(new_headers)
|
72
|
+
throw :halt
|
65
73
|
end
|
66
74
|
|
67
75
|
private
|
68
76
|
|
77
|
+
## Generate default body of error page
|
78
|
+
def default_body
|
79
|
+
return if Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(status)
|
80
|
+
"<h1>#{Rack::Utils::HTTP_STATUS_CODES[status]}</h1>"
|
81
|
+
end
|
82
|
+
|
83
|
+
## Find nearest route
|
84
|
+
def nearest_route_for_request
|
85
|
+
@app.router.find_nearest_route(request.path_parts)
|
86
|
+
end
|
87
|
+
|
69
88
|
## Find route and try execute it
|
70
89
|
def try_route
|
71
90
|
route = @app.class.router.find_route(
|
72
91
|
method: request.http_method,
|
73
92
|
path_parts: request.path_parts
|
74
93
|
)
|
75
|
-
# p route
|
76
94
|
return nil unless route
|
77
95
|
status 200
|
78
96
|
params.merge!(route.arguments(request.path_parts))
|
@@ -81,67 +99,29 @@ module Flame
|
|
81
99
|
end
|
82
100
|
|
83
101
|
def execute_route(route)
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
return nil unless File.exist?(file) && File.file?(file)
|
108
|
-
return_static(file)
|
109
|
-
end
|
110
|
-
|
111
|
-
def static_cached?(file_time)
|
112
|
-
since = request.env['HTTP_IF_MODIFIED_SINCE']
|
113
|
-
since && Time.httpdate(since).to_i >= file_time.to_i
|
114
|
-
end
|
115
|
-
|
116
|
-
def return_static(file)
|
117
|
-
file_time = File.mtime(file)
|
118
|
-
halt 304 if static_cached?(file_time)
|
119
|
-
mime_type = Rack::Mime.mime_type(File.extname(file))
|
120
|
-
response.headers.merge!(
|
121
|
-
'Content-Type' => mime_type,
|
122
|
-
'Last-Modified' => file_time.httpdate
|
123
|
-
# 'Content-Disposition' => 'attachment;' \
|
124
|
-
# "filename=\"#{File.basename(static_file)}\"",
|
125
|
-
# 'Content-Length' => File.size?(static_file).to_s
|
126
|
-
)
|
127
|
-
halt 200, File.read(file)
|
128
|
-
end
|
129
|
-
|
130
|
-
## Helper class for cookies
|
131
|
-
class Cookies
|
132
|
-
def initialize(request_cookies, response)
|
133
|
-
@request_cookies = request_cookies
|
134
|
-
@response = response
|
135
|
-
end
|
136
|
-
|
137
|
-
def [](key)
|
138
|
-
@request_cookies[key.to_s]
|
139
|
-
end
|
140
|
-
|
141
|
-
def []=(key, new_value)
|
142
|
-
return @response.delete_cookie(key.to_s, path: '/') if new_value.nil?
|
143
|
-
@response.set_cookie(key.to_s, value: new_value, path: '/')
|
144
|
-
end
|
102
|
+
exec_route = route.executable
|
103
|
+
response.body = exec_route.run!(self)
|
104
|
+
rescue => exception
|
105
|
+
dump_error(exception)
|
106
|
+
# status 500
|
107
|
+
# exec_route.execute_errors(status)
|
108
|
+
try_error(500, exec_route)
|
109
|
+
end
|
110
|
+
|
111
|
+
def try_error(error_status = nil, exec_route = nil)
|
112
|
+
exec_route = nearest_route_for_request.executable unless exec_route
|
113
|
+
status error_status if error_status
|
114
|
+
exec_route.execute_errors(status)
|
115
|
+
halt
|
116
|
+
end
|
117
|
+
|
118
|
+
def dump_error(error)
|
119
|
+
msg = [
|
120
|
+
"#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} - " \
|
121
|
+
"#{error.class} - #{error.message}:",
|
122
|
+
*error.backtrace
|
123
|
+
].join("\n\t")
|
124
|
+
@env['rack.errors'].puts(msg)
|
145
125
|
end
|
146
126
|
end
|
147
127
|
end
|
data/lib/flame/errors.rb
CHANGED
@@ -79,14 +79,14 @@ module Flame
|
|
79
79
|
end
|
80
80
|
|
81
81
|
## Error for Flame::Router.find_path
|
82
|
-
class
|
83
|
-
def initialize(
|
84
|
-
@
|
82
|
+
class UnexpectedTypeOfHookError < StandardError
|
83
|
+
def initialize(hook, route)
|
84
|
+
@hook = hook
|
85
85
|
@route = route
|
86
86
|
end
|
87
87
|
|
88
88
|
def message
|
89
|
-
"Unexpected
|
89
|
+
"Unexpected hook-block class '#{@hook.class}'" \
|
90
90
|
" in route '#{@route}'"
|
91
91
|
end
|
92
92
|
end
|
data/lib/flame/render.rb
CHANGED
@@ -16,6 +16,7 @@ module Flame
|
|
16
16
|
@locals = options.merge(options.delete(:locals) || {})
|
17
17
|
## Find filename
|
18
18
|
@filename = find_file(path)
|
19
|
+
@ctrl.instance_exec { halt 404 } unless @filename
|
19
20
|
@layout = nil if File.basename(@filename)[0] == '_'
|
20
21
|
end
|
21
22
|
|
@@ -26,7 +27,15 @@ module Flame
|
|
26
27
|
layout_render tilt.render(@scope, @locals), cache: cache
|
27
28
|
end
|
28
29
|
|
29
|
-
|
30
|
+
private
|
31
|
+
|
32
|
+
class << self
|
33
|
+
private
|
34
|
+
|
35
|
+
def tilts
|
36
|
+
@tilts ||= {}
|
37
|
+
end
|
38
|
+
end
|
30
39
|
|
31
40
|
using GorillaPatch::StringExt
|
32
41
|
|
@@ -34,19 +43,20 @@ module Flame
|
|
34
43
|
Tilt.new(filename)
|
35
44
|
end
|
36
45
|
|
37
|
-
def self.tilts
|
38
|
-
@tilts ||= {}
|
39
|
-
end
|
40
|
-
|
41
46
|
## TODO: Add `views_dir` for Application and Controller
|
42
47
|
## TODO: Add `layout` method for Controller
|
43
48
|
def find_file(path)
|
44
49
|
## Get full filename
|
50
|
+
# p Dir[File.join(
|
51
|
+
# @ctrl.config[:views_dir],
|
52
|
+
# "{#{controller_dirs.join(',')},}",
|
53
|
+
# "#{path}.*"
|
54
|
+
# )].uniq
|
45
55
|
Dir[File.join(
|
46
56
|
@ctrl.config[:views_dir],
|
47
57
|
"{#{controller_dirs.join(',')},}",
|
48
58
|
"#{path}.*"
|
49
|
-
)].find do |file|
|
59
|
+
)].uniq.find do |file|
|
50
60
|
Tilt[file]
|
51
61
|
end
|
52
62
|
end
|
@@ -68,11 +78,11 @@ module Flame
|
|
68
78
|
## Compile layout to hash
|
69
79
|
return result unless layout_file
|
70
80
|
layout =
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
81
|
+
if cache
|
82
|
+
self.class.tilts[layout_file] ||= compile(layout_file)
|
83
|
+
else
|
84
|
+
compile(layout_file)
|
85
|
+
end
|
76
86
|
return result unless layout
|
77
87
|
layout.render(@scope, @locals) { result }
|
78
88
|
end
|
data/lib/flame/route.rb
CHANGED
@@ -9,13 +9,17 @@ module Flame
|
|
9
9
|
)
|
10
10
|
end
|
11
11
|
|
12
|
-
def [](
|
13
|
-
@attributes[
|
12
|
+
def [](key)
|
13
|
+
@attributes[key]
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
16
|
+
def []=(key, value)
|
17
|
+
@attributes[key] = value
|
18
|
+
end
|
19
|
+
|
20
|
+
## Create Executable object (route)
|
21
|
+
def executable
|
22
|
+
Executable.new(self)
|
19
23
|
end
|
20
24
|
|
21
25
|
## Compare attributes for `Router.find_route`
|
@@ -46,16 +50,6 @@ module Flame
|
|
46
50
|
end
|
47
51
|
end
|
48
52
|
|
49
|
-
## Arguments in order as parameters of method of controller
|
50
|
-
def arranged_params(params)
|
51
|
-
self[:controller].instance_method(self[:action]).parameters
|
52
|
-
.each_with_object([]) do |par, arr|
|
53
|
-
arr << params[par[1]] if par[0] == :req || params[par[1]]
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
53
|
## Helpers for `compare_attributes`
|
60
54
|
def compare_attribute(name, value)
|
61
55
|
case name
|
@@ -99,5 +93,59 @@ module Flame
|
|
99
93
|
## All is ok
|
100
94
|
param
|
101
95
|
end
|
96
|
+
|
97
|
+
## Class for Route execution
|
98
|
+
class Executable
|
99
|
+
def initialize(route)
|
100
|
+
@route = route
|
101
|
+
end
|
102
|
+
|
103
|
+
## Execute route from Dispatcher
|
104
|
+
def run!(dispatcher)
|
105
|
+
@ctrl = @route[:controller].new(dispatcher)
|
106
|
+
execute_hooks(:before)
|
107
|
+
result = @ctrl.send(@route[:action], *arranged_params)
|
108
|
+
execute_hooks(:after)
|
109
|
+
result
|
110
|
+
end
|
111
|
+
|
112
|
+
def execute_errors(status = 500)
|
113
|
+
execute_hooks(:error, status)
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
## Arguments in order as parameters of method of controller
|
119
|
+
def arranged_params
|
120
|
+
# action_parameters.each_with_object([]) do |par, arr|
|
121
|
+
# arr << @ctrl.params[par[1]] if par[0] == :req || @ctrl.params[par[1]]
|
122
|
+
# end
|
123
|
+
@ctrl.params.values_at(*action_parameters.map { |par| par[1] })
|
124
|
+
end
|
125
|
+
|
126
|
+
## Method parameters of route controller#action
|
127
|
+
def action_parameters
|
128
|
+
@route[:controller].instance_method(@route[:action]).parameters
|
129
|
+
end
|
130
|
+
|
131
|
+
## Execute before, after or error hook of Symbol, String or Proc
|
132
|
+
def execute_hook(hook)
|
133
|
+
case hook
|
134
|
+
when Symbol, String
|
135
|
+
@ctrl.send(hook.to_sym)
|
136
|
+
when Proc
|
137
|
+
@ctrl.instance_exec(&hook)
|
138
|
+
else
|
139
|
+
fail UnexpectedTypeOfHookError.new(hook, @route)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
## Execute before, after or error hooks
|
144
|
+
def execute_hooks(*keys)
|
145
|
+
hooks = @route[:hooks].dig(*keys)
|
146
|
+
# p hooks
|
147
|
+
hooks.each { |hook| execute_hook(hook) } if hooks
|
148
|
+
end
|
149
|
+
end
|
102
150
|
end
|
103
151
|
end
|
data/lib/flame/router.rb
CHANGED
@@ -4,12 +4,12 @@ require_relative 'validators'
|
|
4
4
|
module Flame
|
5
5
|
## Router class for routing
|
6
6
|
class Router
|
7
|
-
attr_reader :app, :routes, :
|
7
|
+
attr_reader :app, :routes, :hooks
|
8
8
|
|
9
9
|
def initialize(app)
|
10
10
|
@app = app
|
11
11
|
@routes = []
|
12
|
-
@
|
12
|
+
@hooks = {}
|
13
13
|
end
|
14
14
|
|
15
15
|
def add_controller(ctrl, path, block = nil)
|
@@ -22,39 +22,48 @@ module Flame
|
|
22
22
|
end
|
23
23
|
|
24
24
|
## Find route by any attributes
|
25
|
-
def find_route(attrs
|
25
|
+
def find_route(attrs)
|
26
26
|
route = routes.find { |r| r.compare_attributes(attrs) }
|
27
|
-
|
28
|
-
route.merge(
|
29
|
-
befores: find_befores(route),
|
30
|
-
afters: find_afters(route)
|
31
|
-
)
|
27
|
+
route.dup if route
|
32
28
|
end
|
33
29
|
|
34
|
-
## Find
|
35
|
-
def
|
36
|
-
|
37
|
-
|
30
|
+
## Find the nearest route by path parts
|
31
|
+
def find_nearest_route(path_parts)
|
32
|
+
while path_parts.size >= 0
|
33
|
+
route = find_route(path_parts: path_parts)
|
34
|
+
break if route || path_parts.empty?
|
35
|
+
path_parts.pop
|
36
|
+
end
|
37
|
+
route
|
38
38
|
end
|
39
39
|
|
40
|
-
## Find
|
41
|
-
def
|
42
|
-
|
43
|
-
|
40
|
+
## Find hooks by Route
|
41
|
+
def find_hooks(route)
|
42
|
+
result = {}
|
43
|
+
hooks[route[:controller]].each do |type, hash|
|
44
|
+
if type == :error
|
45
|
+
result[type] = hash
|
46
|
+
else
|
47
|
+
result[type] = (hash[route[:action]] || []) | (hash[:*] || [])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
# p result
|
51
|
+
result
|
44
52
|
end
|
45
53
|
|
46
54
|
private
|
47
55
|
|
48
56
|
def concat_routes(route_refine)
|
49
57
|
routes.concat(route_refine.routes)
|
50
|
-
|
51
|
-
afters[route_refine.ctrl] = route_refine.afters
|
58
|
+
hooks[route_refine.ctrl] = route_refine.hooks
|
52
59
|
end
|
53
60
|
|
54
61
|
## Helper module for routing refine
|
55
62
|
class RouteRefine
|
56
63
|
attr_accessor :rest_routes
|
57
|
-
attr_reader :ctrl, :routes, :
|
64
|
+
attr_reader :ctrl, :routes, :hooks
|
65
|
+
|
66
|
+
HOOK_TYPES = [:before, :after, :error].freeze
|
58
67
|
|
59
68
|
def self.http_methods
|
60
69
|
[:GET, :POST, :PUT, :DELETE]
|
@@ -75,7 +84,7 @@ module Flame
|
|
75
84
|
@ctrl = ctrl
|
76
85
|
@path = path || @ctrl.default_path
|
77
86
|
@routes = []
|
78
|
-
@
|
87
|
+
@hooks = HOOK_TYPES.each_with_object({}) { |type, hash| hash[type] = {} }
|
79
88
|
execute(&block)
|
80
89
|
end
|
81
90
|
|
@@ -90,14 +99,12 @@ module Flame
|
|
90
99
|
end
|
91
100
|
end
|
92
101
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
actions = [actions] unless actions.is_a?(Array)
|
100
|
-
actions.each { |a| (@afters[a] ||= []).push(action || block) }
|
102
|
+
HOOK_TYPES.each do |type|
|
103
|
+
default_actions = (type == :error ? 500 : :*)
|
104
|
+
define_method(type) do |actions = default_actions, action = nil, &block|
|
105
|
+
actions = [actions] unless actions.is_a?(Array)
|
106
|
+
actions.each { |a| (@hooks[type][a] ||= []).push(action || block) }
|
107
|
+
end
|
101
108
|
end
|
102
109
|
|
103
110
|
def defaults
|
@@ -141,10 +148,9 @@ module Flame
|
|
141
148
|
## TODO: Add :arg:type support (:id:num, :name:str, etc.)
|
142
149
|
unshifted = force_params ? path : action_path(action)
|
143
150
|
if path.nil? || force_params
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
.join('/')
|
151
|
+
parameters = @ctrl.instance_method(action).parameters
|
152
|
+
parameters.map! { |par| ":#{par[0] == :req ? '' : '?'}#{par[1]}" }
|
153
|
+
path = parameters.unshift(unshifted).join('/')
|
148
154
|
end
|
149
155
|
path_merge(@path, path)
|
150
156
|
end
|
data/lib/flame/static.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module Flame
|
2
|
+
class Dispatcher
|
3
|
+
## Module for working with static files
|
4
|
+
module Static
|
5
|
+
## Find static files and try return it
|
6
|
+
def try_static(dir = config[:public_dir])
|
7
|
+
file = File.join(dir, request.path_info)
|
8
|
+
return nil unless File.exist?(file) && File.file?(file)
|
9
|
+
return_static(file)
|
10
|
+
end
|
11
|
+
|
12
|
+
def static_cached?(file_time)
|
13
|
+
since = request.env['HTTP_IF_MODIFIED_SINCE']
|
14
|
+
since && Time.httpdate(since).to_i >= file_time.to_i
|
15
|
+
end
|
16
|
+
|
17
|
+
def return_static(file)
|
18
|
+
file_time = File.mtime(file)
|
19
|
+
halt 304 if static_cached?(file_time)
|
20
|
+
mime_type = Rack::Mime.mime_type(File.extname(file))
|
21
|
+
response.headers.merge!(
|
22
|
+
'Content-Type' => mime_type,
|
23
|
+
'Last-Modified' => file_time.httpdate
|
24
|
+
# 'Content-Disposition' => 'attachment;' \
|
25
|
+
# "filename=\"#{File.basename(static_file)}\"",
|
26
|
+
# 'Content-Length' => File.size?(static_file).to_s
|
27
|
+
)
|
28
|
+
halt 200, File.read(file)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/flame/validators.rb
CHANGED
@@ -58,28 +58,42 @@ module Flame
|
|
58
58
|
## Compare actions from routes and from controller
|
59
59
|
class ActionsValidator
|
60
60
|
def initialize(route_refine)
|
61
|
-
@
|
61
|
+
@routes_actions = route_refine.routes.map { |route| route[:action] }
|
62
|
+
@hooks_actions = route_refine.hooks.values.map(&:values).flatten
|
63
|
+
@hooks_actions.select! { |action| action.is_a? Symbol }
|
62
64
|
@ctrl = route_refine.ctrl
|
65
|
+
@ctrl_actions = {
|
66
|
+
public: @ctrl.public_instance_methods(false),
|
67
|
+
all: @ctrl.instance_methods + @ctrl.private_instance_methods
|
68
|
+
}
|
63
69
|
end
|
64
70
|
|
65
71
|
def valid?
|
66
|
-
|
67
|
-
|
68
|
-
|
72
|
+
no_extra_routes_actions? &&
|
73
|
+
no_extra_hooks_actions? &&
|
74
|
+
no_extra_controller_actions?
|
69
75
|
end
|
70
76
|
|
71
77
|
private
|
72
78
|
|
73
79
|
def no_extra_routes_actions?
|
74
|
-
extra_routes_actions = @routes_actions - @ctrl_actions
|
80
|
+
extra_routes_actions = @routes_actions - @ctrl_actions[:public]
|
75
81
|
return true if extra_routes_actions.empty?
|
76
82
|
fail RouterError::ExtraRoutesActionsError.new(
|
77
83
|
@ctrl, extra_routes_actions
|
78
84
|
)
|
79
85
|
end
|
80
86
|
|
87
|
+
def no_extra_hooks_actions?
|
88
|
+
extra_hooks_actions = @hooks_actions - @ctrl_actions[:all]
|
89
|
+
return true if extra_hooks_actions.empty?
|
90
|
+
fail RouterError::ExtraRoutesActionsError.new(
|
91
|
+
@ctrl, extra_hooks_actions
|
92
|
+
)
|
93
|
+
end
|
94
|
+
|
81
95
|
def no_extra_controller_actions?
|
82
|
-
extra_ctrl_actions = @ctrl_actions - @routes_actions
|
96
|
+
extra_ctrl_actions = @ctrl_actions[:public] - @routes_actions
|
83
97
|
return true if extra_ctrl_actions.empty?
|
84
98
|
fail RouterError::ExtraControllerActionsError.new(
|
85
99
|
@ctrl, extra_ctrl_actions
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flame
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexander Popov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-01-
|
11
|
+
date: 2016-01-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -75,12 +75,15 @@ files:
|
|
75
75
|
- lib/flame.rb
|
76
76
|
- lib/flame/application.rb
|
77
77
|
- lib/flame/controller.rb
|
78
|
+
- lib/flame/cookies.rb
|
78
79
|
- lib/flame/dispatcher.rb
|
79
80
|
- lib/flame/errors.rb
|
80
81
|
- lib/flame/render.rb
|
81
82
|
- lib/flame/request.rb
|
83
|
+
- lib/flame/response.rb
|
82
84
|
- lib/flame/route.rb
|
83
85
|
- lib/flame/router.rb
|
86
|
+
- lib/flame/static.rb
|
84
87
|
- lib/flame/validators.rb
|
85
88
|
- public/favicon.ico
|
86
89
|
homepage: https://gitlab.com/AlexWayfer/flame
|