padrino-core 0.9.19 → 0.9.20

Sign up to get free protection for your applications and to get access to all the features.
data/lib/padrino-core.rb CHANGED
@@ -40,7 +40,15 @@ module Padrino
40
40
  raise ApplicationLoadError, "At least one app must be mounted!" unless self.mounted_apps && self.mounted_apps.any?
41
41
  router = Padrino::Router.new
42
42
  self.mounted_apps.each { |app| app.map_onto(router) }
43
- router
43
+
44
+ unless middleware.empty?
45
+ builder = Rack::Builder.new
46
+ middleware.each { |c,a,b| builder.use(c, *a, &b) }
47
+ builder.run(router)
48
+ builder.to_app
49
+ else
50
+ router
51
+ end
44
52
  end
45
53
 
46
54
  ##
@@ -75,5 +83,27 @@ module Padrino
75
83
  return :locked if File.exist?(root('.bundle/environment.rb'))
76
84
  return :unlocked if File.exist?(root("Gemfile"))
77
85
  end
86
+
87
+ ##
88
+ # A Rack::Builder object that allows to add middlewares in front of all
89
+ # Padrino applications
90
+ #
91
+ def middleware
92
+ @middleware ||= []
93
+ end
94
+
95
+ ##
96
+ # Clears all previously configured middlewares
97
+ #
98
+ def clear_middleware!
99
+ @middleware = []
100
+ end
101
+
102
+ ##
103
+ # Convenience method for adding a Middleware to the whole padrino app.
104
+ #
105
+ def use(m, *args, &block)
106
+ middleware << [m, args, block]
107
+ end
78
108
  end # self
79
109
  end # Padrino
@@ -92,7 +92,7 @@ module Padrino
92
92
  self.default_routes!
93
93
  self.default_errors!
94
94
  if defined?(I18n)
95
- I18n.load_path += self.locale_path
95
+ I18n.load_path << self.locale_path
96
96
  I18n.reload!
97
97
  end
98
98
  @_configured = true
@@ -150,6 +150,7 @@ module Padrino
150
150
  def default_routes!
151
151
  configure :development do
152
152
  get '/__sinatra__/:image.png' do
153
+ content_type :png
153
154
  filename = File.dirname(__FILE__) + "/images/#{params[:image]}.png"
154
155
  send_file filename
155
156
  end
@@ -132,7 +132,7 @@ module Padrino
132
132
  # => "/layouts/custom"
133
133
  #
134
134
  def resolved_layout
135
- located_layout = resolve_template(settings.fetch_layout_path, :strict_format => true, :raise_exceptions => false)
135
+ located_layout = resolve_template(settings.fetch_layout_path, :raise_exceptions => false)
136
136
  located_layout ? located_layout[0] : false
137
137
  end
138
138
 
@@ -63,10 +63,15 @@ module Padrino
63
63
  end
64
64
 
65
65
  def route
66
- match.matched? ? match.path.route : nil
66
+ if match.nil?
67
+ path = Rack::Utils.unescape(path_info)
68
+ path.empty? ? "/" : path
69
+ else
70
+ match.path.route
71
+ end
67
72
  end
68
- end
69
- end
73
+ end # Request
74
+ end # Sinatra
70
75
 
71
76
  class UnrecognizedException < RuntimeError #:nodoc:
72
77
  end
@@ -501,7 +506,9 @@ module Padrino
501
506
  request.path_info =~ /\.([^\.\/]+)$/
502
507
  url_format = $1.to_sym if $1
503
508
 
504
- if !url_format && matching_types.first
509
+ if params[:format]
510
+ accept_format = params[:format]
511
+ elsif !url_format && matching_types.first
505
512
  type = ::Rack::Mime::MIME_TYPES.find { |k, v| v == matching_types.first }[0].sub(/\./,'').to_sym
506
513
  accept_format = CONTENT_TYPE_ALIASES[type] || type
507
514
  end
@@ -585,29 +592,31 @@ module Padrino
585
592
  def route!(base=self.class, pass_block=nil)
586
593
  base.router.runner = self
587
594
  if base.router and match = base.router.recognize(@request)
588
- if !match.matched?
589
- route_eval do
590
- match.headers.each {|k,v| response[k] = v}
591
- status match.status
595
+ if match.first.respond_to?(:path)
596
+ match.each do |matched_path|
597
+ request.match = matched_path
598
+ @block_params = matched_path.param_values
599
+ (@params ||= {}).merge!(matched_path.params)
600
+ pass_block = catch(:pass) do
601
+ # If present set current controller layout
602
+ parent_layout = base.instance_variable_get(:@layout)
603
+ base.instance_variable_set(:@layout, matched_path.path.route.use_layout) if matched_path.path.route.use_layout
604
+ # Provide access to the current controller to the request
605
+ # Now we can eval route, but because we have "throw halt" we need to be
606
+ # (en)sure to reset old layout and run controller after filters.
607
+ begin
608
+ @_response_buffer = catch(:halt) { route_eval(&matched_path.path.route.dest) }
609
+ throw :halt, @_response_buffer
610
+ ensure
611
+ base.instance_variable_set(:@layout, parent_layout) if matched_path.path.route.use_layout
612
+ matched_path.path.route.after_filters.each { |aft| throw :pass if instance_eval(&aft) == false } if matched_path.path.route.after_filters
613
+ end
614
+ end
592
615
  end
593
616
  elsif match
594
- @block_params = match.params
595
- (@params ||= {}).merge!(match.params_as_hash)
596
- pass_block = catch(:pass) do
597
- # If present set current controller layout
598
- parent_layout = base.instance_variable_get(:@layout)
599
- base.instance_variable_set(:@layout, match.path.route.use_layout) if match.path.route.use_layout
600
- # Provide access to the current controller to the request
601
- request.match = match
602
- # Now we can eval route, but because we have "throw halt" we need to be
603
- # (en)sure to reset old layout and run controller after filters.
604
- begin
605
- @_response_buffer = catch(:halt) { route_eval(&match.destination) }
606
- throw :halt, @_response_buffer
607
- ensure
608
- base.instance_variable_set(:@layout, parent_layout) if match.path.route.use_layout
609
- match.path.route.after_filters.each { |aft| throw :pass if instance_eval(&aft) == false } if match.path.route.after_filters
610
- end
617
+ route_eval do
618
+ match[1].each {|k,v| response[k] = v}
619
+ status match[0]
611
620
  end
612
621
  end
613
622
  end
@@ -624,4 +633,4 @@ module Padrino
624
633
  end
625
634
  end # InstanceMethods
626
635
  end # Routing
627
- end # Padrino
636
+ end # Padrino
@@ -1,22 +1,22 @@
1
1
  module Padrino
2
2
  PADRINO_IGNORE_CALLERS = [
3
- %r{lib/padrino-.*$}, # all padrino code
4
- %r{/padrino-.*/(lib|bin)}, # all padrino code
5
- %r{/bin/padrino$}, # all padrino code
6
- %r{/sinatra(/(base|main|showexceptions))?\.rb$}, # all sinatra code
7
- %r{lib/tilt.*\.rb$}, # all tilt code
8
- %r{lib/rack.*\.rb$}, # all rack code
9
- %r{lib/mongrel.*\.rb$}, # all mongrel code
10
- %r{lib/shotgun.*\.rb$}, # all shotgun lib
11
- %r{bin/shotgun$}, # shotgun binary
12
- %r{\(.*\)}, # generated code
13
- %r{shoulda/context\.rb$}, # shoulda hacks
14
- %r{mocha/integration}, # mocha hacks
15
- %r{test/unit}, # test unit hacks
16
- %r{rake_test_loader\.rb}, # rake hacks
17
- %r{custom_require\.rb$}, # rubygems require hacks
18
- %r{active_support}, # active_support require hacks
19
- %r{/thor}, # thor require hacks
3
+ %r{lib/padrino-.*$}, # all padrino code
4
+ %r{/padrino-.*/(lib|bin)}, # all padrino code
5
+ %r{/bin/padrino$}, # all padrino code
6
+ %r{/sinatra(/(base|main|showexceptions))?\.rb$}, # all sinatra code
7
+ %r{lib/tilt.*\.rb$}, # all tilt code
8
+ %r{lib/rack.*\.rb$}, # all rack code
9
+ %r{lib/mongrel.*\.rb$}, # all mongrel code
10
+ %r{lib/shotgun.*\.rb$}, # all shotgun lib
11
+ %r{bin/shotgun$}, # shotgun binary
12
+ %r{\(.*\)}, # generated code
13
+ %r{shoulda/context\.rb$}, # shoulda hacks
14
+ %r{mocha/integration}, # mocha hacks
15
+ %r{test/unit}, # test unit hacks
16
+ %r{rake_test_loader\.rb}, # rake hacks
17
+ %r{custom_require\.rb$}, # rubygems require hacks
18
+ %r{active_support}, # active_support require hacks
19
+ %r{/thor} # thor require hacks
20
20
  ] unless defined?(PADRINO_IGNORE_CALLERS)
21
21
 
22
22
  ##
@@ -170,4 +170,4 @@ module Padrino
170
170
  $:.uniq!
171
171
  end
172
172
  end # self
173
- end # Padrino
173
+ end # Padrino
@@ -97,9 +97,25 @@ module Padrino
97
97
  def ==(other)
98
98
  other.is_a?(Mounter) && self.app_class == other.app_class && self.uri_root == other.uri_root
99
99
  end
100
-
100
+
101
+ ##
102
+ # Returns the class object for the app if defined, nil otherwise
103
+ #
104
+ def app_constant
105
+ klass = Object
106
+ for piece in app_class.split("::")
107
+ piece = piece.to_sym
108
+ if klass.const_defined?(piece)
109
+ klass = klass.const_get(piece)
110
+ else
111
+ return
112
+ end
113
+ end
114
+ klass
115
+ end
116
+
101
117
  protected
102
-
118
+
103
119
  ##
104
120
  # Locates and requires the file to load the app constant
105
121
  #
@@ -122,14 +138,7 @@ module Padrino
122
138
  candidates << Padrino.root("app", "app.rb")
123
139
  candidates.find { |candidate| File.exist?(candidate) }
124
140
  end
125
-
126
- ##
127
- # Returns the class object for the app if defined, nil otherwise
128
- #
129
- def app_constant
130
- app_class.constantize if Object.const_defined?(app_class)
131
- end
132
-
141
+
133
142
  ###
134
143
  # Raises an exception unless app_file is located properly
135
144
  #
@@ -137,7 +146,7 @@ module Padrino
137
146
  message = "Unable to locate source file for app '#{name}', try with :app_file => '/path/app.rb'"
138
147
  raise MounterException, message unless @app_file
139
148
  end
140
-
149
+
141
150
  ###
142
151
  # Raises an exception unless app_obj is defined properly
143
152
  #
@@ -171,23 +180,6 @@ module Padrino
171
180
  Padrino.mounted_apps.push(mounter) unless Padrino.mounted_apps.include?(mounter)
172
181
  end
173
182
 
174
- ##
175
- # Mounts the core application onto Padrino project with given app settings (file, class, root)
176
- #
177
- # ==== Examples
178
- #
179
- # Padrino.mount_core("Blog")
180
- # Padrino.mount_core(:app_file => "/path/to/file", :app_class => "Blog")
181
- #
182
- def mount_core(*args)
183
- # TODO Remove this in 0.9.14 or pre 1.0
184
- warn "DEPRECATION! #{Padrino.first_caller}: Padrino.mount_core has been deprecated.\nUse Padrino.mount('AppName').to('/') instead"
185
- options = args.extract_options!
186
- app_class = args.size > 0 ? args.first.to_s.camelize : nil
187
- options.reverse_merge!(:app_class => app_class)
188
- mount("core", options).to("/")
189
- end
190
-
191
183
  ##
192
184
  # Mounts a new sub-application onto Padrino project
193
185
  #
@@ -74,6 +74,7 @@ module Padrino
74
74
  # Reload all files with changes detected.
75
75
  #
76
76
  def reload!
77
+ # Detect changed files
77
78
  rotation do |file, mtime|
78
79
  # Retrive the last modified time
79
80
  new_file = MTIMES[file].nil?
@@ -253,4 +254,4 @@ module Padrino
253
254
  end # self
254
255
  end # Stat
255
256
  end # Reloader
256
- end # Padrino
257
+ end # Padrino
@@ -75,5 +75,5 @@ module Padrino
75
75
  end
76
76
  [404, {"Content-Type" => "text/plain", "X-Cascade" => "pass"}, ["Not Found: #{rPath}"]]
77
77
  end
78
- end
79
- end
78
+ end # Router
79
+ end # Padrino
@@ -71,4 +71,4 @@ module Padrino
71
71
  raise LoadError, "Server handler (#{servers.join(',')}) not found."
72
72
  end
73
73
  end # Server
74
- end # Padrino
74
+ end # Padrino
@@ -109,4 +109,4 @@ end unless defined?(FileSet)
109
109
  ##
110
110
  # Loads our locales configuration files
111
111
  #
112
- I18n.load_path += Dir["#{File.dirname(__FILE__)}/locale/*.yml"] if defined?(I18n)
112
+ I18n.load_path += Dir["#{File.dirname(__FILE__)}/locale/*.yml"] if defined?(I18n)
@@ -5,7 +5,7 @@
5
5
  # without include full padrino core.
6
6
  #
7
7
  module Padrino
8
- VERSION = '0.9.19' unless defined?(Padrino::VERSION)
8
+ VERSION = '0.9.20' unless defined?(Padrino::VERSION)
9
9
  ##
10
10
  # Return the current Padrino version
11
11
  #
data/padrino-core.gemspec CHANGED
@@ -18,8 +18,8 @@ Gem::Specification.new do |s|
18
18
  s.rdoc_options = ["--charset=UTF-8"]
19
19
  s.require_path = "lib"
20
20
  s.add_dependency("sinatra", ">= 1.1.0")
21
- s.add_dependency("http_router", "~> 0.4.0")
21
+ s.add_dependency("http_router", "~> 0.5.0")
22
22
  s.add_dependency("thor", ">=0.14.3")
23
23
  s.add_dependency("activesupport", ">= 3.0.0")
24
24
  s.add_dependency("tzinfo")
25
- end
25
+ end
@@ -14,6 +14,7 @@ end
14
14
  class Complex2Demo < Padrino::Application
15
15
  set :reload, true
16
16
  get("/old"){ "Old Sinatra Way" }
17
+ get("/"){ "The magick number is: 12!" } # Change only the number!!!
17
18
  end
18
19
 
19
20
  Complex1Demo.controllers do
@@ -21,7 +22,6 @@ Complex1Demo.controllers do
21
22
  end
22
23
 
23
24
  Complex2Demo.controllers do
24
- get("/"){ "The magick number is: 16!" } # Change only the number!!!
25
25
  end
26
26
 
27
27
  Padrino.load!
data/test/test_core.rb CHANGED
@@ -1,6 +1,10 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/helper')
2
2
 
3
3
  class TestCore < Test::Unit::TestCase
4
+ def teardown
5
+ Padrino.clear_middleware!
6
+ end
7
+
4
8
  context 'for core functionality' do
5
9
 
6
10
  should 'check some global methods' do
@@ -36,5 +40,24 @@ class TestCore < Test::Unit::TestCase
36
40
  Padrino.mounted_apps.clear
37
41
  assert_raise(Padrino::ApplicationLoadError) { Padrino.application.new }
38
42
  end
43
+
44
+ should "add middlewares in front if specified" do
45
+ test = Class.new {
46
+ def initialize(app)
47
+ @app = app
48
+ end
49
+
50
+ def call(env)
51
+ status, headers, body = @app.call(env)
52
+ headers["Middleware-Called"] = "yes"
53
+ return status, headers, body
54
+ end
55
+ }
56
+
57
+ Padrino.use(test)
58
+
59
+ res = Rack::MockRequest.new(Padrino.application).get("/")
60
+ assert_equal "yes", res["Middleware-Called"]
61
+ end
39
62
  end
40
63
  end
data/test/test_mounter.rb CHANGED
@@ -38,6 +38,15 @@ class TestMounter < Test::Unit::TestCase
38
38
  assert_equal AnApp, Padrino.mounted_apps.first.app_obj
39
39
  assert_equal ["an_app"], Padrino.mounted_apps.collect(&:name)
40
40
  end
41
+
42
+ should 'correctly mount an app in a namespace' do
43
+ module ::SomeNamespace
44
+ class AnApp < Padrino::Application; end
45
+ end
46
+ Padrino.mount("some_namespace/an_app").to("/")
47
+ assert_equal SomeNamespace::AnApp, Padrino.mounted_apps.first.app_obj
48
+ assert_equal ["some_namespace/an_app"], Padrino.mounted_apps.collect(&:name)
49
+ end
41
50
 
42
51
  should 'mount a primary app to root uri' do
43
52
  mounter = Padrino.mount("test", :app_file => __FILE__).to("/")
@@ -159,4 +168,4 @@ class TestMounter < Test::Unit::TestCase
159
168
  assert_equal File.read(__FILE__), res.body
160
169
  end
161
170
  end
162
- end
171
+ end
@@ -32,13 +32,13 @@ class TestSimpleReloader < Test::Unit::TestCase
32
32
  assert_equal 200, status
33
33
  get "/__sinatra__/404.png"
34
34
  assert_equal 200, status
35
- assert_equal "image/png;charset=utf-8", response["Content-Type"]
35
+ assert_match /image\/png/, response["Content-Type"]
36
36
  @app.reset_routes!
37
37
  get "/"
38
38
  assert_equal 404, status
39
39
  get "/__sinatra__/404.png"
40
40
  assert_equal 200, status
41
- assert_equal "image/png;charset=utf-8", response["Content-Type"]
41
+ assert_match /image\/png/, response["Content-Type"]
42
42
  end
43
43
  end
44
44
 
@@ -93,4 +93,4 @@ class TestSimpleReloader < Test::Unit::TestCase
93
93
  assert_equal 0, @app.templates.size
94
94
  end
95
95
  end
96
- end
96
+ end
data/test/test_routing.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/helper')
2
2
 
3
+ class FooError < RuntimeError; end
4
+
5
+
3
6
  class TestRouting < Test::Unit::TestCase
4
7
  should 'ignore trailing delimiters for basic route' do
5
8
  mock_app do
@@ -255,7 +258,7 @@ class TestRouting < Test::Unit::TestCase
255
258
  assert_equal "bar", body
256
259
  assert_equal "/bar", @app.url(:bar)
257
260
  end
258
-
261
+
259
262
  should 'remove index from path' do
260
263
  mock_app do
261
264
  get(:index){ "index" }
@@ -512,8 +515,8 @@ class TestRouting < Test::Unit::TestCase
512
515
  end
513
516
 
514
517
  should 'apply maps when given path is kind of hash' do
515
- mock_app do
516
- controllers :admin do
518
+ mock_app do
519
+ controllers :admin do
517
520
  get(:foobar, "/foo/bar"){ "foobar" }
518
521
  end
519
522
  end
@@ -564,9 +567,9 @@ class TestRouting < Test::Unit::TestCase
564
567
  assert_equal "show 3 1 2", body
565
568
  assert_equal user_product_project_url, @app.url(:project, :show, :user_id => 1, :product_id => 2, :id => 3)
566
569
  end
567
-
568
- should "apply parent with shallowing to controller" do
569
- mock_app do
570
+
571
+ should "apply parent with shallowing to controller" do
572
+ mock_app do
570
573
  controller :project do
571
574
  parent :user
572
575
  parent :shop, :optional => true
@@ -575,7 +578,7 @@ class TestRouting < Test::Unit::TestCase
575
578
  get(:show, :with => :id, :parent => :product) { "show #{params[:id]} #{params[:user_id]} #{params[:product_id]} #{params[:shop_id]}" }
576
579
  end
577
580
  end
578
-
581
+
579
582
  assert_equal "/user/1/project", @app.url(:project, :index, :user_id => 1, :shop_id => nil)
580
583
  assert_equal "/user/1/shop/23/project", @app.url(:project, :index, :user_id => 1, :shop_id => 23)
581
584
 
@@ -609,15 +612,15 @@ class TestRouting < Test::Unit::TestCase
609
612
  assert_equal "show 3 1 2 1", body
610
613
  assert_equal user_product_project_url, @app.url(:project, :show, :user_id => 1, :product_id => 2, :id => 3, :shop_id => 1)
611
614
  end
612
-
613
- should "respect map in parents with shallowing" do
614
- mock_app do
615
+
616
+ should "respect map in parents with shallowing" do
617
+ mock_app do
615
618
  controller :project do
616
619
  parent :shop, :map => "/foo/bar"
617
620
  get(:index) { "index #{params[:shop_id]}" }
618
621
  end
619
622
  end
620
-
623
+
621
624
  shop_project_url = "/foo/bar/1/project"
622
625
  get shop_project_url
623
626
  assert_equal "index 1", body
@@ -916,7 +919,7 @@ class TestRouting < Test::Unit::TestCase
916
919
 
917
920
  should 'be able to access params in a before filter' do
918
921
  username_from_before_filter = nil
919
-
922
+
920
923
  mock_app do
921
924
  before do
922
925
  username_from_before_filter = params[:username]
@@ -1137,4 +1140,29 @@ class TestRouting < Test::Unit::TestCase
1137
1140
  post @app.url(:posts, :create, :format => :js, :bar => 'bar', :baz => 'baz', :id => 5)
1138
1141
  assert_equal "POST CREATE bar - baz - 5", body, "should properly post to create action"
1139
1142
  end
1143
+
1144
+ should "have overideable format" do
1145
+ mock_app do
1146
+ ::Rack::Mime::MIME_TYPES[".other"] = "text/html"
1147
+ before do
1148
+ params[:format] ||= :other
1149
+ end
1150
+ get("/format_test", :provides => [:html, :other]){ content_type.to_s }
1151
+ end
1152
+ get "/format_test"
1153
+ assert_equal "other", body
1154
+ end
1155
+
1156
+ should 'invokes handlers registered with ::error when raised' do
1157
+ mock_app do
1158
+ set :raise_errors, false
1159
+ error(FooError) { 'Foo!' }
1160
+ get '/' do
1161
+ raise FooError
1162
+ end
1163
+ end
1164
+ get '/'
1165
+ assert_equal 500, status
1166
+ assert_equal 'Foo!', body
1167
+ end
1140
1168
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: padrino-core
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 9
9
- - 19
10
- version: 0.9.19
9
+ - 20
10
+ version: 0.9.20
11
11
  platform: ruby
12
12
  authors:
13
13
  - Padrino Team
@@ -18,7 +18,7 @@ autorequire:
18
18
  bindir: bin
19
19
  cert_chain: []
20
20
 
21
- date: 2010-11-17 00:00:00 +01:00
21
+ date: 2011-01-19 00:00:00 -08:00
22
22
  default_executable: padrino
23
23
  dependencies:
24
24
  - !ruby/object:Gem::Dependency
@@ -45,12 +45,12 @@ dependencies:
45
45
  requirements:
46
46
  - - ~>
47
47
  - !ruby/object:Gem::Version
48
- hash: 15
48
+ hash: 11
49
49
  segments:
50
50
  - 0
51
- - 4
51
+ - 5
52
52
  - 0
53
- version: 0.4.0
53
+ version: 0.5.0
54
54
  type: :runtime
55
55
  version_requirements: *id002
56
56
  - !ruby/object:Gem::Dependency
@@ -115,7 +115,6 @@ files:
115
115
  - Rakefile
116
116
  - padrino-core.gemspec
117
117
  - bin/padrino
118
- - lib/padrino-core/application/mounter.rb
119
118
  - lib/padrino-core/application/rendering.rb
120
119
  - lib/padrino-core/application/routing.rb
121
120
  - lib/padrino-core/application/showexceptions.rb
@@ -144,6 +143,7 @@ files:
144
143
  - lib/padrino-core/locale/tr.yml
145
144
  - lib/padrino-core/locale/uk.yml
146
145
  - lib/padrino-core/logger.rb
146
+ - lib/padrino-core/mounter.rb
147
147
  - lib/padrino-core/reloader.rb
148
148
  - lib/padrino-core/router.rb
149
149
  - lib/padrino-core/server.rb