Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Properly reload routes defined in class definition

Sometimes it's easier to define routes inside Engine or
Application class definition (e.g. one file applications). The
problem with such case is that if there is a plugin that
has config/routes.rb file, it will trigger routes reload on application.
Since routes definition for application is not in config/routes.rb
file routes_reloader will fail to reload application's routes
properly. With this commit you can pass routes definition as a block
to routes method, which will allow to properly reload it:

class MyApp::Application < Rails::Application
  routes do
    resources :users
  end
end
  • Loading branch information...
commit ec5d846ac6137e60d81257041e4fde82c0480b32 1 parent 22b11a4
Piotr Sarnacki drogus authored
1  actionpack/lib/action_dispatch/routing/route_set.rb
View
@@ -1,6 +1,7 @@
require 'rack/mount'
require 'forwardable'
require 'active_support/core_ext/object/to_query'
+require 'active_support/core_ext/hash/slice'
module ActionDispatch
module Routing
21 railties/lib/rails/application.rb
View
@@ -85,13 +85,24 @@ def routes_reloader
end
def reload_routes!
- _routes = self.routes
- _routes.disable_clear_and_finalize = true
- _routes.clear!
+ routes_to_reload.each do |_routes, draw_block|
+ _routes = self.routes
+ _routes.disable_clear_and_finalize = true
+ _routes.clear!
+ _routes.draw(&draw_block) if draw_block
+ end
routes_reloader.paths.each { |path| load(path) }
- ActiveSupport.on_load(:action_controller) { _routes.finalize! }
+ routes_to_reload.each do |_routes, draw_block|
+ ActiveSupport.on_load(:action_controller) { _routes.finalize! }
+ end
ensure
- _routes.disable_clear_and_finalize = false
+ routes_to_reload.each do |_routes, draw_block|
+ _routes.disable_clear_and_finalize = false
+ end
+ end
+
+ def routes_to_reload
+ @routes_to_reload ||= {}
end
def initialize!
7 railties/lib/rails/engine.rb
View
@@ -399,8 +399,10 @@ def env_config
}
end
- def routes
+ def routes(&block)
@routes ||= ActionDispatch::Routing::RouteSet.new
+ self.routes_draw_block = block if block_given?
+ @routes
end
def initializers
@@ -447,6 +449,7 @@ def load_seed
end
initializer :add_routing_paths do |app|
+ app.routes_to_reload[self.routes] = routes_draw_block
paths.config.routes.to_a.each do |route|
app.routes_reloader.paths.unshift(route) if File.exists?(route)
end
@@ -499,6 +502,8 @@ def load_seed
end
protected
+ attr_accessor :routes_draw_block
+
def find_root_with_flag(flag, default=nil)
root_path = self.class.called_from
40 railties/test/railties/engine_test.rb
View
@@ -663,5 +663,45 @@ class Engine < ::Rails::Engine
assert_equal AppTemplate._railtie, AppTemplate::Engine
end
+
+ test "properly reload routes" do
+ # when routes are inside application class definition
+ # they should not be reloaded when engine's routes
+ # file has changed
+ add_to_config <<-RUBY
+ routes do
+ mount lambda{|env| [200, {}, ["foo"]]} => "/foo"
+ mount Bukkits::Engine => "/bukkits"
+ end
+ RUBY
+
+ FileUtils.rm(File.join(app_path, "config/routes.rb"))
+
+ @plugin.write "config/routes.rb", <<-RUBY
+ Bukkits::Engine.routes.draw do
+ mount lambda{|env| [200, {}, ["bar"]]} => "/bar"
+ end
+ RUBY
+
+ @plugin.write "lib/bukkits.rb", <<-RUBY
+ module Bukkits
+ class Engine < ::Rails::Engine
+ namespace(Bukkits)
+ end
+ end
+ RUBY
+
+ require 'rack/test'
+ extend Rack::Test::Methods
+
+ boot_rails
+
+ require "#{rails_root}/config/environment"
+ get "/foo"
+ assert_equal "foo", last_response.body
+
+ get "/bukkits/bar"
+ assert_equal "bar", last_response.body
+ end
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.