padrino-core 0.8.5 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +1 -16
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/lib/padrino-core.rb +1 -1
- data/lib/padrino-core/application.rb +40 -374
- data/lib/padrino-core/{mounter.rb → application/mounter.rb} +1 -2
- data/lib/padrino-core/application/rendering.rb +48 -0
- data/lib/padrino-core/application/routing.rb +313 -0
- data/lib/padrino-core/caller.rb +2 -0
- data/lib/padrino-core/reloader.rb +11 -3
- data/lib/padrino-core/support_lite.rb +11 -13
- data/padrino-core.gemspec +11 -9
- data/test/fixtures/apps/complex.rb +1 -1
- data/test/fixtures/apps/simple.rb +1 -1
- data/test/test_application.rb +0 -21
- data/test/test_routing.rb +70 -2
- metadata +7 -5
data/README.rdoc
CHANGED
@@ -55,7 +55,7 @@ Please help me brainstorm and fork the project if you have any ideas to contribu
|
|
55
55
|
|
56
56
|
To install the padrino framework, simply grab the latest version from gemcutter:
|
57
57
|
|
58
|
-
$ sudo gem install padrino
|
58
|
+
$ sudo gem install padrino
|
59
59
|
|
60
60
|
This will install the necessary padrino gems to get you started.
|
61
61
|
Now you are ready to use this gem to enhance your sinatra projects or to create new Padrino applications.
|
@@ -301,21 +301,6 @@ within your application:
|
|
301
301
|
This will instruct Padrino to autoload these files (and reload them when changes are detected). By default, the load path
|
302
302
|
contains certain paths known to contain important files such as controllers, mailers, models, urls, and helpers.
|
303
303
|
|
304
|
-
=== Initializers
|
305
|
-
|
306
|
-
Padrino also has support for 'initializers' which are important setup steps or configuration within an application
|
307
|
-
that should occur during the bootup process. To construct initializers, simply add a file to the <tt>config/initializers<tt>
|
308
|
-
directory following this convention:
|
309
|
-
|
310
|
-
# config/initializers/example.rb
|
311
|
-
module ExampleInitializer
|
312
|
-
def self.registered(app)
|
313
|
-
# Manipulate 'app' here to register components or adjust configuration
|
314
|
-
app.set :environment, :production # just an example configuration change
|
315
|
-
app.use Hassle # or even enable middleware
|
316
|
-
end
|
317
|
-
end
|
318
|
-
|
319
304
|
Initializers are automatically required and 'registered' during the application startup process. Note that
|
320
305
|
the name of the module must be the name of the file appended with 'Initializer' (i.e sample.rb => SampleInitializer)
|
321
306
|
|
data/Rakefile
CHANGED
@@ -17,8 +17,8 @@ begin
|
|
17
17
|
gem.add_runtime_dependency "i18n", ">= 0.3.2"
|
18
18
|
gem.add_runtime_dependency "usher", ">= 0.6.2"
|
19
19
|
gem.add_runtime_dependency "thor", ">= 0.13.0"
|
20
|
-
gem.add_runtime_dependency "bundler", "= 0.9.
|
21
|
-
gem.add_runtime_dependency "activesupport", "
|
20
|
+
gem.add_runtime_dependency "bundler", "= 0.9.7"
|
21
|
+
gem.add_runtime_dependency "activesupport", "= 2.3.5"
|
22
22
|
gem.add_development_dependency "shoulda", ">= 2.10.3"
|
23
23
|
gem.add_development_dependency "mocha", ">= 0.9.7"
|
24
24
|
gem.add_development_dependency "rack-test", ">= 0.5.0"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.9.0
|
data/lib/padrino-core.rb
CHANGED
@@ -1,20 +1,24 @@
|
|
1
1
|
module Padrino
|
2
2
|
class ApplicationSetupError < RuntimeError #:nodoc:
|
3
3
|
end
|
4
|
+
|
4
5
|
##
|
5
6
|
# Subclasses of this become independent Padrino applications (stemming from Sinatra::Application)
|
6
7
|
# These subclassed applications can be easily mounted into other Padrino applications as well.
|
7
|
-
#
|
8
|
+
#
|
8
9
|
class Application < Sinatra::Application
|
10
|
+
register Padrino::Routing # Support for advanced routing, controllers, url_for
|
11
|
+
register Padrino::Rendering # Support for enhanced rendering with template detection
|
9
12
|
|
10
13
|
class << self
|
14
|
+
|
11
15
|
def inherited(subclass) #:nodoc:
|
12
16
|
CALLERS_TO_IGNORE.concat(PADRINO_IGNORE_CALLERS)
|
13
17
|
subclass.default_configuration!
|
14
18
|
Padrino.set_load_paths File.join(subclass.root, "/models")
|
15
19
|
Padrino.require_dependencies File.join(subclass.root, "/models.rb")
|
16
20
|
Padrino.require_dependencies File.join(subclass.root, "/models/**/*.rb")
|
17
|
-
super(subclass) # Loading the subclass
|
21
|
+
super(subclass) # Loading the subclass inherited method
|
18
22
|
subclass.default_filters!
|
19
23
|
subclass.default_routes!
|
20
24
|
subclass.default_errors!
|
@@ -25,95 +29,21 @@ module Padrino
|
|
25
29
|
# This is used because putting the configuration into inherited doesn't
|
26
30
|
# take into account overwritten app settings inside subclassed definitions
|
27
31
|
# Only performs the setup first time application is initialized.
|
28
|
-
#
|
32
|
+
#
|
29
33
|
def new(*args, &bk)
|
30
34
|
setup_application!
|
31
35
|
super(*args, &bk)
|
32
36
|
end
|
33
37
|
|
34
38
|
##
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
# url(:admin_index) # => "/admin"
|
45
|
-
# url(:admin_show, :id => 1) # "/admin/show/1"
|
46
|
-
#
|
47
|
-
# You can instead using named routes follow the sinatra way like:
|
48
|
-
#
|
49
|
-
# controller "/admin" do
|
50
|
-
# get "/index" do; ...; end
|
51
|
-
# get "/show/:id" do; ...; end
|
52
|
-
# end
|
53
|
-
#
|
54
|
-
# And you can call directly these urls:
|
55
|
-
#
|
56
|
-
# # => "/admin"
|
57
|
-
# # => "/admin/show/1"
|
58
|
-
#
|
59
|
-
def controller(*extensions, &block)
|
60
|
-
if block_given?
|
61
|
-
@_controller, original = extensions, @_controller
|
62
|
-
instance_eval(&block)
|
63
|
-
@_controller = original
|
64
|
-
else
|
65
|
-
include(*extensions) if extensions.any?
|
66
|
-
end
|
67
|
-
end
|
68
|
-
alias :controllers :controller
|
69
|
-
|
70
|
-
##
|
71
|
-
# Usher router, for fatures and configurations see: http://github.com/joshbuddy/usher
|
72
|
-
#
|
73
|
-
# ==== Examples
|
74
|
-
#
|
75
|
-
# router.add_route('/greedy/{!:greed,.*}')
|
76
|
-
# router.recognize_path('/simple')
|
77
|
-
#
|
78
|
-
def router
|
79
|
-
@router ||= Usher.new(:request_methods => [:request_method, :host, :port, :scheme],
|
80
|
-
:ignore_trailing_delimiters => true,
|
81
|
-
:generator => Usher::Util::Generators::URL.new)
|
82
|
-
block_given? ? yield(@router) : @router
|
83
|
-
end
|
84
|
-
alias :urls :router
|
85
|
-
|
86
|
-
##
|
87
|
-
# Instance method for url generation like:
|
88
|
-
#
|
89
|
-
# ==== Examples
|
90
|
-
#
|
91
|
-
# url(:show, :id => 1)
|
92
|
-
# url(:show, :name => :test)
|
93
|
-
# url("/show/:id/:name", :id => 1, :name => foo)
|
94
|
-
#
|
95
|
-
def url(name, *params)
|
96
|
-
params.map! do |param|
|
97
|
-
if param.is_a?(Hash)
|
98
|
-
param[:format] = param[:format].to_s if param.has_key?(:format)
|
99
|
-
param.each { |k,v| param[k] = v.to_param if v.respond_to?(:to_param) }
|
100
|
-
end
|
101
|
-
end
|
102
|
-
url = router.generator.generate(name, *params)
|
103
|
-
uri_root != "/" ? uri_root + url : url
|
104
|
-
end
|
105
|
-
alias :url_for :url
|
106
|
-
|
107
|
-
##
|
108
|
-
# With this method we can use layout like rails do or if a block given like sinatra
|
109
|
-
# By default we look in your/app/views/layouts/application.(haml|erb|etc)
|
110
|
-
#
|
111
|
-
# If you define:
|
112
|
-
#
|
113
|
-
# layout :custom
|
114
|
-
#
|
115
|
-
# Padrino look for your/app/views/layouts/custom.(haml|erb|etc)
|
116
|
-
#
|
39
|
+
# Use layout like rails does or if a block given then like sinatra.
|
40
|
+
# If used without a block, sets the current layout for the route.
|
41
|
+
#
|
42
|
+
# By default, searches in your +app/views/layouts/application.(haml|erb|xxx)+
|
43
|
+
#
|
44
|
+
# If you define +layout :custom+ then searches for your layouts in
|
45
|
+
# +app/views/layouts/custom.(haml|erb|xxx)+
|
46
|
+
#
|
117
47
|
def layout(name=:layout, &block)
|
118
48
|
return super(name, &block) if block_given?
|
119
49
|
@_layout = name
|
@@ -121,13 +51,14 @@ module Padrino
|
|
121
51
|
|
122
52
|
##
|
123
53
|
# Reloads the application files from all defined load paths
|
124
|
-
#
|
125
|
-
# This method is used from our Padrino Reloader
|
126
|
-
#
|
54
|
+
#
|
55
|
+
# This method is used from our Padrino Reloader during development mode
|
56
|
+
# in order to reload the source files.
|
57
|
+
#
|
127
58
|
# ==== Examples
|
128
|
-
#
|
59
|
+
#
|
129
60
|
# MyApp.reload!
|
130
|
-
#
|
61
|
+
#
|
131
62
|
def reload!
|
132
63
|
reset_routes! # remove all existing user-defined application routes
|
133
64
|
Padrino.load_dependency(self.app_file) # reload the app file
|
@@ -136,11 +67,11 @@ module Padrino
|
|
136
67
|
|
137
68
|
##
|
138
69
|
# Resets application routes to only routes not defined by the user
|
139
|
-
#
|
70
|
+
#
|
140
71
|
# ==== Examples
|
141
|
-
#
|
72
|
+
#
|
142
73
|
# MyApp.reset_routes!
|
143
|
-
#
|
74
|
+
#
|
144
75
|
def reset_routes!
|
145
76
|
router.reset!
|
146
77
|
default_routes!
|
@@ -149,11 +80,11 @@ module Padrino
|
|
149
80
|
##
|
150
81
|
# Setup the application by registering initializers, load paths and logger
|
151
82
|
# Invoked automatically when an application is first instantiated
|
152
|
-
#
|
83
|
+
#
|
153
84
|
def setup_application!
|
154
85
|
return if @_configured
|
155
|
-
self.register_framework_extensions
|
156
86
|
self.calculate_paths
|
87
|
+
self.register_framework_extensions
|
157
88
|
self.register_initializers
|
158
89
|
self.require_load_paths
|
159
90
|
self.disable :logging # We need do that as default because Sinatra use commonlogger.
|
@@ -163,9 +94,10 @@ module Padrino
|
|
163
94
|
end
|
164
95
|
|
165
96
|
protected
|
97
|
+
|
166
98
|
##
|
167
99
|
# Defines default settings for Padrino application
|
168
|
-
#
|
100
|
+
#
|
169
101
|
def default_configuration!
|
170
102
|
# Overwriting Sinatra defaults
|
171
103
|
set :app_file, caller_files.first || $0 # Assume app file is first caller
|
@@ -183,7 +115,6 @@ module Padrino
|
|
183
115
|
set :authentication, false
|
184
116
|
# Padrino locale
|
185
117
|
set :locale_path, Proc.new { Dir[File.join(self.root, "/locale/**/*.{rb,yml}")] }
|
186
|
-
set :auto_locale, false
|
187
118
|
# Plugin specific
|
188
119
|
set :padrino_mailer, defined?(Padrino::Mailer)
|
189
120
|
set :padrino_helpers, defined?(Padrino::Helpers)
|
@@ -191,7 +122,7 @@ module Padrino
|
|
191
122
|
|
192
123
|
##
|
193
124
|
# We need to add almost __sinatra__ images.
|
194
|
-
#
|
125
|
+
#
|
195
126
|
def default_routes!
|
196
127
|
# images resources
|
197
128
|
get "/__sinatra__/:image.png" do
|
@@ -202,7 +133,7 @@ module Padrino
|
|
202
133
|
|
203
134
|
##
|
204
135
|
# This filter it's used for know the format of the request, and automatically set the content type.
|
205
|
-
#
|
136
|
+
#
|
206
137
|
def default_filters!
|
207
138
|
before do
|
208
139
|
request.path_info =~ /\.([^\.\/]+)$/
|
@@ -213,7 +144,7 @@ module Padrino
|
|
213
144
|
|
214
145
|
##
|
215
146
|
# This log errors for production environments
|
216
|
-
#
|
147
|
+
#
|
217
148
|
def default_errors!
|
218
149
|
configure :production do
|
219
150
|
error ::Exception do
|
@@ -229,7 +160,7 @@ module Padrino
|
|
229
160
|
##
|
230
161
|
# Calculates any required paths after app_file and root have been properly configured
|
231
162
|
# Executes as part of the setup_application! method
|
232
|
-
#
|
163
|
+
#
|
233
164
|
def calculate_paths
|
234
165
|
raise ApplicationSetupError.new("Please define 'app_file' option for #{self.name} app!") unless self.app_file
|
235
166
|
set :views, find_view_path if find_view_path
|
@@ -237,19 +168,17 @@ module Padrino
|
|
237
168
|
end
|
238
169
|
|
239
170
|
##
|
240
|
-
# Requires the middleware
|
241
|
-
#
|
171
|
+
# Requires the Padrino middleware
|
172
|
+
#
|
242
173
|
def register_initializers
|
243
174
|
use Padrino::Logger::Rack
|
244
175
|
use Padrino::Reloader::Rack if reload?
|
245
176
|
use Rack::Flash if flash?
|
246
|
-
@initializer_path ||= Padrino.root + '/config/initializers/*.rb'
|
247
|
-
Dir[@initializer_path].each { |file| register_initializer(file) }
|
248
177
|
end
|
249
178
|
|
250
179
|
##
|
251
180
|
# Registers all desired padrino extension helpers
|
252
|
-
#
|
181
|
+
#
|
253
182
|
def register_framework_extensions
|
254
183
|
register Padrino::Mailer if padrino_mailer?
|
255
184
|
register Padrino::Helpers if padrino_helpers?
|
@@ -258,288 +187,25 @@ module Padrino
|
|
258
187
|
|
259
188
|
##
|
260
189
|
# Returns the load_paths for the application (relative to the application root)
|
261
|
-
#
|
190
|
+
#
|
262
191
|
def load_paths
|
263
192
|
@load_paths ||= ["urls.rb", "config/urls.rb", "mailers/*.rb", "controllers/**/*.rb", "controllers.rb", "helpers/*.rb"]
|
264
193
|
end
|
265
194
|
|
266
195
|
##
|
267
196
|
# Requires all files within the application load paths
|
268
|
-
#
|
197
|
+
#
|
269
198
|
def require_load_paths
|
270
199
|
load_paths.each { |path| Padrino.require_dependencies(File.join(self.root, path)) }
|
271
200
|
end
|
272
201
|
|
273
202
|
##
|
274
203
|
# Returns the path to the views directory from root by returning the first that is found
|
275
|
-
#
|
204
|
+
#
|
276
205
|
def find_view_path
|
277
206
|
@view_paths = ["views"].collect { |path| File.join(self.root, path) }
|
278
207
|
@view_paths.find { |path| Dir[File.join(path, '/**/*')].any? }
|
279
208
|
end
|
280
|
-
|
281
|
-
##
|
282
|
-
# Registers an initializer with the application
|
283
|
-
# register_initializer('/path/to/initializer')
|
284
|
-
#
|
285
|
-
def register_initializer(file_path)
|
286
|
-
Padrino.require_dependencies(file_path)
|
287
|
-
file_class = File.basename(file_path, '.rb').camelize
|
288
|
-
register "#{file_class}Initializer".constantize
|
289
|
-
rescue NameError => e
|
290
|
-
logger.error "The module '#{file_class}Initializer' (#{file_path}) didn't loaded properly!"
|
291
|
-
logger.error " Initializer error was '#{e.message}'"
|
292
|
-
end
|
293
|
-
|
294
|
-
private
|
295
|
-
##
|
296
|
-
# Rewrite default because now routes can be:
|
297
|
-
#
|
298
|
-
# ==== Examples
|
299
|
-
#
|
300
|
-
# get :index # => "/"
|
301
|
-
# get :index, :map => "/" # => "/"
|
302
|
-
# get :show, :map => "/show-me" # => "/show-me"
|
303
|
-
# get "/foo/bar" # => "/show"
|
304
|
-
# get :show, :with => :id # => "/show/:id"
|
305
|
-
# get :show, :with => [:id, :name] # => "/show/:id/:name"
|
306
|
-
# get :list, :respond_to => :js # => "/list.{:format,js)"
|
307
|
-
# get :list, :respond_to => :any # => "/list(.:format)"
|
308
|
-
# get :list, :respond_to => [:js, :json] # => "/list.{!format,js|json}"
|
309
|
-
# gen :list, :respond_to => [:html, :js, :json] # => "/list(.{!format,js|json})"
|
310
|
-
#
|
311
|
-
def route(verb, path, options={}, &block)
|
312
|
-
|
313
|
-
# We dup options so we can build HEAD request correctly
|
314
|
-
options = options.dup
|
315
|
-
|
316
|
-
# We need check if path is a symbol, if that it's a named route
|
317
|
-
map = options.delete(:map)
|
318
|
-
|
319
|
-
if path.kind_of?(Symbol)
|
320
|
-
name = path # The route name
|
321
|
-
path = map || "/#{path}" # The route path
|
322
|
-
end
|
323
|
-
|
324
|
-
if path.kind_of?(String)
|
325
|
-
# Little reformats
|
326
|
-
path.sub!(/\/index$/, "") # If the route end with /index we remove them
|
327
|
-
path = (uri_root == "/" ? "/" : "(/)") if path.blank? # Add a trailing delimiter if empty
|
328
|
-
|
329
|
-
# Now we need to parse our with params
|
330
|
-
if params = options.delete(:with)
|
331
|
-
path += "/" unless path =~ /\/$/
|
332
|
-
path += Array(params).collect(&:inspect).join("/")
|
333
|
-
end
|
334
|
-
|
335
|
-
# Now we need to parse our respond_to
|
336
|
-
if format = options.delete(:respond_to)
|
337
|
-
path += case format
|
338
|
-
when :any then "(.:format)"
|
339
|
-
when Array then
|
340
|
-
formats = format.dup # Prevent changes to HEAD verb
|
341
|
-
container = formats.delete(:html) ? "(%s)" : "%s"
|
342
|
-
match = ".{:format," + formats.collect { |f| "#{f}$" }.join("|") + "}"
|
343
|
-
container % match
|
344
|
-
else ".{:format,#{format}}"
|
345
|
-
end
|
346
|
-
end
|
347
|
-
|
348
|
-
# Build our controller
|
349
|
-
controller = Array(@_controller).collect(&:to_s)
|
350
|
-
|
351
|
-
unless controller.empty?
|
352
|
-
# Now we need to add our controller path only if not mapped directly
|
353
|
-
if map.blank?
|
354
|
-
controller_path = controller.join("/")
|
355
|
-
path = controller_path + path
|
356
|
-
end
|
357
|
-
# Here we build the correct name route
|
358
|
-
if name
|
359
|
-
controller_name = controller.join("_")
|
360
|
-
name = "#{controller_name}_#{name}".to_sym unless controller_name.blank?
|
361
|
-
end
|
362
|
-
end
|
363
|
-
|
364
|
-
# We need to have a path that start with / in some circumstances and that don't end with /
|
365
|
-
if path != "(/)" && path != "/"
|
366
|
-
path = "/" + path if path !~ /^\//
|
367
|
-
path.sub!(/\/$/, '')
|
368
|
-
end
|
369
|
-
end
|
370
|
-
|
371
|
-
# Standard Sinatra requirements
|
372
|
-
options[:conditions] ||= {}
|
373
|
-
options[:conditions][:request_method] = verb
|
374
|
-
options[:conditions][:host] = options.delete(:host) if options.key?(:host)
|
375
|
-
|
376
|
-
# Because of self.options.host
|
377
|
-
host_name(options.delete(:host)) if options.key?(:host)
|
378
|
-
|
379
|
-
# Sinatra defaults
|
380
|
-
define_method "#{verb} #{path}", &block
|
381
|
-
unbound_method = instance_method("#{verb} #{path}")
|
382
|
-
block =
|
383
|
-
if block.arity != 0
|
384
|
-
proc { unbound_method.bind(self).call(*@block_params) }
|
385
|
-
else
|
386
|
-
proc { unbound_method.bind(self).call }
|
387
|
-
end
|
388
|
-
|
389
|
-
invoke_hook(:route_added, verb, path, block)
|
390
|
-
|
391
|
-
route = router.add_route(path, options).to(block)
|
392
|
-
route.name(name) if name
|
393
|
-
route
|
394
|
-
end
|
395
|
-
end # self
|
396
|
-
|
397
|
-
##
|
398
|
-
# Return the request format, this is useful when we need to respond to a given content_type like:
|
399
|
-
#
|
400
|
-
# ==== Examples
|
401
|
-
#
|
402
|
-
# get :index, :respond_to => :any do
|
403
|
-
# case content_type
|
404
|
-
# when :js then ...
|
405
|
-
# when :json then ...
|
406
|
-
# when :html then ...
|
407
|
-
# end
|
408
|
-
# end
|
409
|
-
#
|
410
|
-
def content_type(type=nil, params={})
|
411
|
-
type.nil? ? @_content_type : super(type, params)
|
412
|
-
end
|
413
|
-
|
414
|
-
##
|
415
|
-
# Instance method for url generation like:
|
416
|
-
#
|
417
|
-
# ==== Examples
|
418
|
-
#
|
419
|
-
# url(:show, :id => 1)
|
420
|
-
# url(:show, :name => :test)
|
421
|
-
# url("/show/:id/:name", :id => 1, :name => foo)
|
422
|
-
#
|
423
|
-
def url(name, *params)
|
424
|
-
self.class.url(name, *params)
|
425
|
-
end
|
426
|
-
alias :url_for :url
|
427
|
-
|
428
|
-
##
|
429
|
-
# This is mostly just a helper so request.path_info isn't changed when
|
430
|
-
# serving files from the public directory
|
431
|
-
#
|
432
|
-
def static_file?(path_info)
|
433
|
-
return if (public_dir = options.public).nil?
|
434
|
-
public_dir = File.expand_path(public_dir)
|
435
|
-
|
436
|
-
path = File.expand_path(public_dir + unescape(path_info))
|
437
|
-
return if path[0, public_dir.length] != public_dir
|
438
|
-
return unless File.file?(path)
|
439
|
-
return path
|
440
|
-
end
|
441
|
-
|
442
|
-
private
|
443
|
-
|
444
|
-
##
|
445
|
-
# Method for deliver static files, Sinatra 0.10.x or 1.0.x have this method
|
446
|
-
# but for now we use this (because we need a compatibility with 0.9.x) and also
|
447
|
-
# because we just have +static_file?+ method.
|
448
|
-
#
|
449
|
-
def static!
|
450
|
-
if path = static_file?(request.path_info)
|
451
|
-
send_file(path, :disposition => nil)
|
452
|
-
end
|
453
|
-
end
|
454
|
-
|
455
|
-
##
|
456
|
-
# Compatibility with usher
|
457
|
-
#
|
458
|
-
def route!(base=self.class, pass_block=nil)
|
459
|
-
# TODO: remove this when sinatra 1.0 will be released
|
460
|
-
if Sinatra::VERSION =~ /^0\.9/
|
461
|
-
# enable nested params in Rack < 1.0; allow indifferent access
|
462
|
-
@params = if Rack::Utils.respond_to?(:parse_nested_query)
|
463
|
-
indifferent_params(@request.params)
|
464
|
-
else
|
465
|
-
nested_params(@request.params)
|
466
|
-
end
|
467
|
-
# deliver static files
|
468
|
-
static! if options.static? && (request.get? || request.head?)
|
469
|
-
# perform before filters
|
470
|
-
self.class.filters.each { |block| instance_eval(&block) }
|
471
|
-
end
|
472
|
-
|
473
|
-
# Usher
|
474
|
-
if self.class.router and match = self.class.router.recognize(@request, @request.path_info)
|
475
|
-
@block_params = match.params.map{|p| p.last}
|
476
|
-
@params = @params ? @params.merge(match.params_as_hash) : match.params_as_hash
|
477
|
-
pass_block = catch(:pass) do
|
478
|
-
route_eval(&match.destination)
|
479
|
-
end
|
480
|
-
elsif base.superclass.respond_to?(:routes)
|
481
|
-
route! base.superclass
|
482
|
-
else
|
483
|
-
route_missing
|
484
|
-
end
|
485
|
-
end
|
486
|
-
|
487
|
-
##
|
488
|
-
# When we set :auto_locale, true then if we use param locale like:
|
489
|
-
#
|
490
|
-
# ==== Examples
|
491
|
-
#
|
492
|
-
# get "/:locale/some/foo" do; ...; end
|
493
|
-
#
|
494
|
-
# we automatically set the I18n locale to params[:locale]
|
495
|
-
#
|
496
|
-
def route_eval(&block)
|
497
|
-
if options.auto_locale
|
498
|
-
if params[:locale]
|
499
|
-
I18n.locale = params[:locale].to_sym rescue options.locale
|
500
|
-
end
|
501
|
-
end
|
502
|
-
super(&block)
|
503
|
-
end
|
504
|
-
|
505
|
-
##
|
506
|
-
# Hijacking the sinatra render for do three thing:
|
507
|
-
#
|
508
|
-
# * Use layout like rails do
|
509
|
-
# * Use render 'path/to/my/template' (without symbols)
|
510
|
-
# * Use render 'path/to/my/template' (with auto enegine lookup)
|
511
|
-
#
|
512
|
-
def render(engine, data=nil, options={}, locals={}, &block)
|
513
|
-
# TODO: remove these @template_cache.respond_to?(:clear) when sinatra 1.0 will be released
|
514
|
-
@template_cache.clear if Padrino.env != :production && @template_cache && @template_cache.respond_to?(:clear)
|
515
|
-
# If engine is an hash we convert to json
|
516
|
-
return engine.to_json if engine.is_a?(Hash)
|
517
|
-
# If an engine is a string probably is a path so we try to resolve them
|
518
|
-
if data.nil?
|
519
|
-
data = engine.to_sym
|
520
|
-
engine = resolve_template_engine(engine)
|
521
|
-
end
|
522
|
-
# Use layout as rails do
|
523
|
-
if (options[:layout].nil? || options[:layout] == true) && !self.class.templates.has_key?(:layout)
|
524
|
-
layout = self.class.instance_variable_defined?(:@_layout) ? self.class.instance_variable_get(:@_layout) : :application
|
525
|
-
if layout
|
526
|
-
# We look first for views/layout_name.ext then then for views/layouts/layout_name.ext
|
527
|
-
options[:layout] = Dir["#{self.options.views}/#{layout}.*"].present? ? layout.to_sym : File.join('layouts', layout.to_s).to_sym
|
528
|
-
logger.debug "Rendering layout #{options[:layout]}"
|
529
|
-
end
|
530
|
-
end
|
531
|
-
super(engine, data, options, locals, &block)
|
532
|
-
end
|
533
|
-
|
534
|
-
##
|
535
|
-
# Returns the template engine (i.e haml) to use for a given template_path
|
536
|
-
# resolve_template_engine('users/new') => :haml
|
537
|
-
#
|
538
|
-
def resolve_template_engine(template_path)
|
539
|
-
resolved_template_path = File.join(self.options.views, template_path.to_s + ".*")
|
540
|
-
template_file = Dir[resolved_template_path].first
|
541
|
-
raise "Template path '#{template_path}' could not be located in views!" unless template_file
|
542
|
-
template_engine = File.extname(template_file)[1..-1].to_sym
|
543
|
-
end
|
209
|
+
end # Class Methods
|
544
210
|
end # Application
|
545
|
-
end # Padrino
|
211
|
+
end # Padrino
|
@@ -45,8 +45,7 @@ module Padrino
|
|
45
45
|
app_obj.set :app_name, app_data.name
|
46
46
|
app_obj.set :app_file, app_data.app_file unless ::File.exist?(app_obj.app_file)
|
47
47
|
app_obj.set :root, app_data.app_root unless app_data.app_root.blank?
|
48
|
-
# We need to initialize here the app.
|
49
|
-
app_obj.setup_application!
|
48
|
+
app_obj.setup_application! # We need to initialize here the app.
|
50
49
|
run app_obj
|
51
50
|
end
|
52
51
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Padrino
|
2
|
+
module Rendering
|
3
|
+
def self.registered(app)
|
4
|
+
app.send(:include, Padrino::Rendering)
|
5
|
+
end
|
6
|
+
|
7
|
+
private
|
8
|
+
##
|
9
|
+
# Hijacking the sinatra render for do three thing:
|
10
|
+
#
|
11
|
+
# * Use layout like rails do
|
12
|
+
# * Use render 'path/to/my/template' (without symbols)
|
13
|
+
# * Use render 'path/to/my/template' (with auto enegine lookup)
|
14
|
+
#
|
15
|
+
def render(engine, data=nil, options={}, locals={}, &block)
|
16
|
+
# TODO: remove these @template_cache.respond_to?(:clear) when sinatra 1.0 will be released
|
17
|
+
@template_cache.clear if Padrino.env != :production && @template_cache && @template_cache.respond_to?(:clear)
|
18
|
+
# If engine is an hash we convert to json
|
19
|
+
return engine.to_json if engine.is_a?(Hash)
|
20
|
+
# If an engine is a string probably is a path so we try to resolve them
|
21
|
+
if data.nil?
|
22
|
+
data = engine.to_sym
|
23
|
+
engine = resolve_template_engine(engine)
|
24
|
+
end
|
25
|
+
# Use layout as rails do
|
26
|
+
if (options[:layout].nil? || options[:layout] == true) && !self.class.templates.has_key?(:layout)
|
27
|
+
layout = self.class.instance_variable_defined?(:@_layout) ? self.class.instance_variable_get(:@_layout) : :application
|
28
|
+
if layout
|
29
|
+
# We look first for views/layout_name.ext then then for views/layouts/layout_name.ext
|
30
|
+
options[:layout] = Dir["#{self.options.views}/#{layout}.*"].present? ? layout.to_sym : File.join('layouts', layout.to_s).to_sym
|
31
|
+
logger.debug "Rendering layout #{options[:layout]}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
super(engine, data, options, locals, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# Returns the template engine (i.e haml) to use for a given template_path
|
39
|
+
# resolve_template_engine('users/new') => :haml
|
40
|
+
#
|
41
|
+
def resolve_template_engine(template_path)
|
42
|
+
resolved_template_path = File.join(self.options.views, template_path.to_s + ".*")
|
43
|
+
template_file = Dir[resolved_template_path].first
|
44
|
+
raise "Template path '#{template_path}' could not be located in views!" unless template_file
|
45
|
+
template_engine = File.extname(template_file)[1..-1].to_sym
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,313 @@
|
|
1
|
+
require 'usher' unless defined?(Usher)
|
2
|
+
require 'padrino-core/support_lite' unless String.method_defined?(:blank!)
|
3
|
+
|
4
|
+
module Padrino
|
5
|
+
module Routing
|
6
|
+
def self.registered(app)
|
7
|
+
app.send(:include, Padrino::Routing)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.included(base)
|
11
|
+
base.extend Padrino::Routing::ClassMethods
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# Compatibility with usher
|
16
|
+
#
|
17
|
+
def route!(base=self.class, pass_block=nil)
|
18
|
+
# TODO: remove this when sinatra 1.0 will be released
|
19
|
+
if Sinatra::VERSION =~ /^0\.9/
|
20
|
+
# enable nested params in Rack < 1.0; allow indifferent access
|
21
|
+
can_parse_nested = Rack::Utils.respond_to?(:parse_nested_query)
|
22
|
+
@params = can_parse_nested ? indifferent_params(@request.params) : nested_params(@request.params)
|
23
|
+
# deliver static files
|
24
|
+
static! if options.static? && (request.get? || request.head?)
|
25
|
+
# perform before filters
|
26
|
+
self.class.filters.each { |block| instance_eval(&block) }
|
27
|
+
end # for sinatra = 0.9
|
28
|
+
|
29
|
+
# Usher
|
30
|
+
if self.class.router and match = self.class.router.recognize(@request, @request.path_info)
|
31
|
+
@block_params = match.params.map { |p| p.last }
|
32
|
+
@params = @params ? @params.merge(match.params_as_hash) : match.params_as_hash
|
33
|
+
pass_block = catch(:pass) do
|
34
|
+
route_eval(&match.destination)
|
35
|
+
end
|
36
|
+
elsif base.superclass.respond_to?(:routes)
|
37
|
+
route! base.superclass
|
38
|
+
else
|
39
|
+
route_missing
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# Instance method for url generation like:
|
45
|
+
#
|
46
|
+
# ==== Examples
|
47
|
+
#
|
48
|
+
# url(:show, :id => 1)
|
49
|
+
# url(:show, :name => :test)
|
50
|
+
# url("/show/:id/:name", :id => 1, :name => foo)
|
51
|
+
#
|
52
|
+
def url(*names)
|
53
|
+
self.class.url(*names)
|
54
|
+
end
|
55
|
+
alias :url_for :url
|
56
|
+
|
57
|
+
##
|
58
|
+
# This is mostly just a helper so request.path_info isn't changed when
|
59
|
+
# serving files from the public directory
|
60
|
+
#
|
61
|
+
def static_file?(path_info)
|
62
|
+
return if (public_dir = options.public).nil?
|
63
|
+
public_dir = File.expand_path(public_dir)
|
64
|
+
|
65
|
+
path = File.expand_path(public_dir + unescape(path_info))
|
66
|
+
return if path[0, public_dir.length] != public_dir
|
67
|
+
return unless File.file?(path)
|
68
|
+
return path
|
69
|
+
end
|
70
|
+
|
71
|
+
##
|
72
|
+
# Return the request format, this is useful when we need to respond to a given content_type like:
|
73
|
+
#
|
74
|
+
# ==== Examples
|
75
|
+
#
|
76
|
+
# get :index, :respond_to => :any do
|
77
|
+
# case content_type
|
78
|
+
# when :js then ...
|
79
|
+
# when :json then ...
|
80
|
+
# when :html then ...
|
81
|
+
# end
|
82
|
+
# end
|
83
|
+
#
|
84
|
+
def content_type(type=nil, params={})
|
85
|
+
type.nil? ? @_content_type : super(type, params)
|
86
|
+
end
|
87
|
+
|
88
|
+
##
|
89
|
+
# Method for deliver static files, Sinatra 0.10.x or 1.0.x have this method
|
90
|
+
# but for now we use this (because we need a compatibility with 0.9.x) and also
|
91
|
+
# because we just have +static_file?+ method.
|
92
|
+
#
|
93
|
+
def static!
|
94
|
+
if path = static_file?(request.path_info)
|
95
|
+
send_file(path, :disposition => nil)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
module ClassMethods
|
100
|
+
##
|
101
|
+
# Method for organize in a better way our routes like:
|
102
|
+
#
|
103
|
+
# controller :admin do
|
104
|
+
# get :index do; ...; end
|
105
|
+
# get :show, :with => :id do; ...; end
|
106
|
+
# end
|
107
|
+
#
|
108
|
+
# Now you can call your actions with:
|
109
|
+
#
|
110
|
+
# url(:admin_index) # => "/admin"
|
111
|
+
# url(:admin_show, :id => 1) # "/admin/show/1"
|
112
|
+
#
|
113
|
+
# You can instead using named routes follow the sinatra way like:
|
114
|
+
#
|
115
|
+
# controller "/admin" do
|
116
|
+
# get "/index" do; ...; end
|
117
|
+
# get "/show/:id" do; ...; end
|
118
|
+
# end
|
119
|
+
#
|
120
|
+
# And you can call directly these urls:
|
121
|
+
#
|
122
|
+
# # => "/admin"
|
123
|
+
# # => "/admin/show/1"
|
124
|
+
#
|
125
|
+
def controller(*extensions, &block)
|
126
|
+
if block_given?
|
127
|
+
options = extensions.extract_options!
|
128
|
+
@_controller, original_controller = extensions, @_controller
|
129
|
+
@_parents, original_parent = options[:parent], @_parents
|
130
|
+
instance_eval(&block)
|
131
|
+
@_controller, @_parents = original_controller, original_parent
|
132
|
+
else
|
133
|
+
include(*extensions) if extensions.any?
|
134
|
+
end
|
135
|
+
end
|
136
|
+
alias :controllers :controller
|
137
|
+
|
138
|
+
##
|
139
|
+
# Usher router, for fatures and configurations see: http://github.com/joshbuddy/usher
|
140
|
+
#
|
141
|
+
# ==== Examples
|
142
|
+
#
|
143
|
+
# router.add_route('/greedy/{!:greed,.*}')
|
144
|
+
# router.recognize_path('/simple')
|
145
|
+
#
|
146
|
+
def router
|
147
|
+
@router ||= Usher.new(:request_methods => [:request_method, :host, :port, :scheme],
|
148
|
+
:ignore_trailing_delimiters => true,
|
149
|
+
:generator => Usher::Util::Generators::URL.new)
|
150
|
+
block_given? ? yield(@router) : @router
|
151
|
+
end
|
152
|
+
alias :urls :router
|
153
|
+
|
154
|
+
##
|
155
|
+
# Instance method for url generation like:
|
156
|
+
#
|
157
|
+
# ==== Examples
|
158
|
+
#
|
159
|
+
# url(:show, :id => 1)
|
160
|
+
# url(:show, :name => :test)
|
161
|
+
# url("/show/:id/:name", :id => 1, :name => foo)
|
162
|
+
#
|
163
|
+
def url(*names)
|
164
|
+
params = names.extract_options! # parameters is hash at end
|
165
|
+
name = names.join("_").to_sym # route name is concatenated with underscores
|
166
|
+
if params.is_a?(Hash)
|
167
|
+
params[:format] = params[:format].to_s if params.has_key?(:format)
|
168
|
+
params.each { |k,v| params[k] = v.to_param if v.respond_to?(:to_param) }
|
169
|
+
end
|
170
|
+
url = router.generator.generate(name, params)
|
171
|
+
url = uri_root + url if defined?(uri_root) && uri_root != "/"
|
172
|
+
url
|
173
|
+
end
|
174
|
+
alias :url_for :url
|
175
|
+
|
176
|
+
private
|
177
|
+
|
178
|
+
##
|
179
|
+
# Rewrite default because now routes can be:
|
180
|
+
#
|
181
|
+
# ==== Examples
|
182
|
+
#
|
183
|
+
# get :index # => "/"
|
184
|
+
# get :index, :map => "/" # => "/"
|
185
|
+
# get :show, :map => "/show-me" # => "/show-me"
|
186
|
+
# get "/foo/bar" # => "/show"
|
187
|
+
# get :index, :parent => :user # => "/user/:user_id/index"
|
188
|
+
# get :show, :with => :id, :parent => :user # => "/user/:user_id/show/:id"
|
189
|
+
# get :show, :with => :id # => "/show/:id"
|
190
|
+
# get :show, :with => [:id, :name] # => "/show/:id/:name"
|
191
|
+
# get :list, :respond_to => :js # => "/list.{:format,js)"
|
192
|
+
# get :list, :respond_to => :any # => "/list(.:format)"
|
193
|
+
# get :list, :respond_to => [:js, :json] # => "/list.{!format,js|json}"
|
194
|
+
# get :list, :respond_to => [:html, :js, :json] # => "/list(.{!format,js|json})"
|
195
|
+
#
|
196
|
+
def route(verb, path, options={}, &block)
|
197
|
+
# We dup options so we can build HEAD request correctly
|
198
|
+
options = options.dup
|
199
|
+
# We need check if path is a symbol, if that it's a named route
|
200
|
+
map = options.delete(:map)
|
201
|
+
|
202
|
+
if path.kind_of?(Symbol) # path i.e :index or :show
|
203
|
+
name = path # The route name
|
204
|
+
path = map || path.to_s # The route path
|
205
|
+
end
|
206
|
+
|
207
|
+
if path.kind_of?(String) # path i.e "/index" or "/show"
|
208
|
+
# Now we need to parse our 'with' params
|
209
|
+
if with_params = options.delete(:with)
|
210
|
+
path = process_path_for_with_params(path, with_params)
|
211
|
+
end
|
212
|
+
|
213
|
+
# Now we need to parse our respond_to
|
214
|
+
if format_params = options.delete(:respond_to)
|
215
|
+
path = process_path_for_respond_to(path, format_params)
|
216
|
+
end
|
217
|
+
|
218
|
+
# Build our controller
|
219
|
+
controller = Array(@_controller).collect(&:to_s)
|
220
|
+
|
221
|
+
unless controller.empty?
|
222
|
+
# Now we need to add our controller path only if not mapped directly
|
223
|
+
if map.blank?
|
224
|
+
controller_path = controller.join("/")
|
225
|
+
path = File.join(controller_path, path)
|
226
|
+
end
|
227
|
+
# Here we build the correct name route
|
228
|
+
if name
|
229
|
+
controller_name = controller.join("_")
|
230
|
+
name = "#{controller_name}_#{name}".to_sym unless controller_name.blank?
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
# Now we need to parse our 'parent' params and parent scope
|
235
|
+
if parent_params = options.delete(:parent) || @_parents
|
236
|
+
parent_params = Array(@_parents) + Array(parent_params)
|
237
|
+
path = process_path_for_parent_params(path, parent_params)
|
238
|
+
end
|
239
|
+
|
240
|
+
# Little reformats
|
241
|
+
path.sub!(%r{\bindex$}, "") # If the route end with /index we remove them
|
242
|
+
path = (uri_root == "/" ? "/" : "(/)") if path.blank? # Add a trailing delimiter if path is empty
|
243
|
+
|
244
|
+
# We need to have a path that start with / in some circumstances and that don't end with /
|
245
|
+
if path != "(/)" && path != "/"
|
246
|
+
path = "/" + path unless path =~ %r{^/}
|
247
|
+
path.sub!(%r{/$}, '')
|
248
|
+
end
|
249
|
+
|
250
|
+
# We need to fix some differences between usher and sintra router
|
251
|
+
path.sub!(%r{/\?$}, '(/)') # '/foo/?' => '/foo(/)'
|
252
|
+
end
|
253
|
+
|
254
|
+
# Standard Sinatra requirements
|
255
|
+
options[:conditions] ||= {}
|
256
|
+
options[:conditions][:request_method] = verb
|
257
|
+
options[:conditions][:host] = options.delete(:host) if options.key?(:host)
|
258
|
+
|
259
|
+
# Because of self.options.host
|
260
|
+
host_name(options.delete(:host)) if options.key?(:host)
|
261
|
+
|
262
|
+
# Sinatra defaults
|
263
|
+
define_method "#{verb} #{path}", &block
|
264
|
+
unbound_method = instance_method("#{verb} #{path}")
|
265
|
+
block =
|
266
|
+
if block.arity != 0
|
267
|
+
proc { unbound_method.bind(self).call(*@block_params) }
|
268
|
+
else
|
269
|
+
proc { unbound_method.bind(self).call }
|
270
|
+
end
|
271
|
+
|
272
|
+
invoke_hook(:route_added, verb, path, block)
|
273
|
+
route = router.add_route(path, options).to(block)
|
274
|
+
route.name(name) if name
|
275
|
+
route
|
276
|
+
end
|
277
|
+
|
278
|
+
##
|
279
|
+
# Processes the existing path and appends the 'with' parameters onto the route
|
280
|
+
# Used for calculating path in route method
|
281
|
+
#
|
282
|
+
def process_path_for_with_params(path, with_params)
|
283
|
+
File.join(path, Array(with_params).collect(&:inspect).join("/"))
|
284
|
+
end
|
285
|
+
|
286
|
+
##
|
287
|
+
# Processes the existing path and prepends the 'parent' parameters onto the route
|
288
|
+
# Used for calculating path in route method
|
289
|
+
#
|
290
|
+
def process_path_for_parent_params(path, parent_params)
|
291
|
+
parent_prefix = parent_params.uniq.collect { |param| "#{param}/:#{param}_id" }.join("/")
|
292
|
+
File.join(parent_prefix, path)
|
293
|
+
end
|
294
|
+
|
295
|
+
##
|
296
|
+
# Processes the existing path and appends the 'format' suffix onto the route
|
297
|
+
# Used for calculating path in route method
|
298
|
+
#
|
299
|
+
def process_path_for_respond_to(path, format_params)
|
300
|
+
format_suffix = case format_params
|
301
|
+
when :any then "(.:format)"
|
302
|
+
when Array then
|
303
|
+
formats = format_params.dup # Prevent changes to HEAD verb
|
304
|
+
container = formats.delete(:html) ? "(%s)" : "%s"
|
305
|
+
match = ".{:format," + formats.collect { |f| "#{f}$" }.join("|") + "}"
|
306
|
+
container % match
|
307
|
+
else ".{:format,#{format_params}}"
|
308
|
+
end
|
309
|
+
path << format_suffix
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
data/lib/padrino-core/caller.rb
CHANGED
@@ -10,7 +10,7 @@ module Padrino
|
|
10
10
|
#
|
11
11
|
# It is performing a check/reload cycle at the start of every request, but
|
12
12
|
# also respects a cool down time, during which nothing will be done.
|
13
|
-
#
|
13
|
+
#
|
14
14
|
class Rack
|
15
15
|
def initialize(app, cooldown = 1)
|
16
16
|
@app = app
|
@@ -33,6 +33,14 @@ module Padrino
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
+
##
|
37
|
+
# You can exclude some folders from reload its contents.
|
38
|
+
# Defaults excluded directories of Padrino.root are: test, spec, features, tmp, config, lib and public
|
39
|
+
#
|
40
|
+
def self.exclude
|
41
|
+
@_exclude ||= %w(test spec tmp features config lib public).map { |path| Padrino.root(path) }
|
42
|
+
end
|
43
|
+
|
36
44
|
##
|
37
45
|
# What makes it especially suited for use in a any environment is that
|
38
46
|
# any file will only be checked once and there will only be made one system
|
@@ -79,8 +87,8 @@ module Padrino
|
|
79
87
|
# Search Ruby files in your +Padrino.root+ and monitor them for changes.
|
80
88
|
#
|
81
89
|
def rotation
|
82
|
-
|
83
|
-
|
90
|
+
paths = Dir[Padrino.root("*")].reject { |path| Padrino::Reloader.exclude.include?(path) || !File.directory?(path) }
|
91
|
+
files = paths.map { |path| Dir["#{path}/**/*.rb"] }.flatten
|
84
92
|
|
85
93
|
files.map{ |file|
|
86
94
|
found, stat = figure_path(file, paths)
|
@@ -1,19 +1,17 @@
|
|
1
1
|
##
|
2
|
-
# This file
|
2
|
+
# This file loads certain extensions required by Padrino from ActiveSupport.
|
3
3
|
#
|
4
|
-
# Why ActiveSupport and not
|
4
|
+
# Why use ActiveSupport and not our own library or extlib?
|
5
|
+
#
|
6
|
+
# 1) Writing custom method extensions needed (i.e string inflections) is not a good use of time.
|
7
|
+
# 2) Loading custom method extensions or separate gem would conflict when AR or MM has been loaded.
|
8
|
+
# 3) Datamapper is planning to move to ActiveSupport and away from extlib.
|
5
9
|
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
# 1) ActiveRecord need ActiveSupport
|
9
|
-
# 2) MongoMapper need ActiveSuport
|
10
|
-
# 3) DataMapper it's planning to migrate to ActiveSupport (see: http://wiki.github.com/datamapper/dm-core/roadmap)
|
11
|
-
#
|
12
|
-
# Required for Padrino to run:
|
10
|
+
# Extensions required for Padrino:
|
13
11
|
#
|
14
12
|
# * Class#cattr_accessor
|
15
13
|
# * Module#alias_method_chain
|
16
|
-
# * String#inflectors (classify, underscore, camelize, etc)
|
14
|
+
# * String#inflectors (classify, underscore, camelize, pluralize, etc)
|
17
15
|
# * Array#extract_options!
|
18
16
|
# * Object#blank?
|
19
17
|
# * Object#present?
|
@@ -38,7 +36,7 @@ require 'active_support/core_ext/module'
|
|
38
36
|
require 'active_support/ordered_hash'
|
39
37
|
|
40
38
|
##
|
41
|
-
# Define our
|
39
|
+
# Define our own OrderedHash based on AS::OrderedHash
|
42
40
|
#
|
43
41
|
unless defined?(SupportLite::OrderedHash)
|
44
42
|
module SupportLite
|
@@ -47,7 +45,7 @@ unless defined?(SupportLite::OrderedHash)
|
|
47
45
|
end
|
48
46
|
|
49
47
|
##
|
50
|
-
#
|
48
|
+
# Alias allowing for use of either method to get query parameters
|
51
49
|
#
|
52
50
|
unless Hash.method_defined?(:to_params)
|
53
51
|
class Hash
|
@@ -56,6 +54,6 @@ unless Hash.method_defined?(:to_params)
|
|
56
54
|
end
|
57
55
|
|
58
56
|
##
|
59
|
-
#
|
57
|
+
# Loads our locales configuration files
|
60
58
|
#
|
61
59
|
I18n.load_path += Dir["#{File.dirname(__FILE__)}/locale/*.yml"]
|
data/padrino-core.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{padrino-core}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.9.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Padrino Team", "Nathan Esquenazi", "Davide D'Agostino", "Arthur Chiu"]
|
12
|
-
s.date = %q{2010-02-
|
12
|
+
s.date = %q{2010-02-23}
|
13
13
|
s.default_executable = %q{padrino}
|
14
14
|
s.description = %q{The Padrino core gem required for use of this framework}
|
15
15
|
s.email = %q{padrinorb@gmail.com}
|
@@ -27,6 +27,9 @@ Gem::Specification.new do |s|
|
|
27
27
|
"bin/padrino",
|
28
28
|
"lib/padrino-core.rb",
|
29
29
|
"lib/padrino-core/application.rb",
|
30
|
+
"lib/padrino-core/application/mounter.rb",
|
31
|
+
"lib/padrino-core/application/rendering.rb",
|
32
|
+
"lib/padrino-core/application/routing.rb",
|
30
33
|
"lib/padrino-core/caller.rb",
|
31
34
|
"lib/padrino-core/cli/adapter.rb",
|
32
35
|
"lib/padrino-core/cli/base.rb",
|
@@ -39,7 +42,6 @@ Gem::Specification.new do |s|
|
|
39
42
|
"lib/padrino-core/locale/en.yml",
|
40
43
|
"lib/padrino-core/locale/it.yml",
|
41
44
|
"lib/padrino-core/logger.rb",
|
42
|
-
"lib/padrino-core/mounter.rb",
|
43
45
|
"lib/padrino-core/reloader.rb",
|
44
46
|
"lib/padrino-core/server.rb",
|
45
47
|
"lib/padrino-core/support_lite.rb",
|
@@ -80,8 +82,8 @@ Gem::Specification.new do |s|
|
|
80
82
|
s.add_runtime_dependency(%q<i18n>, [">= 0.3.2"])
|
81
83
|
s.add_runtime_dependency(%q<usher>, [">= 0.6.2"])
|
82
84
|
s.add_runtime_dependency(%q<thor>, [">= 0.13.0"])
|
83
|
-
s.add_runtime_dependency(%q<bundler>, ["= 0.9.
|
84
|
-
s.add_runtime_dependency(%q<activesupport>, ["
|
85
|
+
s.add_runtime_dependency(%q<bundler>, ["= 0.9.7"])
|
86
|
+
s.add_runtime_dependency(%q<activesupport>, ["= 2.3.5"])
|
85
87
|
s.add_development_dependency(%q<shoulda>, [">= 2.10.3"])
|
86
88
|
s.add_development_dependency(%q<mocha>, [">= 0.9.7"])
|
87
89
|
s.add_development_dependency(%q<rack-test>, [">= 0.5.0"])
|
@@ -91,8 +93,8 @@ Gem::Specification.new do |s|
|
|
91
93
|
s.add_dependency(%q<i18n>, [">= 0.3.2"])
|
92
94
|
s.add_dependency(%q<usher>, [">= 0.6.2"])
|
93
95
|
s.add_dependency(%q<thor>, [">= 0.13.0"])
|
94
|
-
s.add_dependency(%q<bundler>, ["= 0.9.
|
95
|
-
s.add_dependency(%q<activesupport>, ["
|
96
|
+
s.add_dependency(%q<bundler>, ["= 0.9.7"])
|
97
|
+
s.add_dependency(%q<activesupport>, ["= 2.3.5"])
|
96
98
|
s.add_dependency(%q<shoulda>, [">= 2.10.3"])
|
97
99
|
s.add_dependency(%q<mocha>, [">= 0.9.7"])
|
98
100
|
s.add_dependency(%q<rack-test>, [">= 0.5.0"])
|
@@ -103,8 +105,8 @@ Gem::Specification.new do |s|
|
|
103
105
|
s.add_dependency(%q<i18n>, [">= 0.3.2"])
|
104
106
|
s.add_dependency(%q<usher>, [">= 0.6.2"])
|
105
107
|
s.add_dependency(%q<thor>, [">= 0.13.0"])
|
106
|
-
s.add_dependency(%q<bundler>, ["= 0.9.
|
107
|
-
s.add_dependency(%q<activesupport>, ["
|
108
|
+
s.add_dependency(%q<bundler>, ["= 0.9.7"])
|
109
|
+
s.add_dependency(%q<activesupport>, ["= 2.3.5"])
|
108
110
|
s.add_dependency(%q<shoulda>, [">= 2.10.3"])
|
109
111
|
s.add_dependency(%q<mocha>, [">= 0.9.7"])
|
110
112
|
s.add_dependency(%q<rack-test>, [">= 0.5.0"])
|
data/test/test_application.rb
CHANGED
@@ -147,25 +147,4 @@ class TestApplication < Test::Unit::TestCase
|
|
147
147
|
end
|
148
148
|
end
|
149
149
|
end
|
150
|
-
|
151
|
-
context 'for application i18n functionality' do
|
152
|
-
|
153
|
-
should 'have auto_locale disabled' do
|
154
|
-
mock_app do
|
155
|
-
assert !auto_locale
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
should 'set locale when auto_locale is enabled' do
|
160
|
-
mock_app do
|
161
|
-
enable :auto_locale
|
162
|
-
get("/:locale"){ I18n.locale.to_s }
|
163
|
-
end
|
164
|
-
|
165
|
-
%w(it de fr).each do |lang|
|
166
|
-
get("/#{lang}")
|
167
|
-
assert_equal lang, body
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
171
150
|
end
|
data/test/test_routing.rb
CHANGED
@@ -12,7 +12,22 @@ class TestRouting < Test::Unit::TestCase
|
|
12
12
|
assert_equal "okey", body
|
13
13
|
end
|
14
14
|
|
15
|
-
should
|
15
|
+
should "parse routes with question marks" do
|
16
|
+
mock_app do
|
17
|
+
get("/foo/?"){ "okey" }
|
18
|
+
post('/unauthenticated/?') { "no access" }
|
19
|
+
end
|
20
|
+
get "/foo"
|
21
|
+
assert_equal "okey", body
|
22
|
+
get "/foo/"
|
23
|
+
assert_equal "okey", body
|
24
|
+
post "/unauthenticated"
|
25
|
+
assert_equal "no access", body
|
26
|
+
post "/unauthenticated/"
|
27
|
+
assert_equal "no access", body
|
28
|
+
end
|
29
|
+
|
30
|
+
should 'match correctly similar paths' do
|
16
31
|
mock_app do
|
17
32
|
get("/my/:foo_id"){ params[:foo_id] }
|
18
33
|
get("/my/:bar_id/bar"){ params[:bar_id] }
|
@@ -189,6 +204,26 @@ class TestRouting < Test::Unit::TestCase
|
|
189
204
|
assert_equal "foo_bar_index", body
|
190
205
|
end
|
191
206
|
|
207
|
+
should 'use named controllers with array routes' do
|
208
|
+
mock_app do
|
209
|
+
controller :admin do
|
210
|
+
get(:index){ "index" }
|
211
|
+
get(:show, :with => :id){ "show #{params[:id]}" }
|
212
|
+
end
|
213
|
+
controllers :foo, :bar do
|
214
|
+
get(:index){ "foo_bar_index" }
|
215
|
+
end
|
216
|
+
end
|
217
|
+
get "/admin"
|
218
|
+
assert_equal "index", body
|
219
|
+
get "/admin/show/1"
|
220
|
+
assert_equal "show 1", body
|
221
|
+
assert_equal "/admin", @app.url(:admin, :index)
|
222
|
+
assert_equal "/admin/show/1", @app.url(:admin, :show, :id => 1)
|
223
|
+
get "/foo/bar"
|
224
|
+
assert_equal "foo_bar_index", body
|
225
|
+
end
|
226
|
+
|
192
227
|
should 'reset routes' do
|
193
228
|
mock_app do
|
194
229
|
get("/"){ "foo" }
|
@@ -214,4 +249,37 @@ class TestRouting < Test::Unit::TestCase
|
|
214
249
|
assert_equal "edit 1", body
|
215
250
|
end
|
216
251
|
|
217
|
-
|
252
|
+
should "apply parent to route" do
|
253
|
+
mock_app do
|
254
|
+
controllers :project do
|
255
|
+
get(:index, :parent => :user) { "index #{params[:user_id]}" }
|
256
|
+
get(:edit, :with => :id, :parent => :user) { "edit #{params[:id]} #{params[:user_id]}"}
|
257
|
+
get(:show, :with => :id, :parent => [:user, :product]) { "show #{params[:id]} #{params[:user_id]} #{params[:product_id]}"}
|
258
|
+
end
|
259
|
+
end
|
260
|
+
get "/user/1/project"
|
261
|
+
assert_equal "index 1", body
|
262
|
+
get "/user/1/project/edit/2"
|
263
|
+
assert_equal "edit 2 1", body
|
264
|
+
get "/user/1/product/2/project/show/3"
|
265
|
+
assert_equal "show 3 1 2", body
|
266
|
+
|
267
|
+
end
|
268
|
+
|
269
|
+
should "apply parent to controller" do
|
270
|
+
mock_app do
|
271
|
+
controller :project, :parent => :user do
|
272
|
+
get(:index) { "index #{params[:user_id]}"}
|
273
|
+
get(:edit, :with => :id, :parent => :user) { "edit #{params[:id]} #{params[:user_id]}"}
|
274
|
+
get(:show, :with => :id, :parent => :product) { "show #{params[:id]} #{params[:user_id]} #{params[:product_id]}"}
|
275
|
+
end
|
276
|
+
end
|
277
|
+
get "/user/1/project"
|
278
|
+
assert_equal "index 1", body
|
279
|
+
get "/user/1/project/edit/2"
|
280
|
+
assert_equal "edit 2 1", body
|
281
|
+
get "/user/1/product/2/project/show/3"
|
282
|
+
assert_equal "show 3 1 2", body
|
283
|
+
end
|
284
|
+
|
285
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: padrino-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Padrino Team
|
@@ -12,7 +12,7 @@ autorequire:
|
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
14
|
|
15
|
-
date: 2010-02-
|
15
|
+
date: 2010-02-23 00:00:00 -08:00
|
16
16
|
default_executable: padrino
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
@@ -63,7 +63,7 @@ dependencies:
|
|
63
63
|
requirements:
|
64
64
|
- - "="
|
65
65
|
- !ruby/object:Gem::Version
|
66
|
-
version: 0.9.
|
66
|
+
version: 0.9.7
|
67
67
|
version:
|
68
68
|
- !ruby/object:Gem::Dependency
|
69
69
|
name: activesupport
|
@@ -71,7 +71,7 @@ dependencies:
|
|
71
71
|
version_requirement:
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
73
73
|
requirements:
|
74
|
-
- - "
|
74
|
+
- - "="
|
75
75
|
- !ruby/object:Gem::Version
|
76
76
|
version: 2.3.5
|
77
77
|
version:
|
@@ -133,6 +133,9 @@ files:
|
|
133
133
|
- bin/padrino
|
134
134
|
- lib/padrino-core.rb
|
135
135
|
- lib/padrino-core/application.rb
|
136
|
+
- lib/padrino-core/application/mounter.rb
|
137
|
+
- lib/padrino-core/application/rendering.rb
|
138
|
+
- lib/padrino-core/application/routing.rb
|
136
139
|
- lib/padrino-core/caller.rb
|
137
140
|
- lib/padrino-core/cli/adapter.rb
|
138
141
|
- lib/padrino-core/cli/base.rb
|
@@ -145,7 +148,6 @@ files:
|
|
145
148
|
- lib/padrino-core/locale/en.yml
|
146
149
|
- lib/padrino-core/locale/it.yml
|
147
150
|
- lib/padrino-core/logger.rb
|
148
|
-
- lib/padrino-core/mounter.rb
|
149
151
|
- lib/padrino-core/reloader.rb
|
150
152
|
- lib/padrino-core/server.rb
|
151
153
|
- lib/padrino-core/support_lite.rb
|