Recursively redirecting in Rails 3 Routes - ruby-on-rails

We are updating our large web app and getting rid of our URL synonym system. For example, though we only use one model for 'advertiser', it is aliased to 'merchants' and 'sellers', using synonymous paths. Thus, /merchant/1 and /seller/1 use the same exact controller and action as advertiser/1.
We no longer need this functionality, but we do need for old URLs to correctly redirect users to the proper place (i.e. proper controller actions).
So far, I've tried:
1) reading http://guides.rubyonrails.org/routing.html - This lead me to try the following suggestions
2) match '/merchants' => redirect('/advertisers') - this didn't seem to work at all, though the syntax seems correct.
3) iterating over resources (this produces a TON of routes and may cause insecurities):
ADVERTISER_SYNONOYMS = ['affiliates', 'sellers']
ADVERTISER_SYNONYMS.each do |a|
resources :advertisers, :path => a, :as => :advertiser
resources :other_controller do
member do
get :test
match :generate_test
end
end
end
end
We use nested resources in our routes.rb, so I'm struggling with getting these synonymns to be recognized all throughout more complex URLs. If anyone dealt with this problem or has a more elegant suggestion, I'd be most grateful.

There are many ways to handle this, including additional routes in routes.rb like you've tried, or rewrites at the webserver level such as Apache or Nginx.
One solution I like is the rack-rewrite gem; it keeps routes clean and the rules are plain ruby. It provides a set of methods for configuring rewrites and redirects. For your situation, I would want to use permanent redirects. Though I haven't tested it out myself, something like the following may work for you:
# Gemfile
gem 'rack-rewrite'
# application.rb
config.middleware.use(Rack::Rewrite) do
r301 %r{/merchant|seller/(\w+)}, '/advertiser/$1'
end

Related

RSpec: Named routes or hard coded URLs?

In a Rails project, and in an RSpec spec file, what are the pros and cons for using a named route, such as blogs_path() vs a hard coded URL, such as /blogs?
I know the answer is highly opinionated, but it will help me (and many others) to get a view of the pros and cons of each approach.
It's the same as with any hardcoded stuff: harder to change later.
If you change your path from /blogs to /interesting_stuff_people_have_to_say it's a one line change if you're using the methods (named routes):
- get :blogs
+ get :blogs, as: :interesting_stuff_people_have_to_say
But if you hardcoded the path, you need to change it everywhere you used it. You might even miss some cases:
url = 'blog' + 's'
redirect_to url
Which will cause your specs to fail (if you're lucky and have this covered) or errors on production.

How to run copy of the app running on '/' on '/someurl' as well?

Let's say I have a site like Digg running on bookmarks.com and want to create bookmarks.com/girls which shares all the routes, but all the links point to /girls/<something> instead of just /<something>.
Without changing all the links in views, I would like to modify routes.rb to do something like this:
all_routes = lambda {
...
}
scope '/girls', &all_routes, constraint: { |r| r.session[:subsite] == girls }
scope '/', &all_routes
However I am stuck with trial and error and haven't been able to come up with a solution.
Bonus points: how would I route this, if I had dynamic multiple sub-sites?
I think you can achieve this by subclassing your Rails app, and then mounting it using Rack.mount in your routes
mount AnotherRailsApp, :at => "/something"
Alternatively, you could use a rackup file, so in config.ru:
map "/" do
run RailsApp::Application
end
map "/something" do
run AnotherRailsApp::Application
end
However, with either approach, I'm not sure Rails' helper methods for URLs will be able to generate valid URLs when mounted at "/something", and you're probably going to get some interesting issues with your data too, unless you have one db per app.

Namespace in rails routing

First, why do we need to namespace controllers?
The example on rails guides shows
namespace :admin do
resources :post, :comments
end
In this case, we have paths such as GET /admin/posts. Is it identical to GET /posts? Or is GET /posts kept as original while another GET /admin/posts is added as extra?
Does rails create any other stuff for namespace?
You dont have to use namespaces if you dont want to, but it's there to make your life easier, specially in big applications with a lot of controllers. And no, routes arent duplicated if you namespace them, unless you specify the route again in your route file without the namespace, but that doesnt make much sense.

What's the "Rails Way" to create route helpers to other hosts?

My app consists of two rails servers with mostly different concerns sitting behind a reverse proxy. Let's call them Server1 and Server2. Occasionally, Server1 needs to render a link to a url on Server2. Is there a good way to use Rails route helpers for this? Specifically in Rails 2? I came up with this:
ActionController::Routing::Routes.draw do |map|
# other routes omitted
map.with_options(:host => 'server2.example.com') do |add|
# create a named route for 'http://server2.example.com/thingies'
add.server2_thingies '/thingies', :controller => 'fake'
# create a named route for 'http://server2.example.com/thingies/combobulate'
add.enhance_server2_thingies '/thingies/combobulate', :controller => 'fake'
# create a named route for 'http://server2.example.com/mabobs/combobulate'
add.enhance_server2_mabobs '/mabobs/combobulate', :controller => 'fake'
# etc..
end
end
So then I can use server2_thingies_url and such in my views. This works, but it makes me feel like a bad person because there is no FakeController and I certainly have no intention of routing requests to it. I considered making helper methods and placing them in app/controllers/application_controller.rb, but a colleague made the argument that it is best to keep all route helpers in routes.rb, so things like rake routes will be accurate, for instance. Is there a better way?
I think I'd make a counter-argument to your colleague: if you're having to dirty up routes.rb with a "FakeController", then your rake routes is still not going to be accurate. In fact, I'd say that this is exactly the kind of thing that a helper was meant to help: it's taking logic that belongs purely in the view (link generation), and removing it from your view templates. Helpers are also easier to maintain and tweak.
Another advantage to the helper style is that if and when it's time to upgrade to Rails 3.x, the less hackish your routes.rb file is, the happier you will be - and that I can attest to from experience. :)
I'd just pass in :host to your foo_path or foo_url calls.
Seems cleaner than messing around with a FakeController

Namespaced routes in rails 1

I'm working with some legacy code with the last version of rails 1. Upgrading to a later version of rails isn't possible and as such map.namespace is a private method in this version, otherwise I'd be using it.
I have several resources which I have nested into a submenu for simplicity. Their controllers are all within the folder of that submenu and all inherit that controller's namespace.
I'm having major issues with the sub elements. I have mapped the resources and applied a prefix to them in the form of
map.resources :subitem, :path_prefix => "/sub_menu"
but I'm having major issues with using RESTFul methods on these nested objects. The paths that I'm trying to use, say to delete an object simply do not work.
I'm refactoring this current code base so there's very little I can do, and there's very little I can find on rails 1 routes online. It's a bit of a finicky issue but maybe I've missed something simple about routes.
Do I simply need to manually write out every particular route I can use and then manually prefix it, or is there a simpler way?
My other routes work fine, I simply cannot use the
subitem_path(subitem) :method => :delete
function in my link to
So I figured out how to layout the routes appropriately so I could access the paths
Add to the above route the specified controller you're using and the routes will map accordingly
map.resources :subitem, :path_prefix => "/sub_menu, :controller => "submenu/subitem"
Thanks!

Resources