Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove Routes Specified in a Gem?

Is there a way to remove routes specified in a gem in Rails 3? The exception logger gem specifies routes which I don't want. I need to specify constraints on the routes like so:

scope :constraints => {:subdomain => 'secure',  :protocol => 'https'} do 
    collection do
        post :query
        post :destroy_all
        get :feed
    end
end

Based on the Rails Engine docs, I thought I could create a monkey patch and add a routes file with no routes specified to the paths["config/routes"].paths Array but the file doesn't get added to ExceptionLogger::Engine.paths["config/routes"].paths

File: config/initializers/exception_logger_hacks.rb

ExceptionLogger::Engine.paths["config/routes"].paths.unshift(File.expand_path(File.join(File.dirname(__FILE__), "exception_logger_routes.rb")))

Am I way off base here? Maybe there is a better way of doing this?

like image 455
EDD Avatar asked May 05 '11 02:05

EDD


2 Answers

It is possible to prevent Rails from loading the routes of a specific gem, this way none of the gem routes are added, so you will have to add the ones you want manually:

Add an initializer in application.rb like this:

class Application < Rails::Application
...
initializer "myinitializer", :after => "add_routing_paths" do |app|
  app.routes_reloader.paths.delete_if{ |path| path.include?("NAME_OF_GEM_GOES_HERE") }
end
like image 196
Robban Avatar answered Oct 12 '22 12:10

Robban


Here's one way that's worked for me.

It doesn't "remove" routes but lets you take control of where they match. You probably want every route requested to match something, even if it is a catch all 404 at the bottom.

Your application routes (MyApp/config/routes.rb) will be loaded first (unless you've modified the default load process). And routes matched first will take precedence.

So you could redefine the routes you want to block explicitely, or block them with a catch all route at the bottom of YourApp/config/routes.rb file.

Named routes, unfortunately, seem to follow ruby's "last definition wins" rule. So if the routes are named and your app or the engine uses those names, you need to define the routes both first (so yours match first), and last (so named routes point as you intended, not as the engine defines.)

To redefine the engine's routes after the engine adds them, create a file called something like

# config/named_routes_overrides.rb
Rails.application.routes.draw do
  # put your named routes here, which you also included in config/routes.rb
end

# config/application.rb
class Application < Rails::Application
  # ...

  initializer 'add named route overrides' do |app|
    app.routes_reloader.paths << File.expand_path('../named_routes_overrides.rb',__FILE__) 
    # this seems to cause these extra routes to be loaded last, so they will define named routes last.
  end
end

You can test this routing sandwich in the console:

> Rails.application.routes.url_helpers.my_named_route_path
=> # before your fix, this will be the engine's named route, since it was defined last.

> Rails.application.routes.recognize_path("/route/you/want/to/stop/gem/from/controlling")
=> # before your fix, this will route to the controller and method you defined, rather than what the engine defined, because your route comes first.

After your fix, these calls should match each other.

(I posted this originally on the refinery gem google group here: https://groups.google.com/forum/?fromgroups#!topic/refinery-cms/N5F-Insm9co)

like image 21
Anatortoise House Avatar answered Oct 12 '22 11:10

Anatortoise House