padrino-core 0.18.1 → 0.18.2
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.
- checksums.yaml +4 -4
- data/lib/padrino-core/application/routing.rb +12 -11
- data/lib/padrino-core/caller.rb +11 -8
- data/lib/padrino-core/cli/base.rb +4 -2
- data/lib/padrino-core/path_router/route.rb +15 -0
- data/lib/padrino-core/version.rb +1 -1
- data/padrino-core.gemspec +7 -3
- data/test/test_caller.rb +104 -0
- data/test/test_cli.rb +59 -0
- data/test/test_routing.rb +351 -0
- metadata +11 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bf357f68006699d9e80fa024da18fbf0b64bd7d0365ea2ecfd90c12b0b8a6cfa
|
|
4
|
+
data.tar.gz: f702562744c51a4dee46da71739b7864ba3ebc1c9c937ddb8d5af3a07efc391c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 140423832026779eb7731e1145ab1d6d7b7197bf77e85d83c40077f639bcbc3fc0f7ee4ed2bedaee35a6b9b1188ae8ce9437e09fb605c17c605abfbf413c7383
|
|
7
|
+
data.tar.gz: ea73969e005298405dd22072d18a211634d038a68e53b7c3b9cfead7d29b2471eb06f30b723702f50fa00ab331cdb1a5bc29cbdc98449be874629e91dab50e05
|
|
@@ -417,25 +417,25 @@ module Padrino
|
|
|
417
417
|
|
|
418
418
|
# Saves controller options, yields the block, restores controller options.
|
|
419
419
|
def with_new_options(*args)
|
|
420
|
+
original = {}
|
|
420
421
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
|
421
422
|
|
|
422
|
-
CONTROLLER_OPTIONS.each { |key| replace_instance_variable("@_#{key}", options.delete(key)) }
|
|
423
|
-
replace_instance_variable(:@_controller, args)
|
|
424
|
-
replace_instance_variable(:@_defaults, options)
|
|
425
|
-
replace_instance_variable(:@filters, before: @filters[:before].dup, after: @filters[:after].dup)
|
|
426
|
-
replace_instance_variable(:@layout, @layout)
|
|
423
|
+
CONTROLLER_OPTIONS.each { |key| replace_instance_variable(original, "@_#{key}", options.delete(key)) }
|
|
424
|
+
replace_instance_variable(original, :@_controller, args)
|
|
425
|
+
replace_instance_variable(original, :@_defaults, options)
|
|
426
|
+
replace_instance_variable(original, :@filters, before: @filters[:before].dup, after: @filters[:after].dup)
|
|
427
|
+
replace_instance_variable(original, :@layout, @layout)
|
|
427
428
|
|
|
428
429
|
yield
|
|
429
|
-
|
|
430
|
-
|
|
430
|
+
ensure
|
|
431
|
+
original.each do |key, value|
|
|
431
432
|
instance_variable_set(key, value)
|
|
432
433
|
end
|
|
433
434
|
end
|
|
434
435
|
|
|
435
|
-
# Sets instance variable by name and saves the original value in
|
|
436
|
-
def replace_instance_variable(name, value)
|
|
437
|
-
|
|
438
|
-
@original_instance[name] = instance_variable_get(name)
|
|
436
|
+
# Sets instance variable by name and saves the original value in the given hash
|
|
437
|
+
def replace_instance_variable(original, name, value)
|
|
438
|
+
original[name] = instance_variable_get(name)
|
|
439
439
|
instance_variable_set(name, value)
|
|
440
440
|
end
|
|
441
441
|
|
|
@@ -1019,6 +1019,7 @@ module Padrino
|
|
|
1019
1019
|
(route.before_filters - settings.filters[:before]).each { |block| instance_eval(&block) }
|
|
1020
1020
|
@layout = route.use_layout if route.use_layout
|
|
1021
1021
|
route.custom_conditions.each { |block| pass if block.bind(self).call == false }
|
|
1022
|
+
env['sinatra.route'] = "#{@request.request_method} #{route.sinatra_pattern}"
|
|
1022
1023
|
route_response = route.block[self, captured_params]
|
|
1023
1024
|
@_response_buffer = route_response.instance_of?(Array) ? route_response.last : route_response
|
|
1024
1025
|
halt(route_response)
|
data/lib/padrino-core/caller.rb
CHANGED
|
@@ -4,19 +4,22 @@ module Padrino
|
|
|
4
4
|
PADRINO_IGNORE_CALLERS = [
|
|
5
5
|
*Sinatra::Base.callers_to_ignore, # Inherit Sinatra's default ignore patterns
|
|
6
6
|
Regexp.new(Regexp.escape(RbConfig::CONFIG['rubylibdir'])), # Ignore the Ruby standard lib path
|
|
7
|
-
%r{lib/padrino
|
|
8
|
-
%r{/padrino
|
|
7
|
+
%r{/lib/padrino-(admin|cache|core|gen|helpers|mailer|performance|support)/},
|
|
8
|
+
%r{/lib/padrino/(core_ext/|rendering/|rendering\.rb$|safe_buffer\.rb$)},
|
|
9
|
+
%r{/lib/padrino(-[^/]+)?\.rb$},
|
|
10
|
+
%r{/padrino-[^/]+/(lib|bin)/},
|
|
9
11
|
%r{/bin/padrino$},
|
|
10
|
-
%r{lib/rack
|
|
11
|
-
%r{lib/mongrel
|
|
12
|
-
%r{lib/shotgun
|
|
12
|
+
%r{/lib/rack(up)?(\.rb$|/)},
|
|
13
|
+
%r{/lib/mongrel(\.rb$|/)},
|
|
14
|
+
%r{/lib/shotgun(\.rb$|/)},
|
|
13
15
|
%r{bin/shotgun$},
|
|
14
16
|
%r{shoulda/context\.rb$},
|
|
15
|
-
%r{mocha/integration},
|
|
16
|
-
%r{test/unit},
|
|
17
|
+
%r{/lib/mocha/integration(\.rb$|/)},
|
|
18
|
+
%r{/lib/test/unit(\.rb$|/)},
|
|
17
19
|
/rake_test_loader\.rb/,
|
|
18
20
|
/custom_require\.rb$/,
|
|
19
|
-
%r{/thor}
|
|
21
|
+
%r{/lib/thor(\.rb$|/)},
|
|
22
|
+
%r{/bin/thor$}
|
|
20
23
|
]
|
|
21
24
|
|
|
22
25
|
##
|
|
@@ -62,8 +62,10 @@ module Padrino
|
|
|
62
62
|
ARGV.shift
|
|
63
63
|
ARGV << 'help' if ARGV.empty?
|
|
64
64
|
exit 1 unless Padrino.bin_gen(*ARGV)
|
|
65
|
-
rescue
|
|
66
|
-
|
|
65
|
+
rescue LoadError => e
|
|
66
|
+
raise unless (e.path || e.message[/-- (\S+)\z/, 1]) == 'padrino-gen/command'
|
|
67
|
+
|
|
68
|
+
abort "<= padrino g needs padrino-gen. Add gem 'padrino-gen' to your Gemfile and run bundle install, or run: gem install padrino-gen"
|
|
67
69
|
end
|
|
68
70
|
|
|
69
71
|
desc 'version', 'Show current Padrino version.'
|
|
@@ -55,6 +55,20 @@ module Padrino
|
|
|
55
55
|
@path
|
|
56
56
|
end
|
|
57
57
|
|
|
58
|
+
##
|
|
59
|
+
# Returns the pattern as Sinatra writes it in env['sinatra.route']. Sinatra
|
|
60
|
+
# stringifies a Regexp through Mustermann, which drops the (?-mix:) wrapper.
|
|
61
|
+
# The root route is stored as an empty path; Sinatra names it "/".
|
|
62
|
+
#
|
|
63
|
+
def sinatra_pattern
|
|
64
|
+
@sinatra_pattern ||=
|
|
65
|
+
if @path.is_a?(Regexp)
|
|
66
|
+
Mustermann.new(@path, check_anchors: false).to_s
|
|
67
|
+
else
|
|
68
|
+
@path.to_s.empty? ? '/' : @path.to_s
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
58
72
|
SIGNIFICANT_VARIABLES_REGEX = /(^|[^\\])[:*]([a-zA-Z0-9_]+)/
|
|
59
73
|
|
|
60
74
|
##
|
|
@@ -111,6 +125,7 @@ module Padrino
|
|
|
111
125
|
def path=(pattern)
|
|
112
126
|
@path = pattern
|
|
113
127
|
@matcher = nil
|
|
128
|
+
@sinatra_pattern = nil
|
|
114
129
|
@significant_variable_names = nil
|
|
115
130
|
end
|
|
116
131
|
|
data/lib/padrino-core/version.rb
CHANGED
data/padrino-core.gemspec
CHANGED
|
@@ -6,17 +6,21 @@ Gem::Specification.new do |s|
|
|
|
6
6
|
s.authors = ['Padrino Team', 'Nathan Esquenazi', "Davide D'Agostino", 'Arthur Chiu']
|
|
7
7
|
s.email = 'padrinorb@gmail.com'
|
|
8
8
|
s.summary = 'The required Padrino core gem'
|
|
9
|
-
s.homepage = '
|
|
9
|
+
s.homepage = 'https://padrinorb.com'
|
|
10
10
|
s.description = 'The Padrino core gem required for use of this framework'
|
|
11
11
|
s.required_ruby_version = '>= 2.7.8'
|
|
12
12
|
s.required_rubygems_version = '>= 1.3.6'
|
|
13
13
|
s.version = Padrino.version
|
|
14
|
-
s.date = Time.now.strftime('%Y-%m-%d')
|
|
15
14
|
s.license = 'MIT'
|
|
15
|
+
s.metadata = {
|
|
16
|
+
'bug_tracker_uri' => 'https://github.com/padrino/padrino-framework/issues',
|
|
17
|
+
'changelog_uri' => 'https://github.com/padrino/padrino-framework/blob/master/CHANGES.rdoc',
|
|
18
|
+
'documentation_uri' => 'https://padrinorb.com/guides/',
|
|
19
|
+
'source_code_uri' => 'https://github.com/padrino/padrino-framework'
|
|
20
|
+
}
|
|
16
21
|
|
|
17
22
|
s.extra_rdoc_files = Dir['*.rdoc']
|
|
18
23
|
s.files = `git ls-files`.split("\n")
|
|
19
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
20
24
|
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
|
21
25
|
s.require_paths = ['lib']
|
|
22
26
|
s.rdoc_options = ['--charset=UTF-8']
|
data/test/test_caller.rb
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
require_relative 'helper'
|
|
2
|
+
require 'tmpdir'
|
|
3
|
+
|
|
4
|
+
describe 'PADRINO_IGNORE_CALLERS' do
|
|
5
|
+
def ignored?(file)
|
|
6
|
+
Padrino::PADRINO_IGNORE_CALLERS.any? { |pattern| file =~ pattern }
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
gems = '/usr/lib/ruby/gems/4.0.0/gems'
|
|
10
|
+
|
|
11
|
+
[
|
|
12
|
+
"#{gems}/padrino-0.18.1/lib/padrino.rb",
|
|
13
|
+
"#{gems}/padrino-core-0.18.1/lib/padrino-core/application.rb",
|
|
14
|
+
"#{gems}/padrino-helpers-0.18.1/lib/padrino/rendering.rb",
|
|
15
|
+
"#{gems}/padrino-helpers-0.18.1/lib/padrino/rendering/erb_template.rb",
|
|
16
|
+
"#{gems}/padrino-helpers-0.18.1/lib/padrino/safe_buffer.rb",
|
|
17
|
+
"#{gems}/padrino-helpers-0.18.1/lib/padrino/core_ext/output_safety.rb",
|
|
18
|
+
"#{gems}/padrino-gen-0.18.1/bin/padrino-gen",
|
|
19
|
+
"#{gems}/padrino-contrib-0.3.0/lib/padrino-contrib/helpers/flash.rb",
|
|
20
|
+
'/home/me/.bundle/gems/padrino-framework-abc123/padrino-core/lib/padrino-core/mounter.rb',
|
|
21
|
+
'/home/me/.gem/bin/padrino',
|
|
22
|
+
'/srv/vendor/core/lib/padrino-core/application/application_setup.rb',
|
|
23
|
+
'/srv/vendor/core/lib/padrino-core.rb',
|
|
24
|
+
"#{gems}/acme-padrino-core-1.0/lib/padrino-core/mounter.rb",
|
|
25
|
+
'/home/me/.bundle/gems/fork-abc123/padrino-helpers/lib/padrino/rendering.rb',
|
|
26
|
+
"#{gems}/padrino-performance-0.18.1/lib/suites/json.rb",
|
|
27
|
+
"#{gems}/acme/lib/padrino-acme.rb",
|
|
28
|
+
"#{gems}/padrino-foo-1.0/lib/foo.rb",
|
|
29
|
+
"#{gems}/puma-6.4/lib/rack/handler/puma.rb",
|
|
30
|
+
"#{gems}/thor-1.5.0/lib/thor.rb",
|
|
31
|
+
"#{gems}/thor-1.5.0/lib/thor/base.rb",
|
|
32
|
+
"#{gems}/thor-1.5.0/bin/thor",
|
|
33
|
+
"#{gems}/rack-3.2.8/lib/rack.rb",
|
|
34
|
+
"#{gems}/rack-3.2.8/lib/rack/builder.rb",
|
|
35
|
+
"#{gems}/rack-protection-4.2.1/lib/rack/protection/base.rb",
|
|
36
|
+
"#{gems}/rack-session-2.1.2/lib/rack/session/cookie.rb",
|
|
37
|
+
"#{gems}/rackup-2.3.1/lib/rackup/server.rb",
|
|
38
|
+
"#{gems}/shotgun-0.9/lib/shotgun/loader.rb",
|
|
39
|
+
"#{gems}/shotgun-0.9/bin/shotgun",
|
|
40
|
+
"#{gems}/mongrel-1.1/lib/mongrel/http_response.rb",
|
|
41
|
+
"#{gems}/mocha-3.1.0/lib/mocha/integration/mini_test.rb",
|
|
42
|
+
"#{gems}/test-unit-3.6/lib/test/unit/testcase.rb",
|
|
43
|
+
"#{gems}/test-unit-3.6/lib/test/unit.rb",
|
|
44
|
+
"#{gems}/mocha-3.1.0/lib/mocha/integration.rb"
|
|
45
|
+
].each do |file|
|
|
46
|
+
it "should ignore the library file #{file}" do
|
|
47
|
+
assert ignored?(file), "#{file} should be ignored"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
%w[
|
|
52
|
+
/home/thor/demo/app/app.rb
|
|
53
|
+
/srv/thor-apps/demo/app/app.rb
|
|
54
|
+
/srv/lib/padrino-blog/demo/app/app.rb
|
|
55
|
+
/srv/demo/bin/padrino-worker
|
|
56
|
+
/srv/padrino-demo/app/app.rb
|
|
57
|
+
/srv/lib/rack-app/demo/app/app.rb
|
|
58
|
+
/srv/lib/rack_demo/demo/app/app.rb
|
|
59
|
+
/srv/lib/mongrel-demo/app/app.rb
|
|
60
|
+
/srv/lib/shotgun-demo/app/app.rb
|
|
61
|
+
/srv/test/unit/demo/app/app.rb
|
|
62
|
+
/srv/mocha/integration/demo/app/app.rb
|
|
63
|
+
/srv/demo/app/thor_helpers.rb
|
|
64
|
+
/srv/lib/padrino/rendering-blog/app/app.rb
|
|
65
|
+
/srv/lib/padrino/safe_buffer_demo.rb
|
|
66
|
+
/srv/lib/padrino/core_extras/app/app.rb
|
|
67
|
+
/srv/lib/test/unit-app/app/app.rb
|
|
68
|
+
/srv/lib/mocha/integration-demo/app/app.rb
|
|
69
|
+
].each do |file|
|
|
70
|
+
it "should keep the application file #{file}" do
|
|
71
|
+
refute ignored?(file), "#{file} should not be ignored"
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
%w[thor-apps lib/padrino-blog lib/rack-app test/unit].each do |parent|
|
|
76
|
+
it "should find the application file of an app under #{parent}" do
|
|
77
|
+
Dir.mktmpdir do |dir|
|
|
78
|
+
app_file = File.join(dir, parent, 'demo', 'app', 'app.rb')
|
|
79
|
+
FileUtils.mkdir_p(File.dirname(app_file))
|
|
80
|
+
File.write(app_file, "Class.new(Padrino::Application) { $caller_test_app = self }\n")
|
|
81
|
+
begin
|
|
82
|
+
load app_file
|
|
83
|
+
assert_equal File.realpath(app_file), File.realpath($caller_test_app.app_file)
|
|
84
|
+
ensure
|
|
85
|
+
$caller_test_app = nil
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'should keep the first caller for a file under a matching directory' do
|
|
92
|
+
Dir.mktmpdir do |dir|
|
|
93
|
+
file = File.join(dir, 'thor-apps', 'boot.rb')
|
|
94
|
+
FileUtils.mkdir_p(File.dirname(file))
|
|
95
|
+
File.write(file, "$caller_test_file = Padrino.first_caller\n")
|
|
96
|
+
begin
|
|
97
|
+
load file
|
|
98
|
+
assert_equal File.realpath(file), File.realpath($caller_test_file)
|
|
99
|
+
ensure
|
|
100
|
+
$caller_test_file = nil
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
data/test/test_cli.rb
CHANGED
|
@@ -81,6 +81,65 @@ describe 'Padrino::Cli' do
|
|
|
81
81
|
refute_includes err, "add gem 'irb'"
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
+
it 'should say how to add padrino-gen when padrino g cannot load it' do
|
|
85
|
+
_, err, status = run_in_project(<<~RUBY)
|
|
86
|
+
# A bundle without padrino-gen
|
|
87
|
+
module Kernel
|
|
88
|
+
alias_method :require_before_test, :require
|
|
89
|
+
def require(name)
|
|
90
|
+
if name == 'padrino-gen/command'
|
|
91
|
+
error = LoadError.new('cannot load such file -- padrino-gen/command')
|
|
92
|
+
error.define_singleton_method(:path) { 'padrino-gen/command' }
|
|
93
|
+
raise error
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
require_before_test(name)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
require 'padrino-core/cli/base'
|
|
100
|
+
Padrino::Cli::Base.start(['g', 'controller', 'demo'])
|
|
101
|
+
RUBY
|
|
102
|
+
assert_equal 1, status.exitstatus
|
|
103
|
+
assert_includes err, "Add gem 'padrino-gen' to your Gemfile"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it 'should say how to add padrino-gen when the LoadError has no path' do
|
|
107
|
+
_, err, status = run_in_project(<<~RUBY)
|
|
108
|
+
module Kernel
|
|
109
|
+
alias_method :require_before_test, :require
|
|
110
|
+
def require(name)
|
|
111
|
+
if name == 'padrino-gen/command'
|
|
112
|
+
error = LoadError.new('cannot load such file -- padrino-gen/command')
|
|
113
|
+
error.define_singleton_method(:path) { nil }
|
|
114
|
+
raise error
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
require_before_test(name)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
require 'padrino-core/cli/base'
|
|
121
|
+
Padrino::Cli::Base.start(['g', 'controller', 'demo'])
|
|
122
|
+
RUBY
|
|
123
|
+
assert_equal 1, status.exitstatus
|
|
124
|
+
assert_includes err, "Add gem 'padrino-gen' to your Gemfile"
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it 'should not hide a LoadError from inside padrino-gen in padrino g' do
|
|
128
|
+
_, err, status = run_in_project(<<~RUBY)
|
|
129
|
+
module Kernel
|
|
130
|
+
alias_method :require_before_test, :require
|
|
131
|
+
def require(name)
|
|
132
|
+
require_before_test(name == 'padrino-gen/command' ? 'padrino_missing_gen_dependency' : name)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
require 'padrino-core/cli/base'
|
|
136
|
+
Padrino::Cli::Base.start(['g', 'controller', 'demo'])
|
|
137
|
+
RUBY
|
|
138
|
+
refute status.success?
|
|
139
|
+
assert_includes err, 'padrino_missing_gen_dependency'
|
|
140
|
+
refute_includes err, "Add gem 'padrino-gen'"
|
|
141
|
+
end
|
|
142
|
+
|
|
84
143
|
it 'should load the models in the rake environment task after a skeleton task' do
|
|
85
144
|
out, err, status = run_in_project(<<~RUBY)
|
|
86
145
|
require 'rake'
|
data/test/test_routing.rb
CHANGED
|
@@ -980,6 +980,137 @@ describe 'Routing' do
|
|
|
980
980
|
assert_equal 'foo_bar_index', body
|
|
981
981
|
end
|
|
982
982
|
|
|
983
|
+
it 'should not give routes defined after a nested controller block the outer controller options' do
|
|
984
|
+
mock_app do
|
|
985
|
+
get(:early) { 'early' }
|
|
986
|
+
controller :admin, provides: :json, conditions: { agent: /Admin/ } do
|
|
987
|
+
before { response['x-outer'] = 'admin' }
|
|
988
|
+
after { response['x-outer-after'] = 'admin' }
|
|
989
|
+
controller :posts do
|
|
990
|
+
before { response['x-inner'] = 'posts' }
|
|
991
|
+
get(:index) { 'posts' }
|
|
992
|
+
end
|
|
993
|
+
get(:show) { 'show' }
|
|
994
|
+
end
|
|
995
|
+
get(:top) { 'top' }
|
|
996
|
+
end
|
|
997
|
+
get '/posts'
|
|
998
|
+
assert_equal 'posts', body
|
|
999
|
+
assert_equal 'admin', response['x-outer']
|
|
1000
|
+
assert_equal 'posts', response['x-inner']
|
|
1001
|
+
get '/admin/show', {}, 'HTTP_USER_AGENT' => 'Admin'
|
|
1002
|
+
assert_equal 'show', body
|
|
1003
|
+
assert_equal 'admin', response['x-outer']
|
|
1004
|
+
assert_nil response['x-inner']
|
|
1005
|
+
assert_match %r{^application/json}, response['Content-Type']
|
|
1006
|
+
get '/admin/show'
|
|
1007
|
+
assert_equal 404, status
|
|
1008
|
+
get '/top'
|
|
1009
|
+
assert_equal 200, status
|
|
1010
|
+
assert_equal 'top', body
|
|
1011
|
+
assert_nil response['x-outer']
|
|
1012
|
+
assert_nil response['x-outer-after']
|
|
1013
|
+
assert_match %r{^text/html}, response['Content-Type']
|
|
1014
|
+
assert_equal '/top', @app.url(:top)
|
|
1015
|
+
get '/early'
|
|
1016
|
+
assert_equal 'early', body
|
|
1017
|
+
assert_nil response['x-outer']
|
|
1018
|
+
assert_nil response['x-outer-after']
|
|
1019
|
+
get '/admin/top', {}, 'HTTP_USER_AGENT' => 'Admin'
|
|
1020
|
+
assert_equal 404, status
|
|
1021
|
+
end
|
|
1022
|
+
|
|
1023
|
+
it 'should not give routes defined after a nested controller block the outer map, layout or default values' do
|
|
1024
|
+
mock_app do
|
|
1025
|
+
controller :admin, map: '/manage', lang: 'en' do
|
|
1026
|
+
@layout = :admin_layout # what padrino-helpers' `layout :admin_layout` sets
|
|
1027
|
+
controller(:posts) { get(:index) { 'posts' } }
|
|
1028
|
+
get(:show) { 'show' }
|
|
1029
|
+
end
|
|
1030
|
+
get(:top) { 'top' }
|
|
1031
|
+
controller(:other) { get(:x) { 'x' } }
|
|
1032
|
+
end
|
|
1033
|
+
show = @app.routes.find { |route| route.action == :show }
|
|
1034
|
+
top = @app.routes.find { |route| route.action == :top }
|
|
1035
|
+
other = @app.routes.find { |route| route.action == :x }
|
|
1036
|
+
assert_equal :admin_layout, show.use_layout
|
|
1037
|
+
assert_equal({ lang: 'en' }, show.default_values)
|
|
1038
|
+
assert_nil top.use_layout
|
|
1039
|
+
assert_nil top.default_values
|
|
1040
|
+
assert_nil other.use_layout
|
|
1041
|
+
get '/manage/show'
|
|
1042
|
+
assert_equal 'show', body
|
|
1043
|
+
get '/top'
|
|
1044
|
+
assert_equal 'top', body
|
|
1045
|
+
end
|
|
1046
|
+
|
|
1047
|
+
it 'should restore each level of controllers nested three deep' do
|
|
1048
|
+
mock_app do
|
|
1049
|
+
controller :one, conditions: { agent: /One/ } do
|
|
1050
|
+
before { response['x-one'] = 'one' }
|
|
1051
|
+
controller :two do
|
|
1052
|
+
before { response['x-two'] = 'two' }
|
|
1053
|
+
controller :three do
|
|
1054
|
+
get(:index) { 'three' }
|
|
1055
|
+
end
|
|
1056
|
+
get(:in_two) { 'in two' }
|
|
1057
|
+
end
|
|
1058
|
+
get(:in_one) { 'in one' }
|
|
1059
|
+
end
|
|
1060
|
+
get(:top) { 'top' }
|
|
1061
|
+
end
|
|
1062
|
+
get '/three'
|
|
1063
|
+
assert_equal 'three', body
|
|
1064
|
+
assert_equal 'two', response['x-two']
|
|
1065
|
+
get '/two/in_two'
|
|
1066
|
+
assert_equal 'in two', body
|
|
1067
|
+
assert_equal 'one', response['x-one']
|
|
1068
|
+
assert_equal 'two', response['x-two']
|
|
1069
|
+
get '/one/in_one', {}, 'HTTP_USER_AGENT' => 'One'
|
|
1070
|
+
assert_equal 'in one', body
|
|
1071
|
+
assert_equal 'one', response['x-one']
|
|
1072
|
+
assert_nil response['x-two']
|
|
1073
|
+
get '/one/in_one'
|
|
1074
|
+
assert_equal 404, status
|
|
1075
|
+
get '/top'
|
|
1076
|
+
assert_equal 'top', body
|
|
1077
|
+
assert_nil response['x-one']
|
|
1078
|
+
assert_nil response['x-two']
|
|
1079
|
+
end
|
|
1080
|
+
|
|
1081
|
+
it 'should restore the outer options after sibling nested controller blocks' do
|
|
1082
|
+
mock_app do
|
|
1083
|
+
controller :admin, conditions: { agent: /Admin/ } do
|
|
1084
|
+
controller(:posts) { get(:index) { 'posts' } }
|
|
1085
|
+
controller(:users) { get(:index) { 'users' } }
|
|
1086
|
+
get(:show) { 'show' }
|
|
1087
|
+
end
|
|
1088
|
+
get(:top) { 'top' }
|
|
1089
|
+
end
|
|
1090
|
+
get '/posts'
|
|
1091
|
+
assert_equal 'posts', body
|
|
1092
|
+
get '/users'
|
|
1093
|
+
assert_equal 'users', body
|
|
1094
|
+
get '/admin/show', {}, 'HTTP_USER_AGENT' => 'Admin'
|
|
1095
|
+
assert_equal 'show', body
|
|
1096
|
+
get '/top'
|
|
1097
|
+
assert_equal 'top', body
|
|
1098
|
+
end
|
|
1099
|
+
|
|
1100
|
+
it 'should restore the options when a controller block raises' do
|
|
1101
|
+
mock_app
|
|
1102
|
+
assert_raises(RuntimeError) do
|
|
1103
|
+
@app.controller :broken, conditions: { agent: /Broken/ } do
|
|
1104
|
+
before { response['x-broken'] = 'broken' }
|
|
1105
|
+
raise 'broken controller'
|
|
1106
|
+
end
|
|
1107
|
+
end
|
|
1108
|
+
@app.get(:top) { 'top' }
|
|
1109
|
+
get '/top'
|
|
1110
|
+
assert_equal 'top', body
|
|
1111
|
+
assert_nil response['x-broken']
|
|
1112
|
+
end
|
|
1113
|
+
|
|
983
1114
|
it 'should use map and with' do
|
|
984
1115
|
mock_app do
|
|
985
1116
|
get :index, map: '/bugs', with: :id do
|
|
@@ -2599,4 +2730,224 @@ describe 'Routing' do
|
|
|
2599
2730
|
assert_equal 'static', body
|
|
2600
2731
|
end
|
|
2601
2732
|
end
|
|
2733
|
+
|
|
2734
|
+
describe "env['sinatra.route']" do
|
|
2735
|
+
it 'names the root route /' do
|
|
2736
|
+
mock_app do
|
|
2737
|
+
get(:index) { env['sinatra.route'] }
|
|
2738
|
+
controller(:admin) { get(:index) { env['sinatra.route'] } }
|
|
2739
|
+
end
|
|
2740
|
+
get '/'
|
|
2741
|
+
assert_equal 'GET /', body
|
|
2742
|
+
get '/admin'
|
|
2743
|
+
assert_equal 'GET /admin', body
|
|
2744
|
+
end
|
|
2745
|
+
|
|
2746
|
+
it 'holds the verb and the pattern, as Sinatra writes it' do
|
|
2747
|
+
mock_app do
|
|
2748
|
+
get(:index, map: '/posts') { env['sinatra.route'] }
|
|
2749
|
+
get('/posts/:id') { env['sinatra.route'] }
|
|
2750
|
+
post('/posts/:id') { env['sinatra.route'] }
|
|
2751
|
+
end
|
|
2752
|
+
get '/posts'
|
|
2753
|
+
assert_equal 'GET /posts', body
|
|
2754
|
+
get '/posts/1'
|
|
2755
|
+
assert_equal 'GET /posts/:id', body
|
|
2756
|
+
post '/posts/1'
|
|
2757
|
+
assert_equal 'POST /posts/:id', body
|
|
2758
|
+
end
|
|
2759
|
+
|
|
2760
|
+
it 'writes a regexp the way Sinatra does' do
|
|
2761
|
+
mock_app do
|
|
2762
|
+
get(%r{/plain/(\d+)}) { env['sinatra.route'] }
|
|
2763
|
+
get(%r{/flagged/(\d+)}i) { env['sinatra.route'] }
|
|
2764
|
+
get(%r{/spaced/ (\d+)}x) { env['sinatra.route'] }
|
|
2765
|
+
end
|
|
2766
|
+
get '/plain/1'
|
|
2767
|
+
assert_equal 'GET \/plain\/(\d+)', body
|
|
2768
|
+
get '/flagged/1'
|
|
2769
|
+
assert_equal 'GET (?i-mx:\/flagged\/(\d+))', body
|
|
2770
|
+
get '/spaced/1'
|
|
2771
|
+
assert_equal 'GET /spaced/(\d+)', body
|
|
2772
|
+
end
|
|
2773
|
+
|
|
2774
|
+
it 'names a regexp with anchors, which Sinatra refuses' do
|
|
2775
|
+
mock_app do
|
|
2776
|
+
get(%r{^/anchored$}) { env['sinatra.route'] }
|
|
2777
|
+
end
|
|
2778
|
+
get '/anchored'
|
|
2779
|
+
assert_equal 'GET ^\/anchored$', body
|
|
2780
|
+
end
|
|
2781
|
+
|
|
2782
|
+
it 'includes the controller prefix, the parent and the with params' do
|
|
2783
|
+
mock_app do
|
|
2784
|
+
controller :admin do
|
|
2785
|
+
get(:index) { env['sinatra.route'] }
|
|
2786
|
+
get(:show, with: :id) { env['sinatra.route'] }
|
|
2787
|
+
end
|
|
2788
|
+
controller :items, parent: :user do
|
|
2789
|
+
get(:index) { env['sinatra.route'] }
|
|
2790
|
+
end
|
|
2791
|
+
end
|
|
2792
|
+
get '/admin'
|
|
2793
|
+
assert_equal 'GET /admin', body
|
|
2794
|
+
get '/admin/show/1'
|
|
2795
|
+
assert_equal 'GET /admin/show/:id', body
|
|
2796
|
+
get '/user/1/items'
|
|
2797
|
+
assert_equal 'GET /user/:user_id/items', body
|
|
2798
|
+
end
|
|
2799
|
+
|
|
2800
|
+
it 'keeps the format of a route with provides in the pattern' do
|
|
2801
|
+
mock_app do
|
|
2802
|
+
get(:index, map: '/feed', provides: %i[html json]) { env['sinatra.route'] }
|
|
2803
|
+
end
|
|
2804
|
+
get '/feed.json'
|
|
2805
|
+
assert_equal 'GET /feed(.:format)?', body
|
|
2806
|
+
get '/feed'
|
|
2807
|
+
assert_equal 'GET /feed(.:format)?', body
|
|
2808
|
+
end
|
|
2809
|
+
|
|
2810
|
+
it 'is set for after filters, and not yet for before filters, as in Sinatra' do
|
|
2811
|
+
seen = []
|
|
2812
|
+
mock_app do
|
|
2813
|
+
before { seen << [:before, env['sinatra.route']] }
|
|
2814
|
+
after { seen << [:after, env['sinatra.route']] }
|
|
2815
|
+
controller :admin do
|
|
2816
|
+
before { seen << [:controller_before, env['sinatra.route']] }
|
|
2817
|
+
after { seen << [:controller_after, env['sinatra.route']] }
|
|
2818
|
+
get(:show, with: :id) { 'ok' }
|
|
2819
|
+
end
|
|
2820
|
+
end
|
|
2821
|
+
get '/admin/show/1'
|
|
2822
|
+
assert_equal 200, status
|
|
2823
|
+
assert_equal [
|
|
2824
|
+
[:before, nil],
|
|
2825
|
+
[:controller_before, nil],
|
|
2826
|
+
[:controller_after, 'GET /admin/show/:id'],
|
|
2827
|
+
[:after, 'GET /admin/show/:id']
|
|
2828
|
+
], seen
|
|
2829
|
+
end
|
|
2830
|
+
|
|
2831
|
+
it 'stays unset when a before filter halts' do
|
|
2832
|
+
mock_app do
|
|
2833
|
+
before { halt 403, env.key?('sinatra.route').to_s }
|
|
2834
|
+
get('/secret') { 'never' }
|
|
2835
|
+
end
|
|
2836
|
+
get '/secret'
|
|
2837
|
+
assert_equal 403, status
|
|
2838
|
+
assert_equal 'false', body
|
|
2839
|
+
end
|
|
2840
|
+
|
|
2841
|
+
it 'reaches an error handler reached from a route' do
|
|
2842
|
+
mock_app do
|
|
2843
|
+
set :raise_errors, false
|
|
2844
|
+
set :show_exceptions, false
|
|
2845
|
+
error(FooError) { env['sinatra.route'] }
|
|
2846
|
+
get('/boom/:id') { raise FooError }
|
|
2847
|
+
end
|
|
2848
|
+
get '/boom/1'
|
|
2849
|
+
assert_equal 500, status
|
|
2850
|
+
assert_equal 'GET /boom/:id', body
|
|
2851
|
+
end
|
|
2852
|
+
|
|
2853
|
+
it 'names the route that answers after a pass' do
|
|
2854
|
+
seen = []
|
|
2855
|
+
mock_app do
|
|
2856
|
+
after { seen << env['sinatra.route'] }
|
|
2857
|
+
get('/posts/:id') { pass }
|
|
2858
|
+
get('/posts/*rest') { env['sinatra.route'] }
|
|
2859
|
+
end
|
|
2860
|
+
get '/posts/1'
|
|
2861
|
+
assert_equal 'GET /posts/*rest', body
|
|
2862
|
+
assert_equal ['GET /posts/*rest'], seen
|
|
2863
|
+
end
|
|
2864
|
+
|
|
2865
|
+
it 'names a HEAD request as HEAD' do
|
|
2866
|
+
seen = []
|
|
2867
|
+
mock_app do
|
|
2868
|
+
after { seen << env['sinatra.route'] }
|
|
2869
|
+
get('/posts/:id') { 'ok' }
|
|
2870
|
+
end
|
|
2871
|
+
head '/posts/1'
|
|
2872
|
+
assert_equal 200, status
|
|
2873
|
+
assert_equal ['HEAD /posts/:id'], seen
|
|
2874
|
+
end
|
|
2875
|
+
|
|
2876
|
+
it 'stays unset for a request that matches no route' do
|
|
2877
|
+
seen = []
|
|
2878
|
+
mock_app do
|
|
2879
|
+
before { seen << env.key?('sinatra.route') }
|
|
2880
|
+
not_found { env.key?('sinatra.route').to_s }
|
|
2881
|
+
get('/posts') { 'ok' }
|
|
2882
|
+
end
|
|
2883
|
+
get '/nothing'
|
|
2884
|
+
assert_equal 404, status
|
|
2885
|
+
assert_equal 'false', body
|
|
2886
|
+
assert_equal [false], seen
|
|
2887
|
+
end
|
|
2888
|
+
|
|
2889
|
+
it 'stays unset when only the verb differs' do
|
|
2890
|
+
mock_app do
|
|
2891
|
+
error(405) { env.key?('sinatra.route').to_s }
|
|
2892
|
+
get('/posts') { 'ok' }
|
|
2893
|
+
end
|
|
2894
|
+
post '/posts'
|
|
2895
|
+
assert_equal 405, status
|
|
2896
|
+
assert_equal 'false', body
|
|
2897
|
+
end
|
|
2898
|
+
|
|
2899
|
+
it 'stays unset when the only matching route fails its condition' do
|
|
2900
|
+
mock_app do
|
|
2901
|
+
not_found { env.key?('sinatra.route').to_s }
|
|
2902
|
+
get('/feed', provides: :json) { 'ok' }
|
|
2903
|
+
condition { false }
|
|
2904
|
+
get('/hidden') { 'ok' }
|
|
2905
|
+
get('/bots', agent: /bot/) { 'ok' }
|
|
2906
|
+
end
|
|
2907
|
+
['/feed.xml', '/hidden', '/bots'].each do |path|
|
|
2908
|
+
get path
|
|
2909
|
+
assert_equal 404, status
|
|
2910
|
+
assert_equal 'false', body
|
|
2911
|
+
end
|
|
2912
|
+
end
|
|
2913
|
+
|
|
2914
|
+
it 'stays unset when a condition calls pass' do
|
|
2915
|
+
mock_app do
|
|
2916
|
+
not_found { env.key?('sinatra.route').to_s }
|
|
2917
|
+
condition { pass }
|
|
2918
|
+
get('/cp') { 'never' }
|
|
2919
|
+
end
|
|
2920
|
+
get '/cp'
|
|
2921
|
+
assert_equal 404, status
|
|
2922
|
+
assert_equal 'false', body
|
|
2923
|
+
end
|
|
2924
|
+
|
|
2925
|
+
it 'keeps the passed route when the next route fails its condition' do
|
|
2926
|
+
mock_app do
|
|
2927
|
+
not_found { env['sinatra.route'] }
|
|
2928
|
+
get('/posts/:id') { pass }
|
|
2929
|
+
condition { false }
|
|
2930
|
+
get('/posts/*rest') { 'never' }
|
|
2931
|
+
end
|
|
2932
|
+
get '/posts/1'
|
|
2933
|
+
assert_equal 404, status
|
|
2934
|
+
assert_equal 'GET /posts/:id', body
|
|
2935
|
+
end
|
|
2936
|
+
|
|
2937
|
+
it 'leaves out the mount path, at the root and under a sub-path' do
|
|
2938
|
+
mock_app do
|
|
2939
|
+
get('/posts/:id') { env['sinatra.route'] }
|
|
2940
|
+
end
|
|
2941
|
+
map = Padrino::Router.new({ path: '/', to: @app }, { path: '/blog', to: @app })
|
|
2942
|
+
outer_env = nil
|
|
2943
|
+
outer = lambda { |env|
|
|
2944
|
+
outer_env = env
|
|
2945
|
+
map.call(env)
|
|
2946
|
+
}
|
|
2947
|
+
|
|
2948
|
+
assert_equal 'GET /posts/:id', Rack::MockRequest.new(outer).get('/posts/1').body
|
|
2949
|
+
assert_equal 'GET /posts/:id', Rack::MockRequest.new(outer).get('/blog/posts/1').body
|
|
2950
|
+
assert_equal 'GET /posts/:id', outer_env['sinatra.route']
|
|
2951
|
+
end
|
|
2952
|
+
end
|
|
2602
2953
|
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.18.
|
|
4
|
+
version: 0.18.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Padrino Team
|
|
@@ -11,7 +11,7 @@ authors:
|
|
|
11
11
|
autorequire:
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
|
-
date: 2026-
|
|
14
|
+
date: 2026-11-01 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: ostruct
|
|
@@ -33,14 +33,14 @@ dependencies:
|
|
|
33
33
|
requirements:
|
|
34
34
|
- - '='
|
|
35
35
|
- !ruby/object:Gem::Version
|
|
36
|
-
version: 0.18.
|
|
36
|
+
version: 0.18.2
|
|
37
37
|
type: :runtime
|
|
38
38
|
prerelease: false
|
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
|
40
40
|
requirements:
|
|
41
41
|
- - '='
|
|
42
42
|
- !ruby/object:Gem::Version
|
|
43
|
-
version: 0.18.
|
|
43
|
+
version: 0.18.2
|
|
44
44
|
- !ruby/object:Gem::Dependency
|
|
45
45
|
name: rackup
|
|
46
46
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -223,6 +223,7 @@ files:
|
|
|
223
223
|
- test/helper.rb
|
|
224
224
|
- test/test_application.rb
|
|
225
225
|
- test/test_binstub.rb
|
|
226
|
+
- test/test_caller.rb
|
|
226
227
|
- test/test_cli.rb
|
|
227
228
|
- test/test_configuration.rb
|
|
228
229
|
- test/test_core.rb
|
|
@@ -246,10 +247,14 @@ files:
|
|
|
246
247
|
- test/test_router.rb
|
|
247
248
|
- test/test_routing.rb
|
|
248
249
|
- test/test_server.rb
|
|
249
|
-
homepage:
|
|
250
|
+
homepage: https://padrinorb.com
|
|
250
251
|
licenses:
|
|
251
252
|
- MIT
|
|
252
|
-
metadata:
|
|
253
|
+
metadata:
|
|
254
|
+
bug_tracker_uri: https://github.com/padrino/padrino-framework/issues
|
|
255
|
+
changelog_uri: https://github.com/padrino/padrino-framework/blob/master/CHANGES.rdoc
|
|
256
|
+
documentation_uri: https://padrinorb.com/guides/
|
|
257
|
+
source_code_uri: https://github.com/padrino/padrino-framework
|
|
253
258
|
post_install_message:
|
|
254
259
|
rdoc_options:
|
|
255
260
|
- "--charset=UTF-8"
|