padrino-core 0.11.4 → 0.12.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/padrino-core/application/authenticity_token.rb +25 -0
- data/lib/padrino-core/application/rendering/extensions/erubis.rb +11 -7
- data/lib/padrino-core/application/rendering/extensions/haml.rb +3 -2
- data/lib/padrino-core/application/rendering/extensions/slim.rb +10 -3
- data/lib/padrino-core/application/rendering.rb +13 -5
- data/lib/padrino-core/application/routing.rb +62 -19
- data/lib/padrino-core/application.rb +136 -50
- data/lib/padrino-core/cli/base.rb +32 -1
- data/lib/padrino-core/loader.rb +68 -68
- data/lib/padrino-core/logger.rb +6 -6
- data/lib/padrino-core/mounter.rb +9 -4
- data/lib/padrino-core/reloader/rack.rb +26 -0
- data/lib/padrino-core/reloader/storage.rb +55 -0
- data/lib/padrino-core/reloader.rb +192 -287
- data/lib/padrino-core/router.rb +11 -12
- data/lib/padrino-core/server.rb +5 -0
- data/lib/padrino-core/support_lite.rb +31 -32
- data/lib/padrino-core/version.rb +1 -1
- data/lib/padrino-core.rb +22 -30
- data/padrino-core.gemspec +2 -1
- data/test/fixtures/apps/helpers/system_helpers.rb +8 -0
- data/test/fixtures/apps/kiq.rb +3 -0
- data/test/fixtures/apps/lib/myklass/mysubklass.rb +4 -0
- data/test/fixtures/apps/lib/myklass.rb +2 -0
- data/test/fixtures/apps/models/child.rb +2 -0
- data/test/fixtures/apps/models/parent.rb +5 -0
- data/test/fixtures/apps/render.rb +13 -0
- data/test/fixtures/apps/system.rb +13 -0
- data/test/fixtures/apps/views/blog/post.erb +1 -0
- data/test/helper.rb +1 -1
- data/test/mini_shoulda.rb +4 -4
- data/test/test_application.rb +5 -13
- data/test/test_core.rb +2 -6
- data/test/test_csrf_protection.rb +67 -1
- data/test/test_dependencies.rb +14 -1
- data/test/test_mounter.rb +50 -6
- data/test/test_reloader_complex.rb +2 -2
- data/test/test_reloader_simple.rb +1 -1
- data/test/test_reloader_system.rb +52 -0
- data/test/test_rendering.rb +54 -0
- data/test/test_router.rb +121 -2
- data/test/test_routing.rb +84 -15
- metadata +29 -11
data/lib/padrino-core/loader.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Padrino
|
2
|
-
|
2
|
+
module Loader
|
3
3
|
##
|
4
4
|
# Hooks to be called before a load/reload.
|
5
5
|
#
|
@@ -40,17 +40,6 @@ module Padrino
|
|
40
40
|
@_after_load
|
41
41
|
end
|
42
42
|
|
43
|
-
##
|
44
|
-
# The used +$LOAD_PATHS+ from Padrino.
|
45
|
-
#
|
46
|
-
# @return [Array<String>]
|
47
|
-
# The load paths used by Padrino.
|
48
|
-
#
|
49
|
-
def load_paths
|
50
|
-
@_load_paths_was = %w(lib models shared).map { |path| Padrino.root(path) }
|
51
|
-
@_load_paths ||= @_load_paths_was
|
52
|
-
end
|
53
|
-
|
54
43
|
##
|
55
44
|
# Requires necessary dependencies as well as application files from root
|
56
45
|
# lib and models.
|
@@ -60,21 +49,18 @@ module Padrino
|
|
60
49
|
#
|
61
50
|
def load!
|
62
51
|
return false if loaded?
|
63
|
-
|
64
|
-
|
52
|
+
began_at = Time.now
|
65
53
|
@_called_from = first_caller
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
Padrino
|
54
|
+
set_encoding
|
55
|
+
set_load_paths(*load_paths)
|
56
|
+
Logger.setup!
|
57
|
+
require_dependencies("#{root}/config/database.rb")
|
58
|
+
Reloader.lock!
|
59
|
+
before_load.each(&:call)
|
60
|
+
require_dependencies(*dependency_paths)
|
61
|
+
after_load.each(&:call)
|
62
|
+
logger.devel "Loaded Padrino in #{Time.now - began_at} seconds"
|
75
63
|
Thread.current[:padrino_loaded] = true
|
76
|
-
|
77
|
-
Padrino.logger.devel "Loaded Padrino in #{Time.now - t} seconds"
|
78
64
|
end
|
79
65
|
|
80
66
|
##
|
@@ -83,14 +69,14 @@ module Padrino
|
|
83
69
|
# @return [NilClass]
|
84
70
|
#
|
85
71
|
def clear!
|
86
|
-
|
87
|
-
|
72
|
+
clear_middleware!
|
73
|
+
mounted_apps.clear
|
88
74
|
@_load_paths = nil
|
89
75
|
@_dependency_paths = nil
|
90
76
|
@_global_configuration = nil
|
91
|
-
|
92
|
-
|
93
|
-
|
77
|
+
before_load.clear
|
78
|
+
after_load.clear
|
79
|
+
Reloader.clear!
|
94
80
|
Thread.current[:padrino_loaded] = nil
|
95
81
|
end
|
96
82
|
|
@@ -98,10 +84,10 @@ module Padrino
|
|
98
84
|
# Method for reloading required applications and their files.
|
99
85
|
#
|
100
86
|
def reload!
|
101
|
-
return unless
|
102
|
-
|
103
|
-
|
104
|
-
|
87
|
+
return unless Reloader.changed?
|
88
|
+
before_load.each(&:call)
|
89
|
+
Reloader.reload!
|
90
|
+
after_load.each(&:call)
|
105
91
|
end
|
106
92
|
|
107
93
|
##
|
@@ -147,38 +133,55 @@ module Padrino
|
|
147
133
|
# require_dependencies("#{Padrino.root}/lib/**/*.rb")
|
148
134
|
#
|
149
135
|
def require_dependencies(*paths)
|
150
|
-
options = paths.extract_options
|
151
|
-
|
152
|
-
# Extract all files to load
|
153
|
-
files = paths.flatten.map { |path| Dir[path] }.flatten.uniq.sort
|
136
|
+
options = paths.extract_options!.merge( :cyclic => true )
|
137
|
+
files = paths.flatten.map{|path| Dir[path].sort_by{|v| v.count('/') }}.flatten.uniq
|
154
138
|
|
155
139
|
while files.present?
|
156
|
-
|
140
|
+
error, fatal, loaded = nil, nil, nil
|
157
141
|
|
158
|
-
size_at_start = files.size
|
159
|
-
|
160
|
-
# Now we try to require our dependencies, we dup files
|
161
|
-
# so we don't perform delete on the original array during
|
162
|
-
# iteration, this prevent problems with Rubinus
|
163
142
|
files.dup.each do |file|
|
164
143
|
begin
|
165
|
-
|
144
|
+
Reloader.safe_load(file, options)
|
166
145
|
files.delete(file)
|
146
|
+
loaded = true
|
167
147
|
rescue NameError, LoadError => e
|
168
|
-
|
169
|
-
|
170
|
-
failed << file
|
148
|
+
logger.devel "Cyclic dependency reload for #{e.class}: #{e.message}"
|
149
|
+
error = e
|
171
150
|
rescue Exception => e
|
172
|
-
|
151
|
+
fatal = e
|
152
|
+
break
|
173
153
|
end
|
174
154
|
end
|
175
155
|
|
176
|
-
|
177
|
-
|
178
|
-
|
156
|
+
if fatal || !loaded
|
157
|
+
e = fatal || error
|
158
|
+
logger.error "#{e.class}: #{e.message}; #{e.backtrace.first}"
|
159
|
+
raise e
|
160
|
+
end
|
179
161
|
end
|
180
162
|
end
|
181
163
|
|
164
|
+
##
|
165
|
+
# Concat to +$LOAD_PATH+ the given paths.
|
166
|
+
#
|
167
|
+
# @param [Array<String>] paths
|
168
|
+
# The paths to concat.
|
169
|
+
#
|
170
|
+
def set_load_paths(*paths)
|
171
|
+
load_paths.concat(paths).uniq!
|
172
|
+
$LOAD_PATH.concat(paths).uniq!
|
173
|
+
end
|
174
|
+
|
175
|
+
##
|
176
|
+
# The used +$LOAD_PATHS+ from Padrino.
|
177
|
+
#
|
178
|
+
# @return [Array<String>]
|
179
|
+
# The load paths used by Padrino.
|
180
|
+
#
|
181
|
+
def load_paths
|
182
|
+
@_load_paths ||= load_paths_was.dup
|
183
|
+
end
|
184
|
+
|
182
185
|
##
|
183
186
|
# Returns default list of path globs to load as dependencies.
|
184
187
|
# Appends custom dependency patterns to the be loaded for Padrino.
|
@@ -190,35 +193,32 @@ module Padrino
|
|
190
193
|
# Padrino.dependency_paths << "#{Padrino.root}/uploaders/*.rb"
|
191
194
|
#
|
192
195
|
def dependency_paths
|
193
|
-
@_dependency_paths ||=
|
194
|
-
end
|
195
|
-
|
196
|
-
##
|
197
|
-
# Concat to +$LOAD_PATH+ the given paths.
|
198
|
-
#
|
199
|
-
# @param [Array<String>] paths
|
200
|
-
# The paths to concat.
|
201
|
-
#
|
202
|
-
def set_load_paths(*paths)
|
203
|
-
$:.concat(paths); load_paths.concat(paths)
|
204
|
-
$:.uniq!; load_paths.uniq!
|
196
|
+
@_dependency_paths ||= dependency_paths_was + module_paths
|
205
197
|
end
|
206
198
|
|
207
199
|
private
|
208
200
|
|
209
201
|
def module_paths
|
210
|
-
|
202
|
+
modules.map(&:dependency_paths).flatten
|
203
|
+
end
|
204
|
+
|
205
|
+
def load_paths_was
|
206
|
+
@_load_paths_was ||= [
|
207
|
+
"#{root}/lib",
|
208
|
+
"#{root}/models",
|
209
|
+
"#{root}/shared",
|
210
|
+
].freeze
|
211
211
|
end
|
212
212
|
|
213
213
|
def dependency_paths_was
|
214
|
-
[
|
214
|
+
@_dependency_paths_was ||= [
|
215
215
|
"#{root}/config/database.rb",
|
216
216
|
"#{root}/lib/**/*.rb",
|
217
|
-
"#{root}/shared/lib/**/*.rb",
|
218
217
|
"#{root}/models/**/*.rb",
|
218
|
+
"#{root}/shared/lib/**/*.rb",
|
219
219
|
"#{root}/shared/models/**/*.rb",
|
220
220
|
"#{root}/config/apps.rb"
|
221
|
-
]
|
221
|
+
].freeze
|
222
222
|
end
|
223
223
|
end
|
224
224
|
end
|
data/lib/padrino-core/logger.rb
CHANGED
@@ -52,10 +52,10 @@ module Padrino
|
|
52
52
|
# :devel:: Development-related information that is unnecessary in debug mode
|
53
53
|
#
|
54
54
|
Levels = {
|
55
|
-
:fatal =>
|
56
|
-
:error =>
|
57
|
-
:warn =>
|
58
|
-
:info =>
|
55
|
+
:fatal => 4,
|
56
|
+
:error => 3,
|
57
|
+
:warn => 2,
|
58
|
+
:info => 1,
|
59
59
|
:debug => 0,
|
60
60
|
:devel => -1,
|
61
61
|
} unless defined?(Levels)
|
@@ -194,13 +194,13 @@ module Padrino
|
|
194
194
|
#
|
195
195
|
def colorize(string, *colors)
|
196
196
|
colors.each do |c|
|
197
|
-
string = string.
|
197
|
+
string = string.colorize(c)
|
198
198
|
end
|
199
199
|
string
|
200
200
|
end
|
201
201
|
|
202
202
|
def stylized_level(level)
|
203
|
-
style = ColoredLevels[level].map { |c| "\e[%dm" % String.colors[c] } * ''
|
203
|
+
style = ColoredLevels[level].map { |c| "\e[%dm" % String::Colorizer.colors[c] } * ''
|
204
204
|
[style, super, "\e[0m"] * ''
|
205
205
|
end
|
206
206
|
end
|
data/lib/padrino-core/mounter.rb
CHANGED
@@ -8,10 +8,11 @@ module Padrino
|
|
8
8
|
# Mounter.new("blog_app", :app_file => "/path/to/blog/app.rb").to("/blog")
|
9
9
|
#
|
10
10
|
class Mounter
|
11
|
+
DEFAULT_CASCADE = [404, 405]
|
11
12
|
class MounterException < RuntimeError
|
12
13
|
end
|
13
14
|
|
14
|
-
attr_accessor :name, :uri_root, :app_file, :app_class, :app_root, :app_obj, :app_host
|
15
|
+
attr_accessor :name, :uri_root, :app_file, :app_class, :app_root, :app_obj, :app_host, :cascade
|
15
16
|
|
16
17
|
##
|
17
18
|
# @param [String, Padrino::Application] name
|
@@ -31,8 +32,9 @@ module Padrino
|
|
31
32
|
@app_file = options[:app_file] || locate_app_file
|
32
33
|
@app_obj = options[:app_obj] || app_constant || locate_app_object
|
33
34
|
ensure_app_file! || ensure_app_object!
|
34
|
-
@app_root = options[:app_root] || File.dirname(@app_file)
|
35
|
+
@app_root = options[:app_root] || (@app_obj.respond_to?(:root) && @app_obj.root || File.dirname(@app_file))
|
35
36
|
@uri_root = "/"
|
37
|
+
@cascade = options[:cascade] ? true == options[:cascade] ? DEFAULT_CASCADE.dup : Array(options[:cascade]) : []
|
36
38
|
Padrino::Reloader.exclude_constants << @app_class
|
37
39
|
end
|
38
40
|
|
@@ -82,11 +84,12 @@ module Padrino
|
|
82
84
|
def map_onto(router)
|
83
85
|
app_data, app_obj = self, @app_obj
|
84
86
|
app_obj.set :uri_root, app_data.uri_root
|
85
|
-
app_obj.set :app_name, app_data.
|
87
|
+
app_obj.set :app_name, app_data.app_obj.app_name.to_s
|
86
88
|
app_obj.set :app_file, app_data.app_file unless ::File.exist?(app_obj.app_file)
|
87
89
|
app_obj.set :root, app_data.app_root unless app_data.app_root.blank?
|
88
90
|
app_obj.set :public_folder, Padrino.root('public', app_data.uri_root) unless File.exists?(app_obj.public_folder)
|
89
91
|
app_obj.set :static, File.exist?(app_obj.public_folder) if app_obj.nil?
|
92
|
+
app_obj.set :cascade, app_data.cascade
|
90
93
|
app_obj.setup_application! # Initializes the app here with above settings.
|
91
94
|
router.map(:to => app_obj, :path => app_data.uri_root, :host => app_data.app_host)
|
92
95
|
end
|
@@ -106,7 +109,9 @@ module Padrino
|
|
106
109
|
#
|
107
110
|
def named_routes
|
108
111
|
app_obj.routes.map { |route|
|
109
|
-
|
112
|
+
route_name = route.name.to_s
|
113
|
+
route_name.sub!(/^#{route.controller} /, "") if route.controller
|
114
|
+
name_array = "(#{route.controller ? %Q[:#{route.controller}] + ", " : ""}:#{route_name})"
|
110
115
|
request_method = route.request_methods.first
|
111
116
|
next if route.name.blank? || request_method == 'HEAD'
|
112
117
|
original_path = route.original_path.is_a?(Regexp) ? route.original_path.inspect : route.original_path
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Padrino
|
2
|
+
module Reloader
|
3
|
+
##
|
4
|
+
# This class acts as a Rack middleware to be added to the application stack.
|
5
|
+
# This middleware performs a check and reload for source files at the start
|
6
|
+
# of each request, but also respects a specified cool down time
|
7
|
+
# during which no further action will be taken.
|
8
|
+
#
|
9
|
+
class Rack
|
10
|
+
def initialize(app, cooldown=1)
|
11
|
+
@app = app
|
12
|
+
@cooldown = cooldown
|
13
|
+
@last = (Time.now - cooldown)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Invoked in order to perform the reload as part of the request stack.
|
17
|
+
def call(env)
|
18
|
+
if @cooldown && Time.now > @last + @cooldown
|
19
|
+
Thread.list.size > 1 ? Thread.exclusive { Padrino.reload! } : Padrino.reload!
|
20
|
+
@last = Time.now
|
21
|
+
end
|
22
|
+
@app.call(env)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Padrino
|
2
|
+
module Reloader
|
3
|
+
module Storage
|
4
|
+
extend self
|
5
|
+
|
6
|
+
def clear!
|
7
|
+
files.each_key do |file|
|
8
|
+
remove(file)
|
9
|
+
$LOADED_FEATURES.delete(file)
|
10
|
+
end
|
11
|
+
@files = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def remove(name)
|
15
|
+
file = files[name] || return
|
16
|
+
file[:constants].each{ |constant| Reloader.remove_constant(constant) }
|
17
|
+
file[:features].each{ |feature| $LOADED_FEATURES.delete(feature) }
|
18
|
+
files.delete(name)
|
19
|
+
end
|
20
|
+
|
21
|
+
def prepare(name)
|
22
|
+
file = remove(name)
|
23
|
+
@old_entries ||= {}
|
24
|
+
@old_entries[name] = {
|
25
|
+
:constants => ObjectSpace.classes,
|
26
|
+
:features => old_features = Set.new($LOADED_FEATURES.dup)
|
27
|
+
}
|
28
|
+
features = file && file[:features] || []
|
29
|
+
features.each{ |feature| Reloader.safe_load(feature, :force => true) }
|
30
|
+
$LOADED_FEATURES.delete(name) if old_features.include?(name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def commit(name)
|
34
|
+
entry = {
|
35
|
+
:constants => ObjectSpace.new_classes(@old_entries[name][:constants]),
|
36
|
+
:features => Set.new($LOADED_FEATURES) - @old_entries[name][:features] - [name]
|
37
|
+
}
|
38
|
+
files[name] = entry
|
39
|
+
@old_entries.delete(name)
|
40
|
+
end
|
41
|
+
|
42
|
+
def rollback(name)
|
43
|
+
new_constants = ObjectSpace.new_classes(@old_entries[name][:constants])
|
44
|
+
new_constants.each{ |klass| Reloader.remove_constant(klass) }
|
45
|
+
@old_entries.delete(name)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def files
|
51
|
+
@files ||= {}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|