URL Rewrite Ruby on Rails - ruby

We have a Redmine installation on an old server and moved it to a new one with a new domain. Problem is, we need to redirect urls from the old domain to the new one. I really don't have much knowledge about ruby. I was thinking redirecting URLs on this one is as easy as some rewrite rules with .htaccess but I found it different. I've read some answers here redirect but can't figure out where to put those codes.
The scenario should be like:
from http://www.old-domain.com:3000/issues/3456
should be redirected to http://www.new-domain.com:3000/issues/3456
Can anyone help me how to do this? Or if you have better idea how to achieve this?
I'm planning on reading some ruby guides for the meantime.
Thanks guys!
Update:
I managed to create a simple redirect by doing the following:
I created a controller redirect_controller.rb:
class RedirectController < ApplicationController
before_filter :show
def show
redirect_to "http://www.new-domain.com:3000/", :status => :moved_permanently, :notice => "Notice: A redirect!!!"
end
end
And added this to routes.rb:
map.connect '/', :controller => 'redirect'
But I only managed to redirect the page after a successful login. How can I redirect all pages to the new one retaining parameters such as /issues/3456 if there are any?

You can go to your application.rb file (I found it better than place the redirection in the application controller), which is loaded to start all the rails and all engines. The key here is to use
head :moved_permanently, :location => "http://www.newdomain.com/"
To call that you can wrap it in a method I found in a blog. I added some comment
def perm_redirect_to(options)
url = case options
when String # if you pass a string url, which is your case
options
else
url_for(options) # if you pass some more complex option hash in
# `options`, which doesn't seem to be your case
end
head :moved_permanently, :location => url
end
You can call this method passing your url perm_redirect_to(your_new_url)!

Related

No route matches [GET] "/"...Sometimes

So I'm a bit of a Rails n00b, so I'll apologize if this is really simple. When I access my server from another computer, I get this message:
No route matches [GET] "/"
And if I try to go to my subpages (Well, currently I only have one), I get something along these lines:
Unknown action
The action 'index' could not be found for AwebpageController
But here's the catch: this only happens sometimes. The rest of the time, the standard RoR homepage loads, and going to wwww.mydomain.com/awebpage serves up the page fine.
My Routes.rb looks like this:
Wobsite::Application.routes.draw do
resources :awebpage
end
And awebpage_controller.rb looks like this:
class AwebpageController < ApplicationController
end
And yes, index.html.erb for Awebpage does exist. It's all so simple that I don't understand what's going wrong. Oh, and my webserver is Thin (Not sure if that matters). Thanks in advance for any help!
You might want to add this to the top of your routes file to set the default controller and page for your site (i.e. http://www.mysite.com/):
root :to => "AwebpageController#index"
To remove the default Ruby on Rails webpage you'll also want to delete the index.html file in your /public/ directory.
Also, although not required, in your controller you're missing the function definition for index.
class AwebpageController < ApplicationController
def index
end
end
Normally you'd do application logic and serve up a view in this function; however if you do nothing RoR automatically loads the view associated with the page (index.html.erb).
If after all this you're still having a problem perhaps explicitly add index to the AwebpageController in your routes file; perhaps rails is only mapping www.mysite.com/Awebpage/ to Awebpage/index and not www.mysite.com/Awebpage/index.

Override "show" resource route in Rails

resources :some_resource
That is, there is a route /some_resource/:id
In fact, :id for some_resource will always be stored in session, so I want to override the path /some_resource/:id with /some_resource/my. Or I want to override it with /some_resource/ and remove the path GET /some_resource/ for index action.
How can I reach these two goals?
In your routes.rb put:
get "some_resource" => "some_resource#show"
before the line
resources :some_resource
Then rails will pick up your "get" before it finds the resources... thus overriding the get /some_resource
In addition, you should specify:
resources :some_resource, :except => :index
although, as mentioned, rails won't pick it up, it is a good practice
Chen's answer works fine (and I used that approach for some time), but there is a standardized way. In the Official Rails Guides the use of collection routes is preferred.
Collection routes exist so that Rails won't assume you are specifying a resource :id. In my opinion this is better than overriding a route using precedence within the routes.rb file.
resources :some_resource, :except => :index do
get 'some_resource', :on => :collection, :action => 'show'
end
If you need to specify more than collection route, then the use of the block is preferred.
resources :some_resource, :except => :index do
collection do
get 'some_resource', :action => 'show'
# more actions...
end
end

Rack middleware how to redirect to a view in my Rails application

In my Rails 3.1 app I created a Rack Middleware to verify access. If access is not approved user is to be redirected to a page. Specifically it will be a page I already have in my views. Suppose I am trying to redirect to dummy.html.erb with I have defined in my routes.rb as
match '/dummy', to :'page#dummy'
with page being my controller.
I've tried the following but I appear to be stuck in some redirect loop.
My Rack middleware located in /lib :
class AccessVerifier
def initialize(app)
#app = app
end
def call (env)
#....
#....do some type of verification here and redirect if fail verification
#....
[301, {"Location" => '/dummy', "Content-Type" => "text/html"}, []]
end
end
In application.rb I have
config.autoload_paths += %W(#{config.root}/lib)
config.middleware.use "AccessVerifier"
I also tried calling a controller in my middleware but again I am caught in some redirect loop. I called the controller from my middleware class like this:
def call (env)
...
status,headers,response=PageController.action("validateAccess").call(env)
end
and in my controller:
class PageController < ApplicationController
def validateAccess
redirect_to :controller => 'page', :action => "dummy"
end
...
end
I've seen redirecting done successfully without the use of Rack Middleware, for example only with controllers, but please note that I need to do this in middleware before my application is run.
The answer is so simple I felt silly. The problem is that when I redirect to somewhere say /dummy that in turns causes another pass through the Rack middleware and goes through my AccessVerifier code all over again which redirects to /dummy and does this over and over again thus causing the redirect loop. To fix it I force a stopping point by checking if the incoming path is included in the list of my stopping points(with /dummy being in that list) then stop. So an example in pseudo code
if path in ListOfAcceptableStoppingPoints
#app.call(env)
This fixes the redirect loop issue but now I am questioning if it would be better for my specific case to not use rake middleware as I have found that now I am filtering other things out such as assets. Sure I could try to go through and pick out everything I think I need to allow to go through but this seems too tedious and not correct. It seems like ultimately, I need to do my filtering at the rails level not at the rack level.
I don't have an answer off of the top of my head to directly answer your question. However, I would suggest using the cancan gem to handle authorization instead of creating a homegrown solution. See https://github.com/ryanb/cancan

How can I create a Rails 3 route that will match all requests and direct to one resource / page?

I have a rails app (Rails 3.0) that I need to temporarily take out of service. While this is in effect, I want to create a new route that will direct all requests to a single piece of static content. I have a controller set up to serve my static pages.
I tried something like this:
match '*' => 'content#holding'
and
match '*/*' => 'content#holding'
to match a wildcard route as described here:Rails 3 route globbing without success.
This is probably a really simple answer, but I couldn't figure it out.
/EDIT/
Forgot to mention that I did have this rule at the very top of my routes.rb file.
Rails needs to bind the url parameters to a variable, try this:
match '*foo' => 'content#holding'
If you also want to match /, use parenthesis to specify that foo is optional:
match '(*foo)' => 'content#holding'
I did this just yesterday and first came up with the solution that klochner shows.
What I didn't like about this is the fact that whatever you enter in the URL, stays there after the page loads, and since I wanted a catch all route that redirects to my root_url, that wasn't very appealing.
What I came up with looks like this:
# in routes.rb
get '*ignore_me' => 'site#unknown_url'
# in SiteController
def unknown_url
redirect_to root_url
end
Remember to stick the routes entry at the very bottom of the file!
EDIT:
As Nick pointed out, you can also do the redirect directly in the routes file.
I ran into something like this where I had domain names as a parameter in my route:
match '/:domain_name/', :to => 'sitedetails#index', :domain_name => /.*/, :as =>'sitedetails'
The key piece to this was the /.*/ which was a wildcard for pretty much anything. So maybe you could do something like:
match '/:path/', :to => 'content#holding', :path=> /.*/, :as =>'whatever_you_want'
Where in "routes.rb" is this line located?
To have priority over other routes, it has to be placed first.
As an alternative, you can look into this: http://onehub.com/blog/posts/rails-maintenance-pages-done-right/
Or this: Rails: admin-only maintenance mode

What is a very simple authentication scheme for Sinatra/Rack

I am busy porting a very small web app from ASP.NET MVC 2 to Ruby/Sinatra.
In the MVC app, FormsAuthentication.SetAuthCookie was being used to set a persistent cookie when the users login was validated correctly against the database.
I was wondering what the equivalent of Forms Authentication would be in Sinatra? All the authentication frameworks seem very bulky and not really what I'm looking for.
Here is a very simple authentication scheme for Sinatra.
I’ll explain how it works below.
class App < Sinatra::Base
set :sessions => true
register do
def auth (type)
condition do
redirect "/login" unless send("is_#{type}?")
end
end
end
helpers do
def is_user?
#user != nil
end
end
before do
#user = User.get(session[:user_id])
end
get "/" do
"Hello, anonymous."
end
get "/protected", :auth => :user do
"Hello, #{#user.name}."
end
post "/login" do
session[:user_id] = User.authenticate(params).id
end
get "/logout" do
session[:user_id] = nil
end
end
For any route you want to protect, add the :auth => :user condition to it, as in the /protected example above. That will call the auth method, which adds a condition to the route via condition.
The condition calls the is_user? method, which has been defined as a helper. The method should return true or false depending on whether the session contains a valid account id. (Calling helpers dynamically like this makes it simple to add other types of users with different privileges.)
Finally, the before handler sets up a #user instance variable for every request for things like displaying the user’s name at the top of each page. You can also use the is_user? helper in your views to determine if the user is logged in.
Todd's answer does not work for me, and I found an even simpler solution for one-off dead simple authentication in Sinatra's FAQ:
require 'rubygems'
require 'sinatra'
use Rack::Auth::Basic, "Restricted Area" do |username, password|
[username, password] == ['admin', 'admin']
end
get '/' do
"You're welcome"
end
I thought I would share it just in case anyone wandered this question and needed a non-persistent solution.
I' have found this tutorial and repository with a full example, its working fine for me
https://sklise.com/2013/03/08/sinatra-warden-auth/
https://github.com/sklise/sinatra-warden-example
I used the accepted answer for an app that just had 2 passwords, one for users and one for admins. I just made a login form that takes a password(or pin) and compared that to one that I had set in sinatra's settings (one for admin, one for user). Then I set the session[:current_user] to either admin or user according to which password the user entered and authorized accordingly. I didn't even need a user model. I did have to do something like this:
use Rack::Session::Cookie, :key => 'rack.session',
:domain => 'foo.com',
:path => '/',
:expire_after => 2592000, # In seconds
:secret => 'change_me'
As mentioned in the sinatra documentation to get the session to persist in chrome. With that added to my main file, they persist as expected.
I found JWT to be the simple, modern/secure solution I was searching for. OP mentioned bulky frameworks, so for reference I downloaded the tag of the latest jwt gem at the time of writing (2.2.3) and it's 73 KB zipped and 191 KB unzipped. Seems to be well-maintained and open sourced on GitHub.
Here's a good blog post about it with code and a walkthrough for near-beginners: https://auth0.com/blog/ruby-authentication-secure-rack-apps-with-jwt/

Resources