In my Rails4 app I use actionpack-page_caching.
I have a controller like this:
class CodeController < ApplicationController
def home
end
end
and the route:
get "/code/:order/(:page)" => "code#home"
Then when I clear the page caching
expire_page(:controller => 'code', :action => 'home')
I got the error:
No route matches {:action=>"home", :controller=>"code"}
Why? and what should I do?
According to Rails guides
Page Caching has been removed from Rails 4. See the actionpack-page_caching gem. See DHH's key-based cache expiration overview for the newly-preferred method.
Related
I've got a Rails app up running on a server. It's a big project so there are lots of routes involved, and two domains point to the root at the moment. I'd like to somehow design my routes.rb to interpret one domain to take it to a certain part of the app as if it was the root, and use the other for everywhere else.
Something like this (very pseudocode, hope you get the idea):
whole_app.com
whole_app.com/documents
whole_app.com/share
whole_app.com/users
partial_app.com, :points_to => 'whole_app.com/share'
Can Rails handle this? Thank-you!
You can achieve this by overriding default url_options method in application controller. This will override host url for every request.
class ApplicationController < ActionController::Base
....
def default_url_options
if some_condition
{:host => "partial_app.com"}
else
{:host => "whole_app.com"}
end
end
....
end
And for pointing a route to some specific url, you may use:
match "/my_url" => redirect("http://google.com/"), :as => :my_url_path
The better way is to do settings on server to redirect some url to a specific location.
is it going to /share based on some kind of criteria? if so you can do this:
routes.rb
root :to => 'pages#home'
pages_controller.rb
def home
if (some condition is met)
redirect_to this_path
else
render :layout => 'that'
end
end
I read a few websites and questions but all were far beyond my level except one site:
http://markconnell.co.uk/posts/2010/02/rails-3-routing-examples
I'm trying to follow Head First Rails which was made for Rails 2 and so far it's been going well enough. I've been able to find the conversions so far, this is really the first place since installation to stump me.
It says in the config/routes.rb file that it should read:
ActionController::Routing::Routes.draw do |map|
map.connect '/ads/:id', :controller=>'ads', :action=>'show'
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
First off my routes.rb file defaults that first line to be
Mebay::Application.routes.draw do
So my first attempt read:
Mebay::Application.routes.draw do
map.connect '/ads/:id', :controller=>'ads', :action=>'show'
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
When that failed I tried this:
Mebay::Application.routes.draw do'
map '/ads/:id' => 'ads#index'
end
Then I tried the same thing but adding |map| to the first line.
And finally, I tried changing it all to this:
ActionController::Routing::Routes.draw do |map|
map '/ads/:id' => 'ads#index'
end
None of these have worked though. Could someone please help me out here, I'm not sure what I'm doing wrong. I have another book, Ruby On Rails 3 by Hartl but in the Index it doesn't even show anything on Routes so don't even know where to look in there.
Thanks for any help you can offer me!
// EDIT - I also tried with it reading '/ads/':id thinking perhaps that is a mistake since it doesn't make sense to me why :id would be inside quotes.
// EDIT 2 - This is what Rake Routes returns:
WARNING: 'require 'rake/rdoctask'' is deprecated. Please use 'require 'rdoc/task' (in RDoc 2.4.2+)' instead.
at /Users/Dennis/.rvm/gems/ruby-1.9.2-p318#rails3tutorial/gems/rake-0.9.2.2/lib/rake/rdoctask.rb
WARNING: Global access to Rake DSL methods is deprecated. Please include
... Rake::DSL into classes and modules which use the Rake DSL methods
WARNING: DSL method Mebay::Application#task called at /Users/Dennis/.rvm/gems/ruby-1.9.2-p318#rails3tutorial/gems/railties-3.0.1/lib/rails/application.rb:214:in `initialize_tasks'
/ads/:id(.:format) {:controller=>"ads", :action=>"show"}
/:controller/:action/:id(.:format)
/:controller/:action/:id.:format
Error Message:
Routing Error
No route matches "/ads/3"
//EDIT 3 - This is what my 2 controller files look like:
ads_controller:
class AdsController < ApplicationController
end
application_controller:
class ApplicationController < ActionController::Base
protect_from_forgery
end
//EDIT 4 -
Tried in the ads_controller.rb file:
class AdsController < ApplicationController
def show;
end
end
Also tried in the same file:
class AdsController < ApplicationController
end
def show;
end
And each way I tried going to
localhost:3000/mebay/ads/3
localhost:3000/ads/3
localhost:3000/show/ads/3
localhost:3000/mebay/show/ads/3
Same error still "Routing Error. No Route Matches..."
ActionController::Routing::Routes.draw do
match '/ads/:id' => 'ads#show'
match ':controller/:action/:id'
match ':controller/:action/:id.:format'
end
I thoroughly recommend reading the docs: http://apidock.com/rails/ActionDispatch/Routing
I also am using that book and going through for a difference between rails 2 and rails 3.
I got this to work. In routes.rb file all you need to do is add this between the do and the end:
resources :ads
The key is that your routes.rb file is only sending that resource to the right spot. The next place to look is the ads_controller.rb file where you will want to add this:
#Get /ads/1
#Get /ads/1.json
def show
#ad = Ad.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #ad }
end
end
The next part is adding the index which is a bit later in that chapter. You'll want to add this above that:
# GET /ads
# GET /ads.json
def index
#ads = Ad.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #ad }
end
end
Basically if you look at the chapter 1 routes.rb and controller files you'll see that scaffold configures a rails 3 app like that. One more thing that confused me was I was only able to get the javascript to work by putting it in /app/assets/stylesheets and editing application.html.erb and setting the stylesheet link to look like this:
<%= stylesheet_link_tag "application", :media => "default.css" %>
Enjoy
If you are using Rails 3 you don't want to do a Rails 2 tutorial. There are plenty of good rails 3 tutorials out there. For your question about routes, see the blog post below which might help you figure it out.
http://gregmoreno.wordpress.com/2010/08/12/rails-3-upgrade-part-2-routes/
Try making this your Routes file. I had the same problem while doing it from Chapter 2 of Head First Rails. But this resolved it for me
Mebay::Application.routes.draw do
controller 'ads' do
match 'ads/:id' => :show
end
end
We just upgraded our app to Rails 3.2.2 and are now having a routing issue for handling errors.
Per José Valim's blog post, we added the following:
config.exceptions_app = self.routes to config/application.rb
match "/404", :to => "errors#not_found" to config/routes.rb
(and the appropriate controller/views).
The problem is we need ourdomain.com/id to display an index page for a product category of id.
So, now ourdomain.com/404 shows our 404 page, when it should show our category listing page for the category with an id of 404.
How can we work around this?
Is there a way to make the app prepend each error with error_ before it's evaluated by routes?
Or, maybe somehow set config.exceptions_app to reference a namespace in the routes file?
Or, can I create a second route set and set config.exceptions_app = self.second_set_of_routes?
Thanks!
We had the same problem -- error codes colliding with ids for resources at the root level (e.g., collisions between ourdomain.com/:resource_id and ourdomain.com/404).
We modified José Valim's solution by adding a route constraint that only applies when handling an exception:
# Are we handling an exception?
class ExceptionAppConstraint
def self.matches?(request)
request.env["action_dispatch.exception"].present?
end
end
MyApp::Application.routes.draw do
# These routes are only considered when there is an exception
constraints(ExceptionAppConstraint) do
match "/404", :to => "errors#not_found"
match "/500", :to => "errors#internal_server_error"
# Any other status code
match '*a', :to => "errors#unknown"
end
...
# other routes, including 'match "/:resource_id"'
end
(We only stumbled on this solution last night, so it hasn't had much burn-in time. We are using Rails 3.2.8)
There's one solution which I've found so far:
# application_controller.rb
def rescue_404
rescue_action_in_public CustomNotFoundError.new
end
def rescue_action_in_public(exception)
case exception
when CustomNotFoundError, ::ActionController::UnknownAction then
#render_with_layout "shared/error404", 404, "standard"
render template: "shared/error404", layout: "standard", status: "404"
else
#message = exception
render template: "shared/error", layout: "standard", status: "500"
end
end
def local_request?
return false
end
rescue_action_in_public is the method that Rails calls to handle most errors.
local_request? the method tells Rails to stop sucking if it's local request
# config/routes.rb
match '*path', controller: 'application', action: 'rescue_404' \
unless ::ActionController::Base.consider_all_requests_local
It simply says that it can’t find any other route to handle the request (i.e. the *path) it should call the rescue_404 action on the application controller (the first method above).
EDIT
This version worked for me well!
Try to add to application.rb
# 404 catch all route
config.after_initialize do |app|
app.routes.append{ match '*a', to: 'application#render_not_found' } \
unless config.consider_all_requests_local
end
See: https://github.com/rails/rails/issues/671#issuecomment-1780159
It seems that this route is hard coded at the show_exceptions method (see source)
Sorry, but I don't think of a way of doing it besides changing the line 45 on the source above to:
env["PATH_INFO"] = "/error_#{status}"
(what is, needless to say, no solution at all).
It doesn't hurt to ask:If you thought it was nice to have your own error controller implemented so simply and desperately want to have it, than wouldn't it even be more "RESTful" if your route were yourdomain.com/product/:id?
How to rescue from RoutingError in rails 3.1 application. If i'm nt mistaken it was possible to use rescue_from RoutingError in application controller but now it's not possible.
There is no great way to handle it, but there are a few workarounds. The discussion here yields the following suggestion:
Routes
Add the following to your routes file:
match "*", :to => "home#routing_error"
and handle the error in this action:
def routing_error
render text: "Not found, sorry", status: :not_found
end
I wasn't able to replicate #matthew-savage's results. However, per the Rails guide on route globbing and this question on another StackOverflow question, I solved this issue like so:
routes.rb
match "*gibberish", :to => "home#routing_error"
notice how I included text after the wildcard. The controller is fine as shown above:
controller/home_controller.rb
....
def routing_error
render text: "Not found, sorry", status: :not_found
end
Good example.
route.rb
Rails 3:
match '*unmatched_route', :to => 'application#raise_not_found!'
Rails 4:
get '*unmatched_route' => 'application#raise_not_found!'
application_controller.rb
def raise_not_found!
raise ActionController::RoutingError.new("No route matches #{params[:unmatched_route]}")
end
I get a NameError uninitialized constant WorkoutLog when attempting to access a non-resourceful action on a controller.
My controller looks as follows:
class WorkoutLogController < ApplicationController
def index
# random code
end
def on_date
# random code
end
end
My Routes File:
match "workout_log/:date", :controller => "workout_log", :action => "on_date", :as => "log_on_date"
match "workout_log", :controller => 'workout_log', :action => 'index'
And then I have a my link_to as such:
<%= link_to "View Log", log_on_date_path(:date => Date.today.strftime('%d-%B-%Y')), :remote => true, "data-type" => "html" %>
The WorkoutLogController has no model behind it - it's just a controller. However, I can't perform a request on the on_date because it throws the following error:
NameError (uninitialized constant WorkoutLog):
When I run rake routes it seems to be fine as it generates the following:
log_on_date /workout_log/:date(.:format) {:controller=>"workout_log", :action=>"on_date"}
workout_log /workout_log(.:format) {:controller=>"workout_log", :action=>"index"}
I can't wrap my head around what the issue is (especially after spending the past night trying to figure it out). Is rails looking for a model to associate with it and failing to do so?
I figured out the issue. It had to do with declarative_authorization.
Since I had not copied the code 100%, I left out the following from my controller code pasted above:
filter_resource_access
declarative_authorization uses this for resourceful routes - which was not my case. I've since switched it to filter_access_to :all and it works fine. I got to the root of the problem by creating the file workout_log.rb in my models:
class WorkoutLog
end
Then when I issued a request to the index and on_date actions, it gave me the error that it could not find ActiveModel methods on WorkoutLog, which in turn pointed me to the filters on the WorkoutLogController.
If you look under Examples > Controller at the declarative_authorization page on GitHub, it'll provide the necessary info.
Hope this helps anyone else who has this issue!