padrino-core 0.5.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 Padrino
1
+ Copyright (c) 2010 Padrino
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.rdoc CHANGED
@@ -1,18 +1,81 @@
1
1
  = padrino-core
2
2
 
3
+ Padrino is the godfather of Sinatra.
4
+
5
+ == Preface
6
+
7
+ Padrino is a ruby framework build upon the {Sinatra Microframework}[http://www.sinatrarb.com].
8
+
9
+ Sinatra is a DSL for quickly creating web applications in Ruby with minimal effort.
10
+
11
+ The extreme simplicity of this framework is quite refreshing. We have been using Sinatra a great deal
12
+ for recent projects. First for small and simple json and xml web services and then even
13
+ for more complex full-featured applications.
14
+
15
+ This gem represents an attempt to make it as fun and easy as possible to code increasingly advanced web applications in Sinatra.
16
+
17
+ == Introduction
18
+
19
+ Many people love Sinatra's simplicity and lightweight but often quickly come to miss a great deal
20
+ of functionality provided by other web frameworks such as Rails when building non-trivial applications.
21
+
22
+ The obvious question in these cases might be "Why not just use rails then?". This can often be a viable option
23
+ but still Rails is quite a large framework with a 'take it or leave it' attitude.
24
+
25
+ Personally, we have come to love the philosophy of Sinatra which acts as a thin layer on top of rack
26
+ often allowing middleware to do most of the work and pulling in additional complexity only when required.
27
+
28
+ Our goal with this framework is to match the essence of Sinatra and at the same time create a standard library
29
+ of tools, helpers and components that will make Sinatra suitable for more complex applications.
30
+
31
+ Here is a small list of what Padrino provides:
32
+
33
+ Generators:: for creating new padrino applications i.e.: <tt>padrino-gen app</tt> or <tt>padrino start</tt> on command line
34
+ MultiApp:: unlike other ruby frameworks Padrino is principally designed for mounting multiple apps at the same time.
35
+ Routing:: Full url named route, named params, respond_to suppor
36
+ Tag Helpers:: helpers such as: <tt>tag</tt>, <tt>content_tag</tt>, <tt>input_tag</tt>, ...
37
+ Asset Helpers:: helpers such as: <tt>link_to</tt>, <tt>image_tag</tt>, <tt>javascript_include_tag</tt>, ...
38
+ Form Helpers:: with builder support such as: <tt>form_tag</tt>, <tt>form_for</tt>, <tt>field_set_tag</tt>, <tt>text_field</tt>, ...
39
+ Text Helpers:: useful formatting extensions like: <tt>relative_time_ago</tt>, <tt>js_escape_html</tt>, <tt>sanitize_html</tt>
40
+ Mailer:: fast, tiny, delivery support for send templating emails (like ActionMailer do)
41
+ Admin:: an ajax admin that displays your records in sortable grids, tree, windows ... as a desktop app can do.
42
+ Logging:: Padrino provide a logger that can interact with your orm or any other library
43
+ Reloading:: With padrino is not necessary like other framework start and restart your server for see changes.
44
+ I18n:: Padrino has a full support of I18n and can autoset locale.
45
+
46
+ Keep in mind, the user will be able to pull in these components seperately and leave out those that are not required
47
+ or use them altogether for a comprehensive upgrade to Sinatra (a full-stack Padrino application).
48
+
49
+ Note that all work has been created to be compatible with haml, erb, and erubis and that this gem is intended to be
50
+ template-agnostic in providing helpers wherever possible.
51
+
52
+ Please help me brainstorm and fork the project if you have any ideas to contribute.
53
+
3
54
  == Installation
4
55
 
5
- To install the 'full-stack' padrino framework, simply grab the latest version from gemcutter:
56
+ To install the padrino framework, simply grab the latest version from gemcutter:
6
57
 
7
58
  $ sudo gem install padrino --source http://gemcutter.org
8
59
 
9
60
  This will install the necessary padrino gems to get you started.
10
- Now you are ready to use this gem to enhance your existing Sinatra projects or build new Padrino applications.
61
+ Now you are ready to use this gem to enhance your sinatra projects or to create new Padrino applications.
11
62
 
12
63
  == Usage
13
64
 
14
- For a comprehensive overview of the whole padrino-framework, check out the
15
- {Padrino Framework README}[http://github.com/padrino/padrino-framework/blob/master/README.rdoc]
65
+ Padrino is a framework which builds on the existing functionality and Sinatra and provides a variety of
66
+ additional tools and helpers to extend the foundation. This README and Padrino documentation in general will focus
67
+ on the enhancements to the core Sinatra functionality. To use Padrino, one should be familiar with the basic
68
+ usage of Sinatra itself. Resources for Sinatra are listed below:
69
+
70
+ * {Sinatra Introduction}[http://www.sinatrarb.com/intro.html]
71
+ * {Sinatra Book}[http://www.sinatrarb.com/book.html]
72
+ * {Sinatra Github Repo}[http://github.com/sinatra/sinatra]
73
+
74
+ Below is a guide to how this gem enhances the Sinatra framework as part of a 'full-stack' padrino application.
75
+ For information on how to use a specific gem in isolation within an existing Sinatra project, checkout the README for that
76
+ individual gem or gems.
77
+
78
+ == Enhanced Base Application (padrino-core)
16
79
 
17
80
  Sinatra has support for classes which can be extended to create an application: <tt>Sinatra::Base</tt> and <tt>Sinatra::Application</tt>
18
81
  These classes can be extended in order to create a Sinatra web application. These classes provide support for all the basic
@@ -35,11 +98,170 @@ Let us first take a look at the simplest possible Padrino application:
35
98
  Padrino.load!
36
99
 
37
100
  class SimpleApp < Padrino::Application
38
- get '/ do
101
+ get '/' do
39
102
  'Hello world'
40
103
  end
104
+
105
+ # and for read better we can divide with controllers
106
+ controller '/admin' do
107
+ get '/foo' do
108
+ 'Im /admin/foo
109
+ end
110
+ end
41
111
  end
42
-
112
+
113
+ === Controllers
114
+
115
+ Suppose we wanted to add additional routes to our Padrino application, and we want to organize the routes
116
+ within a more structured layout. Simply add a <tt>controllers</tt> or <tt>app/controllers</tt> folder and create a file as such:
117
+
118
+ # Simple Example
119
+ SimpleApp.controllers do
120
+ get "/test" do
121
+ "Text to return"
122
+ end
123
+ end
124
+
125
+ == Advanced Routing Support
126
+
127
+ Padrino provides support for advanced routing functionality not available within Sinatra. This routing
128
+ supports named route aliases and easy access to url paths. The benefits of this is that instead of having to
129
+ hard-code route urls into every area of your application, now we can just define the urls in a
130
+ single spot and then attach an alias which can be used to refer to the url throughout the application.
131
+
132
+ === Padrino Routing
133
+
134
+ Urls mapped here can then be defined within a controller:
135
+
136
+ # app/controllers/example.rb
137
+ SimpleApp.controllers do
138
+ get :index do
139
+ ...
140
+ end
141
+
142
+ get :account do
143
+ # access params[:name] and params[:index]
144
+ end
145
+ end
146
+
147
+ and finally referenced anywhere in the application:
148
+
149
+ # app/views/example.haml
150
+ = link_to "Index", url_for(:index)
151
+ = link_to "Account", url_for(:account, :id => 1, :name => 'first')
152
+
153
+ === Inline Route Alias Definitions
154
+
155
+ The routing plugin also supports inline route definitions in which the url and the named alias
156
+ are defined together within the controller:
157
+
158
+ # app/controllers/example.rb
159
+ SimpleApp.controllers do
160
+ get :index, :map => '/index' do
161
+ ...
162
+ end
163
+
164
+ get :account, :map => '/the/accounts/:name/and/:id' do
165
+ # access params[:name] and params[:index]
166
+ end
167
+ end
168
+
169
+ Routes defined inline this way can be accessed and treated the same way as traditional named aliases.
170
+
171
+ === Namespaced Route Aliases
172
+
173
+ There is also support for namespaced routes which are organized into a larger grouping:
174
+
175
+ # app/controllers/example.rb
176
+ SimpleApp.controllers :admin do
177
+ get :show do
178
+ "Im /admin/show"
179
+ end
180
+
181
+ get :index, :map => "/admin/:id" do
182
+ "Im /admin/#{params[:id]}"
183
+ end
184
+ end
185
+
186
+ You can then reference the urls using the same url_for method:
187
+
188
+ <%= link_to 'admin show page', url_for(:admin_show, :id => 25) %>
189
+ <%= link_to 'admin index page', url_for(:admin_index, :id => 25) %>
190
+
191
+ If you don't want named routes you can
192
+
193
+ # app/controllers/example.rb
194
+ SimpleApp.controllers "/admin" do
195
+ get "/show" do
196
+ "Im /admin/show"
197
+ end
198
+
199
+ get "other/:id" do
200
+ "Im /admin/#{params[:id]}"
201
+ end
202
+ end
203
+
204
+ === Named Params
205
+
206
+ With Padrino you can use named params!! See these examples
207
+
208
+ # app/controllers/example.rb
209
+ SimpleApp.controllers :admin do
210
+ get :show, :with => :id do
211
+ "Im /admin/show/#{params[:id]}"
212
+ end
213
+
214
+ get :other, with => [:id, :name] do
215
+ "Im /admin/#{params[:id]}/#{params[:name]}"
216
+ end
217
+ end
218
+
219
+ You can then reference the urls using the same url_for method:
220
+
221
+ <%= link_to 'admin show page', url_for(:admin_show, :id => 25) %>
222
+ <%= link_to 'admin other page', url_for(:admin_index, :id => 25, :name => :foo) %>
223
+
224
+ === Respond To
225
+
226
+ With Padrino you can simply respond to a given format see example:
227
+
228
+ # app/controllers/example.rb
229
+ SimpleApp.controllers :admin do
230
+ get :show, :with => :id, :respond_to => :js do
231
+ "Im /admin/show/#{params[:id]}.#{params[:format]}"
232
+ end
233
+
234
+ get :other, with => [:id, :name], respond_to => [:html, :json] do
235
+ case content_type
236
+ when :js then ... end
237
+ when :json then ... end
238
+ end
239
+ end
240
+ end
241
+
242
+ <%= link_to 'admin show page', url_for(:admin_show, :id => 25, :format => :js) %>
243
+ <%= link_to 'admin other page', url_for(:admin_index, :id => 25, :name => :foo) %>
244
+ <%= link_to 'admin other json page', url_for(:admin_index, :id => 25, :name => :foo, :format => :json) %>
245
+
246
+ === Rendering
247
+
248
+ Unlike Sinatra Padrino support template auto lookup so:
249
+
250
+ # look for 'account/index.{erb,haml,...}
251
+ render 'account/index'
252
+
253
+ === Layout
254
+
255
+ With Padrino you can (like rails do) use for your custom layout, disable it
256
+
257
+ class SimpleApp < Padrino::Application
258
+
259
+ # Disable layouts
260
+ disable layout
261
+
262
+ # Use the layout located in views/layouts/custom.haml
263
+ layout :custom
264
+
43
265
  === Gemfile Dependency Resolution
44
266
 
45
267
  While this is a fully operational Padrino application in itself, let us take a look at Padrino's expanded capabilites. First,
@@ -97,18 +319,6 @@ directory following this convention:
97
319
  Initializers are automatically required and 'registered' during the application startup process. Note that
98
320
  the name of the module must be the name of the file appended with 'Initializer' (i.e sample.rb => SampleInitializer)
99
321
 
100
- === Controllers
101
-
102
- Suppose we wanted to add additional routes to our Padrino application, and we want to organize the routes
103
- within a more structured layout. Simply add a <tt>controllers</tt> or <tt>app/controllers</tt> folder and create a file as such:
104
-
105
- # controllers/example.rb
106
- SimpleApp.controllers do
107
- get "/test" do
108
- "Text to return"
109
- end
110
- end
111
-
112
322
  === Application Logging
113
323
 
114
324
  Padrino also supports robust logging capabilities. By default, logging information will
@@ -200,8 +410,11 @@ The following commands are available:
200
410
  # Bootup the Padrino console (irb)
201
411
  $ padrino console
202
412
 
413
+ # Run/List tasks
414
+ $ padrino rake
415
+
203
416
  Using these commands can simplify common tasks making development that much smoother.
204
417
 
205
418
  == Copyright
206
419
 
207
- Copyright (c) 2009 Padrino. See LICENSE for details.
420
+ Copyright (c) 2010 Padrino. See LICENSE for details.
data/Rakefile CHANGED
@@ -13,6 +13,7 @@ begin
13
13
  gem.executables = ["padrino"]
14
14
  gem.add_runtime_dependency "sinatra", ">= 0.9.2"
15
15
  gem.add_runtime_dependency "i18n", ">= 0.3.2"
16
+ gem.add_runtime_dependency "usher", ">= 0.6.2"
16
17
  gem.add_runtime_dependency "thor", ">= 0.11.8"
17
18
  gem.add_development_dependency "haml", ">= 2.2.1"
18
19
  gem.add_runtime_dependency "bundler", ">= 0.5.0"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.0
1
+ 0.6.1
data/bin/padrino CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  %w[rubygems thor].each { |gem| require gem }
3
- require File.dirname(__FILE__) + "/../lib/padrino-core/tasks"
3
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../lib"
4
4
 
5
+ require "padrino-core/cli"
5
6
  arguments = ARGV.any? ? ARGV : ['-h']
6
- Padrino::Tasks::Base.start(arguments)
7
+ Padrino::Cli::Base.start(arguments)
data/lib/padrino-core.rb CHANGED
@@ -1,4 +1,6 @@
1
+ require 'usher'
1
2
  require 'sinatra/base'
3
+
2
4
  Dir[File.dirname(__FILE__) + '/padrino-core/*.rb'].each {|file| require file }
3
5
 
4
6
  # Defines our PADRINO_ENV
@@ -4,12 +4,47 @@ module Padrino
4
4
  # These subclassed applications can be easily mounted into other Padrino applications as well.
5
5
  class Application < Sinatra::Application
6
6
 
7
+ # Return the request format, this is useful when we need to respond to a given content_type like:
8
+ #
9
+ # get :index, :respond_to => :any do
10
+ # case content_type
11
+ # when :js then ...
12
+ # when :json then ...
13
+ # when :html then ...
14
+ # end
15
+ # end
16
+ def content_type(type=nil, params={})
17
+ type.nil? ? @_content_type : super(type, params)
18
+ end
19
+
20
+
21
+ # Instance method for url generation like:
22
+ #
23
+ # url(:show, :id => 1)
24
+ # url(:show, :name => :test)
25
+ # url("/show/:id/:name", :id => 1, :name => foo)
26
+ #
27
+ def url(name, *params)
28
+ self.class.url(name, *params)
29
+ end
30
+ alias :url_for :url
31
+
32
+ # This is mostly just a helper so request.path_info isn't changed when
33
+ # serving files from the public directory
34
+ def static_file?(path)
35
+ public_dir = File.expand_path(options.public)
36
+ path = File.expand_path(File.join(public_dir, unescape(path)))
37
+ path[0, public_dir.length] == public_dir && File.file?(path)
38
+ end
39
+
7
40
  class << self
8
41
  def inherited(subclass)
9
42
  CALLERS_TO_IGNORE.concat(PADRINO_IGNORE_CALLERS)
10
43
  subclass.default_configuration!
44
+ Padrino.require_dependencies(File.join(subclass.root, "/models/**/*.rb"))
11
45
  super # Loading the subclass
12
- subclass.register Padrino::Routing if defined?(Padrino::Routing)
46
+ subclass.default_filters!
47
+ subclass.default_routes!
13
48
  end
14
49
 
15
50
  # Hooks into when a new instance of the application is created
@@ -21,12 +56,67 @@ module Padrino
21
56
  super
22
57
  end
23
58
 
24
- # Makes the routes defined in the block and in the Modules given
25
- # in `extensions` available to the application
26
- def controllers(*extensions, &block)
27
- instance_eval(&block) if block_given?
28
- include(*extensions) if extensions.any?
59
+ # Method for organize in a better way our routes like:
60
+ #
61
+ # controller :admin do
62
+ # get :index do; ...; end
63
+ # get :show, :with => :id do; ...; end
64
+ # end
65
+ #
66
+ # Now you can call your actions with:
67
+ #
68
+ # url(:admin_index) # => "/admin"
69
+ # url(:admin_show, :id => 1) # "/admin/show/1"
70
+ #
71
+ # You can instead using named routes follow the sinatra way like:
72
+ #
73
+ # controller "/admin" do
74
+ # get "/index" do; ...; end
75
+ # get "/show/:id" do; ...; end
76
+ # end
77
+ #
78
+ # And you can call directly these urls:
79
+ #
80
+ # # => "/admin"
81
+ # # => "/admin/show/1"
82
+ #
83
+ def controller(*extensions, &block)
84
+ if block_given?
85
+ @_controller, original = extensions, @_controller
86
+ instance_eval(&block)
87
+ @_controller = original
88
+ else
89
+ include(*extensions) if extensions.any?
90
+ end
91
+ end
92
+ alias :controllers :controller
93
+
94
+ # Usher router
95
+ def router
96
+ @router ||= Usher.new(:request_methods => [:request_method, :host, :port, :scheme],
97
+ :ignore_trailing_delimiters => true,
98
+ :generator => Usher::Util::Generators::URL.new)
99
+ block_given? ? yield(@router) : @router
100
+ end
101
+ alias :urls :router
102
+
103
+ # Instance method for url generation like:
104
+ #
105
+ # url(:show, :id => 1)
106
+ # url(:show, :name => :test)
107
+ # url("/show/:id/:name", :id => 1, :name => foo)
108
+ #
109
+ def url(name, *params)
110
+ params.map! do |param|
111
+ if param.is_a?(Hash)
112
+ param[:format] = param[:format].to_s if param.has_key?(:format)
113
+ param.each { |k,v| param[k] = v.to_param if v.respond_to?(:to_param) }
114
+ end
115
+ end
116
+ url = router.generator.generate(name, *params)
117
+ uri_root != "/" ? uri_root + url : url
29
118
  end
119
+ alias :url_for :url
30
120
 
31
121
  # With this method we can use layout like rails do or if a block given like sinatra
32
122
  # By default we look in your/app/views/layouts/application.(haml|erb|etc)
@@ -50,7 +140,8 @@ module Padrino
50
140
 
51
141
  # Resets application routes to only routes not defined by the user
52
142
  def reset_routes!
53
- @routes = Padrino::Application.respond_to?(:dupe_routes) ? Padrino::Application.dupe_routes : {}
143
+ router.reset!
144
+ default_routes!
54
145
  end
55
146
 
56
147
  # Setup the application by registering initializers, load paths and logger
@@ -64,7 +155,6 @@ module Padrino
64
155
  self.disable :logging # We need do that as default because Sinatra use commonlogger.
65
156
  I18n.locale = self.locale
66
157
  I18n.load_path += self.translations
67
- self.get(""){ redirect("#{options.uri_root}/") } if self.uri_root != "/"
68
158
  @_configured = true
69
159
  end
70
160
 
@@ -93,6 +183,25 @@ module Padrino
93
183
  set :padrino_helpers, defined?(Padrino::Helpers)
94
184
  end
95
185
 
186
+ def default_routes!
187
+ # images resources
188
+ get "/__sinatra__/:image.png" do
189
+ filename = File.dirname(__FILE__) + "/images/#{params[:image]}.png"
190
+ send_file filename
191
+ end
192
+ end
193
+
194
+ # This filter it's used for know the format of the request, and automatically set the content type.
195
+ def default_filters!
196
+ before do
197
+ unless options.static? && options.public? && (request.get? || request.head?) && static_file?(request.path_info)
198
+ request.path_info =~ /\.([^\.\/]+)$/
199
+ @_content_type = ($1 || :html).to_sym
200
+ content_type(@_content_type) rescue content_type('application/octet-stream')
201
+ end
202
+ end
203
+ end
204
+
96
205
  # Calculates any required paths after app_file and root have been properly configured
97
206
  # Executes as part of the setup_application! method
98
207
  def calculate_paths
@@ -111,7 +220,7 @@ module Padrino
111
220
  Dir[@initializer_path].each { |file| register_initializer(file) }
112
221
  end
113
222
 
114
- # Registers all desired padrino extension helpers/routing
223
+ # Registers all desired padrino extension helpers
115
224
  def register_framework_extensions
116
225
  register Padrino::Mailer if padrino_mailer?
117
226
  register Padrino::Helpers if padrino_helpers?
@@ -120,7 +229,7 @@ module Padrino
120
229
 
121
230
  # Returns the load_paths for the application (relative to the application root)
122
231
  def load_paths
123
- @load_paths ||= ["urls.rb", "config/urls.rb", "models/*.rb", "mailers/*.rb", "controllers/**/*.rb", "helpers/*.rb"]
232
+ @load_paths ||= ["urls.rb", "config/urls.rb", "mailers/*.rb", "controllers/**/*.rb", "helpers/*.rb"]
124
233
  end
125
234
 
126
235
  # Requires all files within the application load paths
@@ -144,15 +253,172 @@ module Padrino
144
253
  logger.error "The module '#{file_class}Initializer' (#{file_path}) didn't loaded properly!"
145
254
  logger.error " Initializer error was '#{e.message}'"
146
255
  end
147
- end
256
+
257
+ private
258
+ # Rewrite default because now routes can be:
259
+ #
260
+ # get :index # => "/"
261
+ # get :index, :map => "/" # => "/"
262
+ # get :show, :map => "/show-me" # => "/show-me"
263
+ # get "/foo/bar" # => "/show"
264
+ # get :show, :with => :id # => "/show/:id"
265
+ # get :show, :with => [:id, :name] # => "/show/:id/:name"
266
+ # get :list, :respond_to => :js # => "/list.{:format,js)"
267
+ # get :list, :respond_to => :any # => "/list(.:format)"
268
+ # get :list, :respond_to => [:js, :json] # => "/list.{!format,js|json}"
269
+ # gen :list, :respond_to => [:html, :js, :json] # => "/list(.{!format,js|json})"
270
+ #
271
+ def route(verb, path, options={}, &block)
272
+
273
+ # We dup options so we can build HEAD request correctly
274
+ options = options.dup
275
+
276
+ # We need check if path is a symbol, if that it's a named route
277
+ map = options.delete(:map)
278
+
279
+ if path.kind_of?(Symbol)
280
+ name = path # The route name
281
+ path = map || "/#{path}" # The route path
282
+ end
283
+
284
+ if path.kind_of?(String)
285
+ # Little reformats
286
+ path.sub!(/\/index$/, "") # If the route end with /index we remove them
287
+ path = (uri_root == "/" ? "/" : "(/)") if path.blank? # Add a trailing delimiter if empty
288
+
289
+ # Now we need to parse our with params
290
+ if params = options.delete(:with)
291
+ path += "/" unless path =~ /\/$/
292
+ path += Array(params).collect(&:inspect).join("/")
293
+ end
294
+
295
+ # Now we need to parse our respond_to
296
+ if format = options.delete(:respond_to)
297
+ path += case format
298
+ when :any then "(.:format)"
299
+ when Array then
300
+ formats = format.dup # Prevent changes to HEAD verb
301
+ container = formats.delete(:html) ? "(%s)" : "%s"
302
+ match = ".{:format," + formats.collect { |f| "#{f}$" }.join("|") + "}"
303
+ container % match
304
+ else ".{:format,#{format}}"
305
+ end
306
+ end
307
+
308
+ # Build our controller
309
+ controller = Array(@_controller).collect(&:to_s)
310
+
311
+ unless controller.empty?
312
+ # Now we need to add our controller path only if not mapped directly
313
+ if map.blank?
314
+ controller_path = controller.join("/")
315
+ path = controller_path + path
316
+ end
317
+ # Here we build the correct name route
318
+ if name
319
+ controller_name = controller.join("_")
320
+ name = "#{controller_name}_#{name}".to_sym unless controller_name.blank?
321
+ end
322
+ end
323
+
324
+ # We need to have a path that start with / in some circumstances and that don't end with /
325
+ if path != "(/)" && path != "/"
326
+ path = "/" + path if path !~ /^\//
327
+ path.sub!(/\/$/, '')
328
+ end
329
+ end
330
+
331
+ # Standard Sinatra requirements
332
+ options[:conditions] ||= {}
333
+ options[:conditions][:request_method] = verb
334
+ options[:conditions][:host] = options.delete(:host) if options.key?(:host)
335
+
336
+ # Because of self.options.host
337
+ host_name(options.delete(:host)) if options.key?(:host)
338
+
339
+ # Sinatra defaults
340
+ define_method "\#{verb} \#{path}", &block
341
+ unbound_method = instance_method("\#{verb} \#{path}")
342
+ block =
343
+ if block.arity != 0
344
+ lambda { unbound_method.bind(self).call(*@block_params) }
345
+ else
346
+ lambda { unbound_method.bind(self).call }
347
+ end
348
+
349
+ invoke_hook(:route_added, verb, path, block)
350
+
351
+ route = router.add_route(path, options).to(block)
352
+ route.name(name) if name
353
+ route
354
+ end
355
+
356
+ end
148
357
 
149
358
  private
359
+ # TODO: remove this when sinatra 1.0 will be released
360
+ # Compatibility with sinatra 0.9.4
361
+ def static!
362
+ return if (public_dir = options.public).nil?
363
+ public_dir = File.expand_path(public_dir)
364
+
365
+ path = File.expand_path(public_dir + unescape(request.path_info))
366
+ return if path[0, public_dir.length] != public_dir
367
+ return unless File.file?(path)
368
+
369
+ send_file path, :disposition => nil
370
+ end
371
+
372
+ # Compatibility with usher
373
+ def route!(base=self.class, pass_block=nil)
374
+ # TODO: remove this when sinatra 1.0 will be released
375
+ if Sinatra::VERSION =~ /^0\.9/
376
+ # enable nested params in Rack < 1.0; allow indifferent access
377
+ @params = if Rack::Utils.respond_to?(:parse_nested_query)
378
+ indifferent_params(@request.params)
379
+ else
380
+ nested_params(@request.params)
381
+ end
382
+ # deliver static files
383
+ static! if options.static? && (request.get? || request.head?)
384
+ # perform before filters
385
+ self.class.filters.each { |block| instance_eval(&block) }
386
+ end
387
+
388
+ # Usher
389
+ if self.class.router and match = self.class.router.recognize(@request, @request.path_info)
390
+ @block_params = match.params.map{|p| p.last}
391
+ @params = @params ? @params.merge(match.params_as_hash) : match.params_as_hash
392
+ pass_block = catch(:pass) do
393
+ route_eval(&match.destination)
394
+ end
395
+ elsif base.superclass.respond_to?(:routes)
396
+ route! base.superclass
397
+ else
398
+ route_missing
399
+ end
400
+ end
401
+
402
+ # When we set :auto_locale, true then:
403
+ #
404
+ # * if we pass "/:locale/some/foo" we automatically set teh I18n locale to params[:locale]
405
+ # * if params[:locale] is empty we use the first HTTP_ACCEPT_LANGUAGE
406
+ def route_eval(&block)
407
+ if options.auto_locale
408
+ if params[:locale]
409
+ I18n.locale = params[:locale].to_sym rescue options.locale
410
+ end
411
+ end
412
+ super
413
+ end
414
+
150
415
  # Hijacking the sinatra render for do two thing:
151
416
  #
152
417
  # * Use layout like rails do
153
418
  # * Use render 'path/to/my/template'
154
419
  #
155
420
  def render(engine, data=nil, options={}, locals={}, &block)
421
+ # TODO: remove these @template_cache.respond_to?(:clear) when sinatra 1.0 will be released
156
422
  @template_cache.clear if Padrino.env != :production && @template_cache && @template_cache.respond_to?(:clear)
157
423
  # If an engine is a string probably is a path so we try to resolve them
158
424
  if data.nil?
@@ -178,18 +444,6 @@ module Padrino
178
444
  raise "Template path '#{template_path}' could not be located in views!" unless template_file
179
445
  template_engine = File.extname(template_file)[1..-1].to_sym
180
446
  end
181
-
182
- # When we set :auto_locale, true then:
183
- #
184
- # * if we pass "/:locale/some/foo" we automatically set teh I18n locale to params[:locale]
185
- # * if params[:locale] is empty we use the first HTTP_ACCEPT_LANGUAGE
186
- def route_eval(&block)
187
- if options.auto_locale
188
- if params[:locale]
189
- I18n.locale = params[:locale].to_sym rescue options.locale
190
- end
191
- end
192
- super
193
- end
194
447
  end
448
+
195
449
  end