Migrating from Drupal to Rails - Routing - ruby-on-rails

I've developed a new Ruby on Rails site for my organization. I want the new Rails site to intercept incoming requests that were meant for the old site and display a message for the user indicating that the new site is launched, a link the new URL they were most likely trying to get to, and a reminder to update bookmarks.
So I'm pretty green when in comes to rails routing so I'm asking how would you do this. Is there a 'rails way'?
Here are my thoughts so far.
The old site does not use clean urls so every request goes to the default route which in the new site is the home controller with a query string. I was thinking in the controller I can test to see if params[:q] is set and then depending on what the q parameter is, search for and render the an info page directing the user to the new link. If the q parameter doesn't make sense (I don't care about catching every page on the old site, just the important ones) redirect to a custom 404 page informing the user that the link was probably for the old site, and give the user a search page.
Any thoughts, is there a better way?
I appreciate any input.
Thanks

In your Rails controller responsible for the homepage (let's say it's HomeController) add before_filter like so:
class HomeController < ActionController::Base
before_filter :handle_drupal_requests, :only => :index
Then add the handler method itself handle_drupal_requests like so.
class HomeController < ActionController::Base
before_filter :handle_drupal_requests, :only => :index
# ... other code ...
private
def handle_drupal_requests
if params[:q].present?
flash[:notice] = "You're being redirected because blah."
redirect_to convert_drupal_url(params[:q]), :status => 301
end
end
def convert_drupal_url(query_string)
# your logic for converting query string, for example:
item, id = query_string.split('&').last.split('=')
item_controller = item.underscore.split('_').first.pluralize
{:controller => item_controller, :action => "show", :id => id}
end
end

Is there a consistent way that the URLs have changed? Such as /?q=pie becoming /dessert/pie ?
If not, and it requires some sort of manual db query, you'll have to do it the way you mentioned. I would create a redirect action that catches all the paths to keep it separate from your home/index action.
Also, if you care about SEO juice, make sure to use a 301 redirect:
redirect_to dessert_url, :status=>301
You would then have to do an instant redirect (no intermediate page saying 'update your bookmark'). What I would do is the instant redirect, and put a flash[:notice] message saying to "please update your bookmarks".
Please post some examples of URLs if you need more direct examples.

Related

How to skip_before_filter for a redirect in a action method?

I have a controller which has several methods and one of them has a redirect at the end.
def launch
do_something
params[:hey] = "heyo"
redirect_to("/tasks")
end
All actions has a before_filter which sets some access control headers.
What i want is;
I want to have this before filter for "launch" method, but not for the redirect in it.
How can i achieve this ?
When i set this below, it removes filter for both launch method and "/tasks" redirect, but i only want to remove it for the redirect.
skip_filter :set_access_control_headers, :only => :launch
Thanks in advance!
Update:
This method lives in an engine, that's why I have different access control headers than main application. I do not want to mess with main applications code since i create specific engine and routes for each customer.
And the redirect in the end goes to main application.
You can set param in your redirect and in filter check if param is not exist than skip
Example: redirect_to edit_multiple_items_path, :notice => 'items updated', {:page => ##, :method => 'GET'}
It might be because I focused too much on doing it the "Rails" way.
I fixed the issue by simply removing the headers manually just before the redirect and it all worked fine now.
headers.delete('Access-Control-Allow-Origin')
headers.delete('Access-Control-Request-Method')
headers.delete('Access-Control-Allow-Methods')
redirect(/tasks?#{options.to_query})
Thanks for the answers though!

How to setup routes when the controller only has edit and update?

I can't seem to figure out how to get my routes setup properly.
In my app, I have a view that lets site owners update their address information. The new and create actions are part of the signup process and are located in the signups_controller. The edit and update actions are in the settings_controller.
When the user goes into the settings area, he/she sees only the edit form. When filled out, the user is then returned to the same form with a flash message, or error message. Here is what the controller looks like:
class SettingsController < ApplicationController
def edit
#account = current_account
#account.companies.first
#account.companies.first.addresses.first
#account.companies.first.phones.first
end
def update
#account = current_account
if #account.update_attributes(params[:account])
redirect_to edit_setting_path
flash[:notice] = "Success!"
else
render :edit
end
end
end
In my routes, I simply have:
resources :settings
The link to this area of the site is a basic RESTful named linke, with the parameter options:
edit_setting_path(:id => current_account.id)
When the user arrives to this page, they see the following URL:
http://domainname.com/settings/1/edit
When they submit the form and get errors, the URL changes to:
http://domainname.com/settings/1
Why is the URL changing -- I'd rather it not? Is there a way to make it stay the same as the initial edit view? I've tried doing a redirect on a failed update, but then I don't get the error messages.
Any ideas?
To answer your "why" question: The URL is changing because it's reflecting the URL of the failed request - which in this case is a PUT request to that URL (/settings/1). You've submitted the form and the submission of that form (correctly) points to that URL. This is a result of the RESTful routes that the helper gives you. Since the logic in your action, falls through to the render :action, there is no redirect and the form simply re-renders on the page using the same data available in this action (which is why you can see the errors).
If you want to redirect back to the edit page, yes, you will lose the errors that have been set in the #account instance variable since the redirect will reset (re-query for) the account.
You could add a route that matches a PUT to /settings/1/edit and point it to your update action and change your form etc. In short, I wouldn't recommend this, but it should work.
completely untested but attemptable:
routes.rb
put "/settings/:id/edit", :to=>"settings#update", :as=>"update_setting"
resources :settings, :except=>:update
your form would also have to submit to the update_setting_path (which also means it's not reusable for a new object... ew)
First you should read up on The Rails Guides for Routing. They will help a lot to understand why its working like that.
Secondly, to accomplish what you are trying to do, you will need to add manual routes via the match call. You'll need something like this.
match '/settings/:id/edit' => "settings#edit"

No route matches - after login attempt - even though the route exists?

I am working on a rails application and added a simple login system according to a book.
I created the controller admin:
rails generate controller admin login logout index
It added the following routes to routes.db
get "admin/login"
get "admin/logout"
get "admin/index"
I can got to http://localhost:3000/admin/login there is no problem at all.
But when I try to login I get: No route matches "/admin/login"!
Now, the first confusing part is that the "login" method of my AdminController is not executed at all.
The second confusing part is that this code works like a charm - redirects everything to /admin/login:
def authorize
unless User.find_by_id(session[:user_id])
flash[:notice] = "you need to login"
redirect_to :controller => 'admin', :action => 'login'
end
end
Sidenotes:
I restarted the server several times.
I tried a different browser - to be sure there is no caching problem.
Try
match "/admin/login" => "admin#login"
match "/admin/logout" => "admin#logout"
match "/admin/index" => "admin#index"
(notice the leading /)
As an aside, unless you're creating a login system to learn about Rails and/or authentication, you're probably better off using something like Devise.
Following on from David Sulc's answer:
You're defining the routes as get requests, meaning to go to them you must perform a GET /admin/login request which is basically what happens when you type the URL into your address bar or follow a link that uses it.
However when you try to use these URLs in a form, the form does a POST request and because you've defined all of these as get-only requests, Rails will not be able to find a compatible route.
I definitely agree with David that you should look at an alternative system such as Devise.

How to go 'back' 2 levels?

From the list view of my app, I can view a list of records or drill down and edit/update a record. After updating, I want to go directly back to the list view, bypassing a couple of intermediate pages - but I don't simply want to link_to(:action => list) - there's pagination involved. I want to go back to the exact 'list' page I came from. What's the best way? Pass a hidden arg somewhere with the page number? Is there an elegant way to accomplish this?
I'm just going to throw this one out there with the disclaimer that there may be security considerations or existing gems.
On your edit action, you could store the previous page in a session. Then in your update action, redirect to it.
class MyController < ApplicationController
def edit
session[:prev_url] = request.referer
end
def update
redirect_to session[:prev_url]
end
end
As an alternative to use the session, you could carry the referer through the actions using a hidden form field.
class MyController < ApplicationController
def edit
#prev_url = request.referer
end
def update
redirect_to params[:prev_url]
end
end
Form using hidden_field:
f.hidden_field :prev_url, :value => #prev_url
If you do not want to carry along the whole referer url you could also do the same with the page parameter instead and append the parameter to the url in the update action. I would also expect Rails' url helpers to accept parameters.

Rails3 - routing: How do you create a root path for a database-driven item?

Background info
I have an app where users can make microsites ala http://myname.the_app.com.
Microsite has_many :pages
Each Microsite belongs_to :landing_page (which is a Page) that determines where the visitor is fowarded when they view the site. Right now the app does a redirect_to #microsite.landing_page. The visitor then sees a url like so: `http://myname.the_app.com/pages/id
How can I render the landing page but keep the root path? I want to be able to see the "about page" but with the url http://myname.the_app.com.
An option
Here's an option: have a home_controller#index action that instantiates all the page variables it needs. However... I'm holding this off because what if I have more than page? What if I want the landing_page to be something else in the future, like a contact_form located at `/contact_forms/id?
Thanks!
Perhaps render :template => "pages/#{whatever_id}" might solve your problem. Just replace your redirect_to with the render...

Resources