padrino-core 0.12.2 → 0.12.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -87,7 +87,7 @@ module Padrino
87
87
  began_at = Time.now
88
88
  file = figure_path(file)
89
89
  return unless options[:force] || file_changed?(file)
90
- return require(file) if external_feature?(file)
90
+ return require(file) if feature_excluded?(file)
91
91
 
92
92
  Storage.prepare(file) # might call #safe_load recursively
93
93
  logger.devel(file_new?(file) ? :loading : :reload, began_at, file)
@@ -95,13 +95,13 @@ module Padrino
95
95
  with_silence{ require(file) }
96
96
  Storage.commit(file)
97
97
  update_modification_time(file)
98
- rescue Exception => e
98
+ rescue Exception => exception
99
99
  unless options[:cyclic]
100
- logger.exception e, :short
100
+ logger.exception exception, :short
101
101
  logger.error "Failed to load #{file}; removing partially defined constants"
102
102
  end
103
103
  Storage.rollback(file)
104
- raise e
104
+ raise
105
105
  end
106
106
  end
107
107
 
@@ -121,7 +121,7 @@ module Padrino
121
121
  # Remove a feature from $LOADED_FEATURES so it can be required again.
122
122
  #
123
123
  def remove_feature(file)
124
- $LOADED_FEATURES.delete(file) unless external_feature?(file)
124
+ $LOADED_FEATURES.delete(file) unless feature_excluded?(file)
125
125
  end
126
126
 
127
127
  ##
@@ -156,7 +156,7 @@ module Padrino
156
156
  # Reloads the file if it's special. For now it's only I18n locale files.
157
157
  #
158
158
  def reload_special(file)
159
- return unless special_files.any?{ |f| File.identical?(f, file) }
159
+ return unless special_files.any?{ |special_file| File.identical?(special_file, file) }
160
160
  if defined?(I18n)
161
161
  began_at = Time.now
162
162
  I18n.reload!
@@ -171,14 +171,14 @@ module Padrino
171
171
  #
172
172
  def reload_regular(file)
173
173
  apps = mounted_apps_of(file)
174
- if apps.present?
175
- apps.each { |app| app.app_obj.reload! }
176
- update_modification_time(file)
177
- else
174
+ if apps.empty?
178
175
  reloadable_apps.each do |app|
179
176
  app.app_obj.reload! if app.app_obj.dependencies.include?(file)
180
177
  end
181
178
  safe_load(file)
179
+ else
180
+ apps.each { |app| app.app_obj.reload! }
181
+ update_modification_time(file)
182
182
  end
183
183
  end
184
184
 
@@ -203,14 +203,6 @@ module Padrino
203
203
  MTIMES[file].nil?
204
204
  end
205
205
 
206
- ##
207
- # Return the mounted_apps providing the app location.
208
- # Can be an array because in one app.rb we can define multiple Padrino::Application.
209
- #
210
- def mounted_apps_of(file)
211
- Padrino.mounted_apps.select { |app| File.identical?(file, app.app_file) }
212
- end
213
-
214
206
  ##
215
207
  # Searches Ruby files in your +Padrino.load_paths+ , Padrino::Application.load_paths
216
208
  # and monitors them for any changes.
@@ -229,25 +221,73 @@ module Padrino
229
221
  #
230
222
  def files_for_rotation
231
223
  files = Set.new
232
- Padrino.load_paths.each{ |path| files += Dir.glob("#{path}/**/*.rb") }
224
+ files += Dir.glob("#{Padrino.root}/{lib,models,shared}/**/*.rb")
233
225
  reloadable_apps.each do |app|
234
226
  files << app.app_file
227
+ files += Dir.glob(app.app_obj.prerequisites)
235
228
  files += app.app_obj.dependencies
236
229
  end
237
230
  files + special_files
238
231
  end
239
232
 
240
233
  ##
241
- # Tells if a feature is internal or external for Padrino project.
234
+ # Tells if a feature should be excluded from Reloader tracking.
242
235
  #
243
- def external_feature?(file)
244
- !file.start_with?(Padrino.root)
236
+ def feature_excluded?(file)
237
+ !file.start_with?(Padrino.root) || exclude.any?{ |excluded_path| file.start_with?(excluded_path) }
245
238
  end
246
239
 
240
+ ##
241
+ # Tells if a constant should be excluded from Reloader routines.
242
+ #
247
243
  def constant_excluded?(const)
248
- (exclude_constants - include_constants).any?{ |c| const._orig_klass_name.start_with?(c) }
244
+ external_constant?(const) || (exclude_constants - include_constants).any?{ |excluded_constant| const._orig_klass_name.start_with?(excluded_constant) }
245
+ end
246
+
247
+ ##
248
+ # Tells if a constant is defined only outside of Padrino project path.
249
+ # If a constant has any methods defined inside of the project path it's
250
+ # considered internal and will be included in further testing.
251
+ #
252
+ def external_constant?(const)
253
+ sources = object_sources(const)
254
+ begin
255
+ if sample = ObjectSpace.each_object(const).first
256
+ sources += object_sources(sample)
257
+ end
258
+ rescue RuntimeError => error # JRuby 1.7.12 fails to ObjectSpace.each_object
259
+ raise unless RUBY_PLATFORM =='java' && error.message.start_with?("ObjectSpace is disabled")
260
+ end
261
+ !sources.any?{ |source| source.start_with?(Padrino.root) }
262
+ end
263
+
264
+ ##
265
+ # Gets all the sources in which target's class or instance methods are defined.
266
+ #
267
+ # Note: Method#source_location is for Ruby 1.9.3+ only.
268
+ #
269
+ def object_sources(target)
270
+ sources = Set.new
271
+ target.methods.each do |method_name|
272
+ method_object = target.method(method_name)
273
+ if method_object.owner == (target.class == Class ? target.singleton_class : target.class)
274
+ sources << method_object.source_location.first
275
+ end
276
+ end
277
+ sources
249
278
  end
250
279
 
280
+ ##
281
+ # Return the mounted_apps providing the app location.
282
+ # Can be an array because in one app.rb we can define multiple Padrino::Application.
283
+ #
284
+ def mounted_apps_of(file)
285
+ Padrino.mounted_apps.select { |app| File.identical?(file, app.app_file) }
286
+ end
287
+
288
+ ##
289
+ # Return the apps that allow reloading.
290
+ #
251
291
  def reloadable_apps
252
292
  Padrino.mounted_apps.select{ |app| app.app_obj.respond_to?(:reload) && app.app_obj.reload? }
253
293
  end
@@ -57,7 +57,9 @@ module Padrino
57
57
  def start
58
58
  puts "=> Padrino/#{Padrino.version} has taken the stage #{Padrino.env} at http://#{options[:Host]}:#{options[:Port]}"
59
59
  [:INT, :TERM].each { |sig| trap(sig) { exit } }
60
- super
60
+ super do |server|
61
+ server.threaded = true if server.respond_to?(:threaded=)
62
+ end
61
63
  ensure
62
64
  puts "<= Padrino leaves the gun, takes the cannoli" unless options[:daemonize]
63
65
  end
@@ -6,7 +6,7 @@
6
6
  #
7
7
  module Padrino
8
8
  # The version constant for the current version of Padrino.
9
- VERSION = '0.12.2' unless defined?(Padrino::VERSION)
9
+ VERSION = '0.12.3' unless defined?(Padrino::VERSION)
10
10
 
11
11
  #
12
12
  # The current Padrino version.
data/padrino-core.gemspec CHANGED
@@ -30,7 +30,7 @@ Gem::Specification.new do |s|
30
30
  s.add_dependency("sinatra", "~> 1.4.2")
31
31
  end
32
32
  s.add_dependency("http_router", "~> 0.11.0")
33
- s.add_dependency("thor", "~> 0.18.0")
33
+ s.add_dependency("thor", "~> 0.18")
34
34
  s.add_dependency("activesupport", ">= 3.1")
35
35
  s.add_dependency("rack-protection", ">= 1.5.0")
36
36
  end
@@ -0,0 +1,4 @@
1
+ begin
2
+ require '/tmp/padrino_class_demo'
3
+ rescue LoadError
4
+ end
@@ -0,0 +1,4 @@
1
+ begin
2
+ require '/tmp/padrino_instance_demo'
3
+ rescue LoadError
4
+ end
@@ -0,0 +1,7 @@
1
+ PADRINO_ROOT = File.dirname(__FILE__) unless defined? PADRINO_ROOT
2
+
3
+ class SystemClassMethodsDemo < Padrino::Application
4
+ set :reload, true
5
+ end
6
+
7
+ Padrino.load!
@@ -0,0 +1,7 @@
1
+ PADRINO_ROOT = File.dirname(__FILE__) unless defined? PADRINO_ROOT
2
+
3
+ class SystemInstanceMethodsDemo < Padrino::Application
4
+ set :reload, true
5
+ end
6
+
7
+ Padrino.load!
data/test/test_core.rb CHANGED
@@ -30,6 +30,7 @@ describe "Core" do
30
30
  end
31
31
 
32
32
  it 'should have load paths' do
33
+ skip
33
34
  assert_equal [Padrino.root('lib'), Padrino.root('models'), Padrino.root('shared')], Padrino.load_paths
34
35
  end
35
36
 
data/test/test_logger.rb CHANGED
@@ -2,9 +2,14 @@ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
2
  require 'logger'
3
3
 
4
4
  describe "PadrinoLogger" do
5
+ before do
6
+ @save_config = Padrino::Logger::Config[:test].dup
7
+ Padrino::Logger::Config[:test][:stream] = :null
8
+ Padrino::Logger.setup!
9
+ end
5
10
 
6
- def setup
7
- Padrino::Logger::Config[:test][:stream] = :null # The default
11
+ after do
12
+ Padrino::Logger::Config[:test] = @save_config
8
13
  Padrino::Logger.setup!
9
14
  end
10
15
 
@@ -14,9 +19,7 @@ describe "PadrinoLogger" do
14
19
  end
15
20
 
16
21
  describe 'for logger functionality' do
17
-
18
22
  describe 'check stream config' do
19
-
20
23
  it 'should use stdout if stream is nil' do
21
24
  Padrino::Logger::Config[:test][:stream] = nil
22
25
  Padrino::Logger.setup!
@@ -116,6 +119,7 @@ describe "PadrinoLogger" do
116
119
  access_to_mock_app
117
120
  assert_match /\e\[0;36m DEBUG\e\[0m/, Padrino.logger.log.string
118
121
  end
122
+
119
123
  it 'should not output over debug level' do
120
124
  Padrino.logger.instance_eval{ @level = Padrino::Logger::Levels[:info] }
121
125
  access_to_mock_app
@@ -141,13 +145,17 @@ describe "alternate logger" do
141
145
  end
142
146
  end
143
147
 
144
- def setup_logger
148
+ before do
149
+ @save_logger = Padrino.logger
145
150
  @log = StringIO.new
146
151
  Padrino.logger = FancyLogger.new(@log)
147
152
  end
148
153
 
154
+ after do
155
+ Padrino.logger = @save_logger
156
+ end
157
+
149
158
  it 'should annotate the logger to support additional Padrino fancyness' do
150
- setup_logger
151
159
  Padrino.logger.debug("Debug message")
152
160
  assert_match(/Debug message/, @log.string)
153
161
  Padrino.logger.exception(Exception.new 'scary message')
@@ -155,7 +163,6 @@ describe "alternate logger" do
155
163
  end
156
164
 
157
165
  it 'should colorize log output after colorize! is called' do
158
- setup_logger
159
166
  Padrino.logger.colorize!
160
167
 
161
168
  mock_app do
@@ -169,19 +176,22 @@ describe "alternate logger" do
169
176
  end
170
177
 
171
178
  describe "alternate logger: stdlib logger" do
172
- def setup_logger
179
+ before do
173
180
  @log = StringIO.new
181
+ @save_logger = Padrino.logger
174
182
  Padrino.logger = Logger.new(@log)
175
183
  end
176
184
 
185
+ after do
186
+ Padrino.logger = @save_logger
187
+ end
188
+
177
189
  it 'should annotate the logger to support additional Padrino fancyness' do
178
- setup_logger
179
190
  Padrino.logger.debug("Debug message")
180
191
  assert_match(/Debug message/, @log.string)
181
192
  end
182
193
 
183
194
  it 'should colorize log output after colorize! is called' do
184
- setup_logger
185
195
  Padrino.logger.colorize!
186
196
 
187
197
  mock_app do
@@ -202,7 +212,22 @@ describe "options :colorize_logging" do
202
212
  end
203
213
  get "/"
204
214
  end
215
+
216
+ before do
217
+ @save_config = Padrino::Logger::Config[:test].dup
218
+ end
219
+
220
+ after do
221
+ Padrino::Logger::Config[:test] = @save_config
222
+ Padrino::Logger.setup!
223
+ end
224
+
205
225
  describe 'default' do
226
+ before do
227
+ Padrino::Logger::Config[:test][:colorize_logging] = true
228
+ Padrino::Logger.setup!
229
+ end
230
+
206
231
  it 'should use colorize logging' do
207
232
  Padrino::Logger.setup!
208
233
 
@@ -210,11 +235,14 @@ describe "options :colorize_logging" do
210
235
  assert_match /\e\[1;9m200\e\[0m OK/, Padrino.logger.log.string
211
236
  end
212
237
  end
238
+
213
239
  describe 'set value is false' do
214
- it 'should not use colorize logging' do
240
+ before do
215
241
  Padrino::Logger::Config[:test][:colorize_logging] = false
216
242
  Padrino::Logger.setup!
243
+ end
217
244
 
245
+ it 'should not use colorize logging' do
218
246
  access_to_mock_app
219
247
  assert_match /200 OK/, Padrino.logger.log.string
220
248
  end
@@ -17,6 +17,7 @@ describe "SystemReloader" do
17
17
  end
18
18
 
19
19
  it 'should reload children on parent change' do
20
+ Padrino.mount(SystemDemo).to("/")
20
21
  assert_equal Child.new.family, 'Danes'
21
22
  parent_file = File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/models/parent.rb')
22
23
  new_class = <<-DOC
@@ -46,10 +47,11 @@ describe "SystemReloader" do
46
47
  end
47
48
 
48
49
  it 'should tamper with LOAD_PATH' do
50
+ skip
49
51
  SystemDemo.load_paths.each do |lib_dir|
50
52
  assert_includes $LOAD_PATH, lib_dir
51
53
  end
52
- Padrino.send(:load_paths_was).each do |lib_dir|
54
+ Padrino.send(:default_load_paths).each do |lib_dir|
53
55
  assert_includes $LOAD_PATH, lib_dir
54
56
  end
55
57
  end
@@ -64,4 +66,58 @@ describe "SystemReloader" do
64
66
  Padrino.reload!
65
67
  end
66
68
  end
69
+
70
+ describe 'reloading external constants' do
71
+ it 'should not touch external constants defining singleton methods' do
72
+ new_class = <<-DOC
73
+ class SingletonClassTest
74
+ def self.external_test
75
+ end
76
+ end
77
+ DOC
78
+ tmp_file = '/tmp/padrino_class_demo.rb'
79
+ begin
80
+ File.open(tmp_file, "w") { |f| f.write(new_class) }
81
+ Padrino.clear!
82
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/system_class_methods_demo.rb')
83
+ @app = SystemClassMethodsDemo
84
+ Padrino.mount(SystemClassMethodsDemo).to("/")
85
+ get '/'
86
+ assert defined?(SingletonClassTest), 'SingletonClassTest undefined'
87
+ assert_includes SingletonClassTest.singleton_methods, :external_test
88
+ FileUtils.touch File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/helpers/class_methods_helpers.rb')
89
+ Padrino.reload!
90
+ assert defined?(SingletonClassTest), 'SingletonClassTest undefined'
91
+ assert_includes SingletonClassTest.singleton_methods, :external_test
92
+ ensure
93
+ FileUtils.rm tmp_file
94
+ end
95
+ end
96
+
97
+ it 'should not touch external constants defining instance methods' do
98
+ new_class = <<-DOC
99
+ class InstanceTest
100
+ def instance_test
101
+ end
102
+ end
103
+ DOC
104
+ tmp_file = '/tmp/padrino_instance_demo.rb'
105
+ begin
106
+ File.open(tmp_file, "w") { |f| f.write(new_class) }
107
+ Padrino.clear!
108
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/system_instance_methods_demo.rb')
109
+ @app = SystemInstanceMethodsDemo
110
+ Padrino.mount(SystemInstanceMethodsDemo).to("/")
111
+ get '/'
112
+ assert defined?(InstanceTest), 'InstanceTest undefined'
113
+ assert_includes InstanceTest.new.methods, :instance_test
114
+ FileUtils.touch File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/helpers/instance_methods_helpers.rb')
115
+ Padrino.reload!
116
+ assert defined?(InstanceTest), 'InstanceTest undefined'
117
+ assert_includes InstanceTest.new.methods, :instance_test
118
+ ensure
119
+ FileUtils.rm tmp_file
120
+ end
121
+ end
122
+ end
67
123
  end
data/test/test_routing.rb CHANGED
@@ -228,6 +228,10 @@ describe "Routing" do
228
228
  get("/old-bar/:id"){ params[:id] }
229
229
  post(:mix, :map => "/mix-bar/:id"){ params[:id] }
230
230
  get(:mix, :map => "/mix-bar/:id"){ params[:id] }
231
+ get(:foo, '', :with => :id){ |id| "/#{id}" }
232
+ post(:foo, '', :with => :id){ |id| "/#{id}" }
233
+ delete(:drugs, :with => [:id, 'destroy']){ |id| "/drugs/#{id}/destroy" }
234
+ delete(:drugs, '', :with => [:id, 'destroy']){ |id| "/#{id}/destroy" }
231
235
  end
232
236
  get "/foo"
233
237
  assert_equal "/foo", body
@@ -251,6 +255,14 @@ describe "Routing" do
251
255
  assert_equal "4", body
252
256
  get "/mix-bar/4"
253
257
  assert_equal "4", body
258
+ get "/123"
259
+ assert_equal "/123", body
260
+ post "/123"
261
+ assert_equal "/123", body
262
+ delete "/drugs/123/destroy"
263
+ assert_equal "/drugs/123/destroy", body
264
+ delete "/123/destroy"
265
+ assert_equal "/123/destroy", body
254
266
  end
255
267
 
256
268
  it 'should generate url with format' do
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.12.2
4
+ version: 0.12.3
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: 2014-05-12 00:00:00.000000000 Z
14
+ date: 2014-08-13 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: padrino-support
@@ -19,14 +19,14 @@ dependencies:
19
19
  requirements:
20
20
  - - '='
21
21
  - !ruby/object:Gem::Version
22
- version: 0.12.2
22
+ version: 0.12.3
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - '='
28
28
  - !ruby/object:Gem::Version
29
- version: 0.12.2
29
+ version: 0.12.3
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: sinatra
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -61,14 +61,14 @@ dependencies:
61
61
  requirements:
62
62
  - - ~>
63
63
  - !ruby/object:Gem::Version
64
- version: 0.18.0
64
+ version: '0.18'
65
65
  type: :runtime
66
66
  prerelease: false
67
67
  version_requirements: !ruby/object:Gem::Requirement
68
68
  requirements:
69
69
  - - ~>
70
70
  - !ruby/object:Gem::Version
71
- version: 0.18.0
71
+ version: '0.18'
72
72
  - !ruby/object:Gem::Dependency
73
73
  name: activesupport
74
74
  requirement: !ruby/object:Gem::Requirement
@@ -124,9 +124,13 @@ files:
124
124
  - lib/padrino-core/cli/adapter.rb
125
125
  - lib/padrino-core/cli/base.rb
126
126
  - lib/padrino-core/cli/console.rb
127
+ - lib/padrino-core/cli/launcher.rb
127
128
  - lib/padrino-core/cli/rake.rb
128
129
  - lib/padrino-core/cli/rake_tasks.rb
129
130
  - lib/padrino-core/command.rb
131
+ - lib/padrino-core/ext/http_router.rb
132
+ - lib/padrino-core/ext/sinatra.rb
133
+ - lib/padrino-core/filter.rb
130
134
  - lib/padrino-core/images/404.png
131
135
  - lib/padrino-core/images/500.png
132
136
  - lib/padrino-core/loader.rb
@@ -149,6 +153,8 @@ files:
149
153
  - test/fixtures/apps/complex.rb
150
154
  - test/fixtures/apps/demo_app.rb
151
155
  - test/fixtures/apps/demo_demo.rb
156
+ - test/fixtures/apps/helpers/class_methods_helpers.rb
157
+ - test/fixtures/apps/helpers/instance_methods_helpers.rb
152
158
  - test/fixtures/apps/helpers/support.rb
153
159
  - test/fixtures/apps/helpers/system_helpers.rb
154
160
  - test/fixtures/apps/kiq.rb
@@ -159,6 +165,8 @@ files:
159
165
  - test/fixtures/apps/simple.rb
160
166
  - test/fixtures/apps/static.rb
161
167
  - test/fixtures/apps/system.rb
168
+ - test/fixtures/apps/system_class_methods_demo.rb
169
+ - test/fixtures/apps/system_instance_methods_demo.rb
162
170
  - test/fixtures/dependencies/a.rb
163
171
  - test/fixtures/dependencies/b.rb
164
172
  - test/fixtures/dependencies/c.rb
@@ -217,6 +225,8 @@ test_files:
217
225
  - test/fixtures/apps/complex.rb
218
226
  - test/fixtures/apps/demo_app.rb
219
227
  - test/fixtures/apps/demo_demo.rb
228
+ - test/fixtures/apps/helpers/class_methods_helpers.rb
229
+ - test/fixtures/apps/helpers/instance_methods_helpers.rb
220
230
  - test/fixtures/apps/helpers/support.rb
221
231
  - test/fixtures/apps/helpers/system_helpers.rb
222
232
  - test/fixtures/apps/kiq.rb
@@ -227,6 +237,8 @@ test_files:
227
237
  - test/fixtures/apps/simple.rb
228
238
  - test/fixtures/apps/static.rb
229
239
  - test/fixtures/apps/system.rb
240
+ - test/fixtures/apps/system_class_methods_demo.rb
241
+ - test/fixtures/apps/system_instance_methods_demo.rb
230
242
  - test/fixtures/dependencies/a.rb
231
243
  - test/fixtures/dependencies/b.rb
232
244
  - test/fixtures/dependencies/c.rb