padrino-core 0.8.5 → 0.9.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.
- 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
|