I fixed RoutingError in rails 3 using this link. I wanted to redirect users to root page so I added:
match '*a', :to => 'homes#index'
to my routes.rb.
Question is: can I define flash[:error] message in this 'match' line to be displayed on target page?
Regards,
Mateusz
This is similar to Redirect and raise flash message when catch-all in routes
But I did run into this problem and it was giving me an issue because I was using MATCH and when I used GET, the alert wouldn't flash. Eventually I found a working solution using the thread above and applying GET in another manner.
match '*path' => redirect{ |p, req| req.flash[:alert] = "The page you requested is not valid."; '/' }, via: [:get]
This is what I ultimately came up with, via: [:get] being key to making everything work.
And remember to place such code at the end of your routes.rb
Related
I have a Rails 2.3.5 app with many controllers, models etc. which I'm trying to upgrade to Rails 3.2.21. I'm having some troubles with my routes. I tried to follow the Rails 3 new routing format but it doesn't seem to work. I'm getting two problems (which I guess all indicate one fundamental issue with my routing):
In the root ('/') I'm getting the generic "Welcome abroad" Rails
page. My routes (see below) have defined routing for root.
For some controllers I get No route matches [GET] "/study" message. My route shows this route, but for some reason doesn't define the GET method.
Here's my config/routes.rb code:
Myapp::Application.routes.draw do
root :to => 'study#index'
match 'login' => 'login', :protocol => 'https://'
resources :study_maps do
get :clone, :on => :member
end
# Route report create actions to the report controller
match 'report/create', :as => 'report'
match ':controller(/:action(/:id))(.:format)'
end
If I'm running rake routes I'm getting:
root / study#index
login /login(.:format) login#login {:protocol=>"https://"}
clone_study_map GET /study_maps/:id/clone(.:format) study_maps#clone
study_maps GET /study_maps(.:format) study_maps#index
POST /study_maps(.:format) study_maps#create
new_study_map GET /study_maps/new(.:format) study_maps#new
edit_study_map GET /study_maps/:id/edit(.:format) study_maps#edit
study_map GET /study_maps/:id(.:format) study_maps#show
PUT /study_maps/:id(.:format) study_maps#update
DELETE /study_maps/:id(.:format) study_maps#destroy
report /report/create(.:format) report#create
/:controller(/:action(/:id))(.:format) :controller#:action
Here's my StudyController#index code:
require 'myapp/studymgr'
require 'project_user'
require_dependency 'myapp/controller_extensions/report_manager'
class StudyController < ApplicationController
include PaginatorController
before_filter(:authenticate, :except => [:todo])
before_filter(:authorize,
:only => [:update, :destroy, :edit, :prune, :select_experiments ])
def index
#tags = Stag.find(:all).collect { |stag| stag.tag }
...
#include_ext = true
end
end
Can someone advise on what I'm missing?
Finally found a solution - my views had .rhtml extension. I found that this format is no longer supported under Rails 3 (What is the difference Between .erb , .rhtml and .html.erb?), so I changed all views extensions to .html.erb and then the routes worked with no need to specify explicit resource for each controller, just using the generic route: match ':controller(/:action(/:id))'.
As for the issue in the root route (#1 above), where I always got the Rails "Welcome abroad" page, despite having explicit route in my routes.rb, turns out I had to remove public/index.html which is loaded for root by Rails, and then my view was loaded.
I'm migrating an application from Rails 2 to Rails 3.
We have multiple namespaced controllers with different namespaces.
As they are not RESTfull I don't want to use resource routing, instead I would like to have an old Rails 2 like match ':controller/:action' that picks up namespaced controllers.
In my routes.rb I have
# Install the default route as the lowest priority.
match ':controller(/:action(/:id(.:format)))'
match ':controller(/:action(/:id(.:format)))', :controller => /[^\/]+\/[^\/]+/
rake routes reports
/:controller(/:action(/:id(.:format))) :controller#:action
/:controller(/:action(/:id(.:format))) (?-mix:[^\/]+\/[^\/]+)#:action
Still a request to /config/companies/index fails
ActionController::RoutingError (No route matches [GET] "/config/companies/index"):
What am I doing wrong? Is there another way to get namespaced routes with dynamic segments? When I try to use namespace and a match with a dynamic segment together it throws an error.
:controller segment is not allowed within a namespace block
OK I found the problem.
Config is a reserved constant in Rails, it points to RbConfig. My match condition actually works but tries to call RbConfig::CompaniesController which of course does not exist.
When I tried to add
match '/:controller(/:action(/:id(.:format)))', :controller => /config\/[^\/]+/
the error was
ActionController::RoutingError (uninitialized constant RbConfig::CompaniesController)
Solution: rename the app/controllers/config -> app/controllers/configuration (and the views folder) and add a redirect to the routing to handle legacy links.
match '/config/*path' => redirect("/configuration/%{path}")
I'm currently defining routes for my pages in the following manner:
get "home/index"
get "photo/index"
get "project/index"
get "home/about"
root :to => 'home#index'
However, I can only seem to be able to create a link to the photo/project index pages by using:
link
link
In the URL, the "index" part also shows up. I can't simple use /photo in the a link, because rails throws a routing error:
No route matches [GET] "/photo"
How would I create a route match for this?
match "/photo", to: "controller#action"
http://guides.rubyonrails.org/routing.html#connecting-urls-to-code
The best answer is to use match. Don't forget to include via to preserve your restriction on the http method:
match "/photo", to: "controller#action", :via => 'get'
I have a double namespace situation, where my controllers look like this:
CandidateController
Candidate::PerformanceController
Candidate::Performance::ReviewController
In Rails 2, I was able to use redirect_to from the Candidate::Performance::ReviewController controller in order to redirect to an action in the CandidateController, like so:
class Candidate::Performance::ReviewController < ApplicationController
before_filter :ensure_manager
# ...
def ensure_manager
if !current_user.manager?
flash[:warning] = t(:must_be_manager)
redirect_to :controller => '/candidate', :action => :index
end
end
end
The / in controller => '/candidate' would allow Rails to redirect from app.com/performance/reviews to app.com/candidate.
However, this seems to not work the same in Rails 3.1. Instead, my redirect_to goes to app.com/candidate//candidate. What is the correct way to specify a "absolute" controller within a redirect_to hash (ie. without using a path helper)?
Update: I know this would be infinitely easier if I just use named route helpers (ie. candidate_path). Unfortunately, there is a lot of legacy code in our codebase which doesn't use RESTful routing and instead uses the default "catch-all" route; ie. we have a lot of actions with no named route to fallback on.
I wonder if something else is wrong. In the doc:
In particular, a leading slash ensures no namespace is assumed. Thus,
while url_for :controller => ‘users‘ may resolve to
Admin::UsersController if the current controller lives under that
module, url_for :controller => ’/users‘ ensures you link to
::UsersController no matter what.
And I don't think it changed...
Also, shouldn't the catch-all routes be after the default routes in your config?
I think that redirect_to :controller => ... uses url_for to build the url, so in the end, if your custom routes catches /candidates, I don't really see the difference.
Some people have the same problem: https://github.com/rails/rails/issues/2575
Patching actionpack/lib/action_dispatch/routing/route_set.rb line 434
as follows fixes this: if !named_route && different_controller? &&
!controller.starts_with?('/')
If anyone else runs into this problem, it seems to be a known issue (unsure whether they consider it a bug or not, given the lack of response on the issue page from anyone working on Rails).
Until they patch it (assuming they do), I've added the following little monkey patch into an initializer, based on the code given in the original post of that issue:
module ActionDispatch
module Routing
class RouteSet
class Generator
def use_relative_controller_with_absolute_paths!
return if controller.starts_with?('/')
use_relative_controller_without_absolute_paths!
end
alias_method_chain :use_relative_controller!, :absolute_paths
end
end
end
end
Hope this can help someone else!
Update: It seems that this was fixed in Rails here.
I'm working on a Rails3 app that has a Pages controller, and two pages: pages#main and pages#status. The main page has a link which, when clicked, goes to status. The user already has profile information, and if part of that profile information is not present, I want status to redirect to main. I'm getting a mysterious double-redirect though, that I can't solve. Here's the pages controller:
def main
#current_user = current_user
end
def status
#current_user = current_user
if #current_user.address.blank?
redirect_to :action => "main" and return
end
end
Everything works swimmingly as long as the condition isn't met, but as soon as it is, I get the error:
Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return".
Indeed, redirect_to is called twice (same line, according to the trace; not sure why). I'm wondering whether it is a routes problem. Here is routes.rb:
match '/main', :to => 'pages#main'
match '/status', :to => 'pages#status'
Any suggestions would be greatly appreciated.
Here is the development log:
Started GET "/status" for 127.0.0.1 at Wed Nov 03 21:28:15 -0700 2010
Processing by PagesController#status as HTML
User Load (0.3ms) SELECT "users".* FROM "users" WHERE ("users"."id" = 3) LIMIT 1
Before redirect
Before redirect
Redirected to
Redirected to
Completed in 32ms
AbstractController::DoubleRenderError (Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return".):
app/controllers/pages_controller.rb:15:in `status'
app/controllers/pages_controller.rb:15:in `status'
Trying to solve the problem, I've added two debugging lines to the status method, in the hopes that it will provide some clue:
logger.debug "Before redirect"
redirect_to :action => "main" and return
logger.debug "After redirect"
So, the "Before redirect" lines are hit before we get to "Redirected to". Then "Redirected to" appears twice with no target. Incidentally, this happens with or without "and return" on the redirect line. I'm really not sure what's going on.
Also, interestingly, I added a debug line to the main method. It is never triggered.
Rav, can you paste the development log for this request? Specifically, does the first request for /status result in a redirect to /main, or does it fail with the above error?
Specifically, look in log/development.log for the most recent request block or blocks.