Splitting Routes File Into Multiple Files - ruby-on-rails

I'm working w/ a Rails 3 application and I want to split up the routes into separate files depending on the subdomain. Right now I have this in my routes.rb file:
Skateparks::Application.routes.draw do
constraints(:subdomain => 'api') do
load 'routes/api.rb'
end
end
And In my routes/api.rb file I have:
resources :skateparks
This doesn't seem to work though because if I run rake routes I get
undefined method `resources' for main:Object
Also, if I try to navigate to http://0.0.0.0:3000/ I get:
Routing Error
No route matches "/"

In Rails 3.2, config.paths is now a hash, so #sunkencity's solution can be modified to:
# config/application.rb
config.paths["config/routes"] << File.join(Rails.root, "config/routes/fooroutes.rb")

Sunkencity's answer seems to be identical to the following link, but for completeness' sake: https://rails-bestpractices.com/posts/2011/05/04/split-route-namespaces-into-different-files/
Note that routes defined later will override routes defined earlier. However, if you use something like
config.paths.config.routes.concat(
Dir[Rails.root.join('config/routes/*.rb')])
you don't know in what order the files will be read. So use
config.paths.config.routes.concat(
Dir[Rails.root.join('config/routes/*.rb')].sort)
instead, so you at least know they will be in alphabetical order.

Add the route file to the app route loading path:
# config/application.rb
config.paths.config.routes << File.join(Rails.root, "config/routes/fooroutes.rb")
Wrap your other route file in a block like this.
#config/routes/fooroutes.rb
Rails.application.routes.draw do |map|
match 'FOO' => 'foo/bar'
end
Works for me in rails 3.0

We used this in our app:
config.paths['config/routes'] = Dir["config/routes/*.rb"]
If you try to access config.paths['config/routes'] normally, it returns the relative path to config/routes.rb, so by doing the above you're giving it relative paths to all of the files in your routes folder and removing the reference to config/routes.rb

Related

Rails application without routes.rb file

I am new to RoR and I have an API rails application that does not have routes.rb file.
I know it works but I don't know how.
What are the possible approaches(exept routes.rb file) to route requests?
In rails it's not necessary to have a routes.rb file. Any file/files inside config directory might have route destination like this:
Rails.application.routes.draw do
# Your routes here ..
end

Rails scaffold built table called assets - now route errors

I used scaffold to build a table called "assets". The files were created. The "rake db:create" worked fine. I added " resources :assets" to my routes.rb file. I now get route errors. I ran "rake routes" and none of the routes for "assets" show up.
Is it bad to use a table name "assets"?
Or is something else wrong?
The asset pipeline uses /assets by default.
You can either change the default assets path by using this in application.rb:
config.assets.prefix = '/something-else'
Or change the routing for your assets resource by using:
resources :assets, :path => 'something-else'
edit: Actually the second option is probably the better choice because I forgot that asset_path is available by default and belongs to the asset pipeline. If you changed your default assets prefix and used asset_path #asset hoping to generate a link to assets#show then it might cause problems.
Use the :as option in your routes to change the path/url methods it generates.
resources :assets, :path => 'things', :as => 'things'
things_path results in /things and routes to the index action of the assets controller
thing_path #asset results in /things/:id and routes to the show action of the assets controller
etc.

Overriding named routes provided by Rails 3 Engines

I am working on a Ruby on Rails 3(.0) application that uses a Rails engine. However, in my local application, I want to override one of the routes provided by the Rails engine.
From the engine config/routes.rb:
match 'their_named_route' => 'controller#action', :as => 'the_route'
From my application config/routes.rb:
match 'my_named_route' => 'controller#action', :as => 'the_route'
However, when I inspect the routes, both seem to be active (and their route appears to "win", at least within the engine controllers)
$ rake routes
the_route /my_named_route(.:format) {:controller=>"controller", :action=>"action"}
the_route /their_named_route(.:format) {:controller=>"controller", :action=>"action"}
Is there a good way to force my local application's named route to take priority?
I got around this by moving my engine's routes from config/routes.rb to a class method in the engine class itself:
module MyEngine
class Engine < Rails::Engine
def self.routes
MyRailsApp::Application.routes.draw do
resources :products
end
end
end
end
and then in the base app's routes file:
MyRailsApp::Application.routes.draw do
# Routes for base app including the ones overriding MyEngine::Engine.
MyEngine::Engine.routes
end
I can then happily override any routes in the base app with those in the engine.
Note that the overriding routes need to be defined before the overridden routes since the earlier defined routes take precedence over later ones.
I'm afraid that there's no such easy way. The routes are defined in lib/action_dispatch/routing/mapper.rb:271, which calls add_route on the RouteSet (defined in rack-mount-0.6.14/lib/rack/mount/route_set.rb, and on line 71 the name is attached). There's no remove_route method, and the Engine's route is added last. You can add your route manually after the application is initialized with Rails.application.routes.draw instead of having it in routes.rb, or you can patch the Engine.
There is no way to override a route within an engine. Instead, you must define an overruling route. You can do this by calling prepend on the engine's router:
An::Engine.routes.prepend do
root :to => "somewhere#action"
end
If the engine's namespace is isolated, this will use the SomewhereController from inside the engine's namespace. If not, it will use the typical SomewhereController.
If you want to override a route to return a 404, the best way I can think of is to redirect to a 404 page:
match "/route_goes_here" => redirect("/404")
You need add initializer hook to config/application.rb, like this:
class Application < Rails::Application
config.encoding = "utf-8"
...
initializer :add_routing_paths do |app|
their_routes_path = app.routes_reloader.paths.select{|path| path =~ /DIR/}.first
app.routes_reloader.paths.delete(their_routes_path)
app.routes_reloader.paths.unshift(their_routes_path)
end
end
It's load roues.rb of you engine first and you can override their routes.
You can prepend routes as suggest by Ryan Bigg above. I found that in order overrule the named route helper with my custom route I need to call append instead of prepend, like so:
An::Engine.routes.append do
root :to => "somewhere#action"
end
Otherwise the app contains both routes and the named helper for engine's router is the last definition, and therefore the one that is applied.
Routing rules defined in routes.rb are applied from the top down until a match is found. I was able to override the route defined in the mounted engine simply by moving the higher-priority rule above the line where the engine is mounted. So,
get 'about', controller: 'static', action: 'about', as: 'about'
mount My::Engine => '/'
results in the app routing /about/ requests to (in this case) the static controller, whereas:
mount My::Engine => '/'
get 'about', controller: 'static', action: 'about', as: 'about'
results in the app routing /about/ requests to the route defined in the mounted engine.
To Replace the default routes path provided by gem or engine we can achive that in following way.
For me I wanted to replace 'spree_user' with 'account' etc from all routes
/user/spree_user/sign_in I did this in following way
Step 1
Create config/some_engine_route_override.rb
Copy the content of engine route file and update the routes as per need
Step 2
in application.rb use the folllowing hook
# Override Spree Core routes in order to translate products routes
initializer "delete_spree_core_routes", after: "add_routing_paths" do |app|
new_spree_auth_route_path = File.expand_path('../../config/some_engine_route_override.rb', __FILE__)
routes_paths = app.routes_reloader.paths
spree_devise_auth_route_path = routes_paths.select{ |path| path.include?("spree_auth_devise") }.first
if spree_devise_auth_route_path.present?
spree_core_route_path_index = routes_paths.index(spree_devise_auth_route_path)
routes_paths.delete_at(spree_core_route_path_index)
routes_paths.insert(spree_core_route_path_index, new_spree_auth_route_path)
end
end

Sinatra & Rails 3 routes issue

I have just setup Sinatra v1.1.0 inside my rails (v3.0.1) app. But I can't invoke any routes that are more than 1 level deep, meaning this works - http://localhost/customer/3,
but this one does not work - http://localhost/customer/3/edit and I get a "Routing Error"
Here's the Sinatra object
class CustomerApp < Sinatra::Base
# this works
get "/customer/:id" do
"Hello Customer"
end
# this does NOT work
get "/customer/:id/edit" do
"Hello Customer"
end
end
This is what I have in my rails routes.rb file -
match '/customer/(:string)' => CustomerApp
I am guessing I need some magic in the routes file? What could be the problem?
In your routes file, you can specify the mapping this way:
mount CustomerApp, :at => '/customer'
Now, inside your sinatra application, you can specify your routes without the /customer part.
Dont't forget to require your sinatra application somewhere (you can do it directly in the route file)
You need to add an additional route to match the different URL:
match '/customer/(:string)/edit' => CustomerApp

Recognize routes in rails console Session

Say I have a router helper that I want more info on, like blogs_path, how do I find out the map statements behind that in console.
I tried generate and recognize and I got unrecognized method error, even after I did require 'config/routes.rb'
There is a good summary with examples at Zobie's Blog showing how to manually check URL-to-controller/action mapping and the converse. For example, start with
r = Rails.application.routes
to access the routes object (Zobie's page, a couple years old, says to use ActionController::Routing::Routes, but that's now deprecated in favor of Rails.application.routes). You can then check the routing based on a URL:
>> r.recognize_path "/station/index/42.html"
=> {:controller=>"station", :action=>"index", :format=>"html", :id=>"42"}
and see what URL is generated for a given controller/action/parameters combination:
>> r.generate :controller => :station, :action=> :index, :id=>42
=> /station/index/42
Thanks, Zobie!
In the console of a Rails 3.2 app:
# include routing and URL helpers
include ActionDispatch::Routing
include Rails.application.routes.url_helpers
# use routes normally
users_path #=> "/users"
Basically(if I understood your question right) it boils down to including the UrlWriter Module:
include ActionController::UrlWriter
root_path
=> "/"
Or you can prepend app to the calls in the console e.g.:
ruby-1.9.2-p136 :002 > app.root_path
=> "/"
(This is all Rails v. 3.0.3)
running the routes command from your project directory will display your routing:
rake routes
is this what you had in mind?
If you are seeing errors like
ActionController::RoutingError: No route matches
Where it should be working, you may be using a rails gem or engine that does something like Spree does where it prepends routes, you may need to do something else to view routes in console.
In spree's case, this is in the routes file
Spree::Core::Engine.routes.prepend do
...
end
And to work like #mike-blythe suggests, you would then do this before generate or recognize_path.
r = Spree::Core::Engine.routes

Resources