padrino-core 0.12.9 → 0.13.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +5 -13
  2. data/bin/padrino +1 -2
  3. data/lib/padrino-core/application/application_setup.rb +10 -6
  4. data/lib/padrino-core/application/params_protection.rb +7 -1
  5. data/lib/padrino-core/application/routing.rb +88 -50
  6. data/lib/padrino-core/application/show_exceptions.rb +29 -0
  7. data/lib/padrino-core/application.rb +0 -19
  8. data/lib/padrino-core/caller.rb +1 -2
  9. data/lib/padrino-core/cli/base.rb +7 -11
  10. data/lib/padrino-core/cli/rake_tasks.rb +8 -21
  11. data/lib/padrino-core/loader.rb +13 -12
  12. data/lib/padrino-core/logger.rb +4 -32
  13. data/lib/padrino-core/mounter.rb +62 -21
  14. data/lib/padrino-core/path_router/compiler.rb +110 -0
  15. data/lib/padrino-core/path_router/error_handler.rb +8 -0
  16. data/lib/padrino-core/path_router/matcher.rb +123 -0
  17. data/lib/padrino-core/path_router/route.rb +169 -0
  18. data/lib/padrino-core/path_router.rb +119 -0
  19. data/lib/padrino-core/reloader/rack.rb +1 -4
  20. data/lib/padrino-core/reloader/storage.rb +3 -31
  21. data/lib/padrino-core/reloader.rb +12 -17
  22. data/lib/padrino-core/version.rb +1 -1
  23. data/lib/padrino-core.rb +0 -2
  24. data/padrino-core.gemspec +8 -2
  25. data/test/fixtures/apps/helpers/support.rb +1 -0
  26. data/test/fixtures/apps/{rack_apps.rb → mountable_apps/rack_apps.rb} +0 -4
  27. data/test/fixtures/apps/{static.html → mountable_apps/static.html} +0 -0
  28. data/test/fixtures/apps/precompiled_app.rb +19 -0
  29. data/test/fixtures/apps/system.rb +0 -2
  30. data/test/helper.rb +1 -1
  31. data/test/test_application.rb +18 -6
  32. data/test/test_csrf_protection.rb +6 -7
  33. data/test/test_filters.rb +18 -1
  34. data/test/test_logger.rb +1 -49
  35. data/test/test_mounter.rb +2 -4
  36. data/test/test_params_protection.rb +15 -15
  37. data/test/test_reloader_simple.rb +2 -2
  38. data/test/test_reloader_system.rb +0 -30
  39. data/test/test_restful_routing.rb +4 -4
  40. data/test/test_routing.rb +176 -54
  41. metadata +109 -49
  42. data/lib/padrino-core/cli/binstub.rb +0 -27
  43. data/lib/padrino-core/configuration.rb +0 -40
  44. data/lib/padrino-core/ext/http_router.rb +0 -201
  45. data/lib/padrino-core/mounter/application_extension.rb +0 -55
  46. data/test/fixtures/apps/custom_dependencies/custom_dependencies.rb +0 -11
  47. data/test/fixtures/apps/custom_dependencies/my_dependencies/my_dependency.rb +0 -0
  48. data/test/fixtures/apps/stealthy/app.rb +0 -7
  49. data/test/fixtures/apps/stealthy/helpers/stealthy_class_helpers.rb +0 -13
  50. data/test/test_configuration.rb +0 -29
  51. data/test/test_reloader_storage.rb +0 -51
@@ -1,27 +0,0 @@
1
- module Padrino
2
- ##
3
- # Replaces the current process with it's binstub.
4
- #
5
- def self.replace_with_binstub(executable)
6
- begin
7
- return if Bundler.definition.missing_specs.empty?
8
- rescue NameError, NoMethodError, Bundler::GemfileNotFound
9
- end
10
-
11
- project_root = Dir.pwd
12
- until project_root.empty?
13
- break if File.file?(File.join(project_root, 'Gemfile'))
14
- project_root = project_root.rpartition('/').first
15
- end
16
-
17
- if %w(Gemfile .components).all? { |file| File.file?(File.join(project_root, file)) }
18
- binstub = File.join(project_root, 'bin', executable)
19
- if File.file?(binstub)
20
- exec Gem.ruby, binstub, *ARGV
21
- else
22
- puts 'Please run `bundler install --binstubs` from your project root to generate bundle-specific executables'
23
- exit!
24
- end
25
- end
26
- end
27
- end
@@ -1,40 +0,0 @@
1
- require 'ostruct'
2
-
3
- module Padrino
4
- ##
5
- # Padrino simple configuration module
6
- #
7
- module Configuration
8
- ##
9
- # Returns the configuration structure allowing to get and set it's values.
10
- # Padrino.config is a simple Ruby OpenStruct object with no additional magic.
11
- #
12
- # Example:
13
- #
14
- # Padrino.config.value1 = 42
15
- # exit if Padrino.config.exiting
16
- #
17
- def config
18
- @config ||= OpenStruct.new
19
- end
20
-
21
- ##
22
- # Allows to configure different environments differently. Requires a block.
23
- #
24
- # Example:
25
- #
26
- # Padrino.configure :development do |config|
27
- # config.value2 = 'only development'
28
- # end
29
- # Padrino.configure :development, :production do |config|
30
- # config.value2 = 'both development and production'
31
- # end
32
- # Padrino.configure do |config|
33
- # config.value2 = 'any environment'
34
- # end
35
- #
36
- def configure(*environments)
37
- yield(config) if environments.empty? || environments.include?(Padrino.env)
38
- end
39
- end
40
- end
@@ -1,201 +0,0 @@
1
- require 'http_router' unless defined?(HttpRouter)
2
-
3
- class HttpRouter
4
- def rewrite_partial_path_info(env, request); end
5
- def rewrite_path_info(env, request); end
6
-
7
- def process_destination_path(path, env)
8
- Thread.current['padrino.instance'].instance_eval do
9
- request.route_obj = path.route
10
- @_response_buffer = nil
11
- @route = path.route
12
- @params ||= {}
13
- @params.update(env['router.params'])
14
- @block_params = if match_data = env['router.request'].extra_env['router.regex_match']
15
- params_list = match_data.to_a
16
- params_list.shift
17
- @params[:captures] = params_list
18
- params_list
19
- else
20
- env['router.request'].params
21
- end
22
- # Provide access to the current controller to the request
23
- # Now we can eval route, but because we have "throw halt" we need to be
24
- # (en)sure to reset old layout and run controller after filters.
25
- original_params = @params
26
- parent_layout = @layout
27
- successful = false
28
- begin
29
- filter! :before
30
- (@route.before_filters - settings.filters[:before]).each { |block| instance_eval(&block) }
31
- @layout = path.route.use_layout if path.route.use_layout
32
- @route.custom_conditions.each { |block| pass if block.bind(self).call == false }
33
- halt_response = catch(:halt) { route_eval { @route.dest[self, @block_params] } }
34
- @_response_buffer = halt_response.is_a?(Array) ? halt_response.last : halt_response
35
- successful = true
36
- halt halt_response
37
- ensure
38
- (@route.after_filters - settings.filters[:after]).each { |block| instance_eval(&block) } if successful
39
- @layout = parent_layout
40
- @params = original_params
41
- end
42
- end
43
- end
44
-
45
- class Route
46
- VALID_HTTP_VERBS.replace %w[GET POST PUT PATCH DELETE HEAD OPTIONS LINK UNLINK]
47
-
48
- attr_accessor :use_layout, :controller, :action, :cache, :cache_key, :cache_expires, :parent
49
-
50
- def before_filters(&block)
51
- @_before_filters ||= []
52
- @_before_filters << block if block_given?
53
-
54
- @_before_filters
55
- end
56
-
57
- def after_filters(&block)
58
- @_after_filters ||= []
59
- @_after_filters << block if block_given?
60
-
61
- @_after_filters
62
- end
63
-
64
- def custom_conditions(&block)
65
- @_custom_conditions ||= []
66
- @_custom_conditions << block if block_given?
67
-
68
- @_custom_conditions
69
- end
70
-
71
- def significant_variable_names
72
- @significant_variable_names ||= if @original_path.is_a?(String)
73
- @original_path.scan(/(^|[^\\])[:\*]([a-zA-Z0-9_]+)/).map{|p| p.last.to_sym}
74
- elsif @original_path.is_a?(Regexp) and @original_path.respond_to?(:named_captures)
75
- @original_path.named_captures.keys.map(&:to_sym)
76
- else
77
- []
78
- end
79
- end
80
-
81
- def to(dest = nil, &dest_block)
82
- @dest = dest || dest_block || raise("you didn't specify a destination")
83
-
84
- @router.current_order ||= 0
85
- @order = @router.current_order
86
- @router.current_order += 1
87
-
88
- if @dest.respond_to?(:url_mount=)
89
- urlmount = UrlMount.new(@path_for_generation, @default_values || {}) # TODO url mount should accept nil here.
90
- urlmount.url_mount = @router.url_mount if @router.url_mount
91
- @dest.url_mount = urlmount
92
- end
93
- self
94
- end
95
-
96
- attr_accessor :order
97
-
98
- end
99
-
100
- attr_accessor :current_order
101
-
102
- def sort!
103
- @routes.sort!{ |a, b| a.order <=> b.order }
104
- end
105
-
106
- class Node::Glob
107
- def to_code
108
- id = root.next_counter
109
- "request.params << (globbed_params#{id} = [])
110
- until request.path.empty?
111
- globbed_params#{id} << request.path.shift
112
- #{super}
113
- end
114
- request.path[0,0] = globbed_params#{id}
115
- request.params.pop"
116
- end
117
- end
118
-
119
- class Node::SpanningRegex
120
- def to_code
121
- params_count = @ordered_indicies.size
122
- whole_path_var = "whole_path#{root.next_counter}"
123
- "#{whole_path_var} = request.joined_path
124
- if match = #{@matcher.inspect}.match(#{whole_path_var}) and match.begin(0).zero?
125
- _#{whole_path_var} = request.path.dup
126
- " << param_capturing_code << "
127
- remaining_path = #{whole_path_var}[match[0].size + (#{whole_path_var}[match[0].size] == ?/ ? 1 : 0), #{whole_path_var}.size]
128
- request.path = remaining_path.split('/')
129
- #{node_to_code}
130
- request.path = _#{whole_path_var}
131
- request.params.slice!(#{-params_count}, #{params_count})
132
- end
133
- "
134
- end
135
- end
136
-
137
- # Monkey patching the Request class. Using Rack::Utils.unescape rather than
138
- # URI.unescape which can't handle utf-8 chars
139
- class Request
140
- def initialize(path, rack_request)
141
- @rack_request = rack_request
142
- @path = path.split(/\//).map{|part| Rack::Utils.unescape(part) }
143
- @path.shift if @path.first == ''
144
- @path.push('') if path[-1] == ?/
145
- @extra_env = {}
146
- @params = []
147
- @acceptable_methods = Set.new
148
- end
149
- end
150
-
151
- class Node::Path
152
- def to_code
153
- path_ivar = inject_root_ivar(self)
154
- "#{"if !callback && request.path.size == 1 && request.path.first == '' && (request.rack_request.head? || request.rack_request.get?) && request.rack_request.path_info[-1] == ?/
155
- catch(:pass) do
156
- response = ::Rack::Response.new
157
- response.redirect(request.rack_request.path_info[0, request.rack_request.path_info.size - 1], 302)
158
- return response.finish
159
- end
160
- end" if router.redirect_trailing_slash?}
161
-
162
- #{"if request.#{router.ignore_trailing_slash? ? 'path_finished?' : 'path.empty?'}" unless route.match_partially}
163
- catch(:pass) do
164
- if callback
165
- request.called = true
166
- callback.call(Response.new(request, #{path_ivar}))
167
- else
168
- env = request.rack_request.dup.env
169
- env['router.request'] = request
170
- env['router.params'] ||= {}
171
- #{"env['router.params'].merge!(Hash[#{param_names.inspect}.zip(request.params)])" if dynamic?}
172
- env['router.params'] = env['router.params'].with_indifferent_access
173
- @router.rewrite#{"_partial" if route.match_partially}_path_info(env, request)
174
- response = @router.process_destination_path(#{path_ivar}, env)
175
- return response unless router.pass_on_response(response)
176
- end
177
- end
178
- #{"end" unless route.match_partially}"
179
- end
180
- end
181
-
182
- class Node::FreeRegex
183
- def to_code
184
- id = root.next_counter
185
- "whole_path#{id} = \"/\#{request.joined_path}\"
186
- if match = #{matcher.inspect}.match(whole_path#{id}) and match[0].size == whole_path#{id}.size
187
- request.extra_env['router.regex_match'] = match
188
- old_path = request.path
189
- request.path = ['']
190
- " << (use_named_captures? ?
191
- "match.names.size.times{|i| request.params << match[i + 1]} if match.respond_to?(:names) && match.names" : "") << "
192
- #{super}
193
- request.path = old_path
194
- request.extra_env.delete('router.regex_match')
195
- " << (use_named_captures? ?
196
- "request.params.slice!(-match.names.size, match.names.size)" : ""
197
- ) << "
198
- end"
199
- end
200
- end
201
- end
@@ -1,55 +0,0 @@
1
- module Padrino
2
- class Mounter
3
- module ApplicationExtension
4
- attr_accessor :uri_root, :mounter_options
5
- attr_writer :public_folder
6
-
7
- def dependencies
8
- @__dependencies ||= Dir.glob("#{root}/**/*.rb").delete_if { |path| path == app_file }
9
- end
10
-
11
- def prerequisites
12
- @__prerequisites ||= []
13
- end
14
-
15
- def app_file
16
- @__app_file ||= trace_method(:app_file) { mounter_options[:app_file] }
17
- end
18
-
19
- def root
20
- @__root ||= trace_method(:root) { File.expand_path("#{app_file}/../") }
21
- end
22
-
23
- def public_folder
24
- @public_folder ||= trace_method(:public_folder) { "" }
25
- end
26
-
27
- def app_name
28
- @__app_name ||= mounter_options[:app_name] || self.to_s.underscore.to_sym
29
- end
30
-
31
- def setup_application!
32
- @configured ||= trace_method(:setup_application!) do
33
- $LOAD_PATH.concat(prerequisites)
34
- require_dependencies if root.start_with?(Padrino.root)
35
- true
36
- end
37
- end
38
-
39
- private
40
-
41
- def require_dependencies
42
- Padrino.require_dependencies(dependencies, :force => true)
43
- end
44
-
45
- def trace_method(method_name)
46
- value = baseclass.send(method_name) if baseclass != self && baseclass.respond_to?(method_name)
47
- value || yield
48
- end
49
-
50
- def baseclass
51
- @__baseclass ||= respond_to?(:superclass) ? superclass : self
52
- end
53
- end
54
- end
55
- end
@@ -1,11 +0,0 @@
1
- PADRINO_ROOT = File.dirname(__FILE__) unless defined? PADRINO_ROOT
2
-
3
- class CustomDependencies < Padrino::Application
4
- set :reload, true
5
- end
6
-
7
- CustomDependencies.controllers do
8
- get "/" do
9
- "foo"
10
- end
11
- end
@@ -1,7 +0,0 @@
1
- PADRINO_ROOT = File.dirname(__FILE__) unless defined? PADRINO_ROOT
2
-
3
- class SystemStealthyClassDemo < Padrino::Application
4
- set :reload, true
5
- end
6
-
7
- Padrino.load!
@@ -1,13 +0,0 @@
1
- class Boo
2
- def self.class_method
3
- "BooClass"
4
- end
5
- end
6
-
7
- class Woo < Boo
8
- def poo
9
- end
10
- end
11
-
12
- class Soo < Boo
13
- end
@@ -1,29 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/helper')
2
-
3
- describe "PadrinoConfiguration" do
4
- it 'should be able to store values' do
5
- Padrino.config.val1 = 12345
6
- assert_equal 12345, Padrino.config.val1
7
- end
8
-
9
- it 'should be able to configure with block' do
10
- Padrino.configure do |config|
11
- config.val2 = 54321
12
- end
13
- assert_equal 54321, Padrino.config.val2
14
- end
15
-
16
- it 'should be able to configure with block' do
17
- Padrino.configure :test do |config|
18
- config.test1 = 54321
19
- end
20
- Padrino.configure :development do |config|
21
- config.test1 = 12345
22
- end
23
- Padrino.configure :test, :development do |config|
24
- config.both1 = 54321
25
- end
26
- assert_equal 54321, Padrino.config.test1
27
- assert_equal 54321, Padrino.config.both1
28
- end
29
- end
@@ -1,51 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/helper')
2
-
3
- describe "Padrino::Reloader::Storage" do
4
- describe "#classes" do
5
- it 'should take an snapshot of the current loaded classes' do
6
- snapshot = Padrino::Reloader::Storage.send(:object_classes)
7
- assert_equal snapshot.include?(Padrino::Logger), true
8
- end
9
-
10
- it 'should return a Set object' do
11
- snapshot = Padrino::Reloader::Storage.send(:object_classes)
12
- assert_equal snapshot.kind_of?(Set), true
13
- end
14
-
15
- it 'should be able to process a the class name given a block' do
16
- klasses = Padrino::Reloader::Storage.send(:object_classes) do |klass|
17
- next unless klass.respond_to?(:name) # fix JRuby < 1.7.22
18
- if klass.name =~ /^Padrino::/
19
- klass
20
- end
21
- end
22
-
23
- assert_equal (klasses.size > 1), true
24
- klasses.each do |klass|
25
- assert_match /^Padrino::/, klass.to_s
26
- end
27
- end
28
- end
29
-
30
- describe "#new_classes" do
31
- before do
32
- @snapshot = Padrino::Reloader::Storage.send(:object_classes)
33
- end
34
-
35
- it 'should return list of new classes' do
36
- class OSTest; end
37
- module OSTestModule; class B; end; end
38
-
39
- new_classes = Padrino::Reloader::Storage.send(:new_classes, @snapshot)
40
-
41
- assert_equal new_classes.size, 2
42
- assert_equal new_classes.include?(OSTest), true
43
- assert_equal new_classes.include?(OSTestModule::B), true
44
- end
45
-
46
- it 'should return a Set object' do
47
- new_classes = Padrino::Reloader::Storage.send(:new_classes, @snapshot)
48
- assert_equal new_classes.kind_of?(Set), true
49
- end
50
- end
51
- end