I have routes that work perfectly on one machine, but on another machine they are failing and I've had a hard time to figure out what is wrong. On the failing machine it return the following errors for get /groups/my and groups/ respectively
No route matches {:controller=>"groups/owner/static_content", :topic=>"general"}
No route matches {:controller=>"groups/static_content", :topic=>"general"}
I have no idea where
static_controller
and
:topic=>"general"
come from since they don't appear anywhere in my routes file. Basically I have a route like
namespace :groups , :as => nil do
root :to => 'groups#index'
resources :groups, :only => [:show, :new, :create], :path => '' do
collection do
get :search
get 'my' => 'owner/groups#my', :as => :my
end
member do
post :subscribe
end
... other resources within a group
end
end
Any idea what I have done wrong or I'm missing? I'm using rails 3.2.2 and ruby 1.9.3 on rvm
A route is usually called from the views, so always check your view for action_controller_name_path if Controller::Action can not be found!
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.
Say I have an object called invoice. In routes.rb I have
resources :invoices do
get "pay"
end
When I run rake routes, the route is generated as
invoice_pay GET /invoices/:invoice_id/pay(.:format) invoices#pay
and the parameter is :invoices_id instead of :id
If I use a match statement:
match "invoices/:id/pay" => "invoices#pay", :via => :get
I get:
GET /invoices/:id/pay(.:format) invoices#pay
It seems to me that the route should be pay_invoice_path(#invoice), however, I have not found suitable documentation on this. Any suggestions?
i think what you are trying to do is
resources :invoices do
get "pay", :on => :member
end
have a look at the guides: http://guides.rubyonrails.org/routing.html
I'm trying to set up a nested resource in my routes config but I just can't work out where the problem lies.
Here is the relevant code from my routes config
resources :positions, :only => [:new,:create,:edit,:update,:destroy]
resources :etkh_profiles, :path => "members", :only => [:new,:create,:show,:index] do
resources :positions
collection do
post 'search'
end
end
It works when I try '/positions/new' but when I try 'members/positions/new' I get this error
No route matches [GET] "/members/positions/new"
Any ideas?
Thanks for your help.
The URL you need to use is more like /members/:memberid/positions/new since you've specified that positions are contained inside an etkh_profile. You can check this by running rake routes.
I'm using a Rails 3 App with Kaminari for Pagination. Because of my language, SEO and friendly URLs I want to change my URLs looks like. But it seems I have to decide between friendly pagination links and or displaying the correct method names. But first things first:
I have a model, which is called "pages" and contains some pages which can't be applied to only one model or don't contain any model. The following is a snippet of my "routes.rb":
match'/neugikeiten', :to => 'pages#neuigkeiten'
scope(:path_names => { :new => "neu", :edit => "bearbeiten", :delete => "loeschen", :index => "index", :page => "seite" }) do
resources :news, :path => "neuigkeiten"
end
As you can see, I match every page from pages to a single name and match all my other models and methods (I only used one as example) with scope. All of this works just fine. But now I have to add the Kaminare routes, for which the route looks like this:
resources :pages do
get 'seite/:page', :action => :neuigkeiten, :on => :collection
end
So, basically what I want to get is an URL like this:
/neuigkeiten/seite/2
The 2 is just an example and seite is the german word for page. But what i do get, is this:
/pages/seite/2
So, I get the model name, instead of the name I defined for this single page. I already tried switching the different codes but either I just have the original model name in the URL or I don't get nice URLs for pagination, which look like this:
/neuigkeiten?page=2
And if I try to match the pages without the resource like this:
match'/tagebuch/seite/:page', :to => 'pages#tagebuch', :on => :collection
I get the following error.
can't use collection outside resources scope
It seems to me that there should be another method to do this, because I can't be the only one having this kind of problem.
I'm glad for any help!
If anybody is interested in an solution, I found one myself. It's not perfect, but it works.
I had to install an extra gem for the localisation called "i18n_routing". Then in my routes.rb I did:
localized do
resources :news, :path => "neuigkeiten" do
get 'seite/:page', :action => :index, :on => :collection
end
end
The rest is done in the localized language file (en.yml).
resources :leagues do
resources :schedule
end
This generates:
leagues/:id
leagues/:league_id/schedule/:id
How can I keep the league ID from changing param names?
So it'll be:
leagues/:id
leagues/:id/schedule/:schedule_id
No, please do not do this.
The reason for it being this way is that it provides a common interface for nested resources across every single application. By making it different in your application, you're effectively going "against the grain" of Rails. Rails has a strict set of conventions that you should stick to. When you stray from this path, things get messy.
However, if you do want to shoot yourself in the foot, metaphorically speaking, you will need to define the routes manually. Here's the routes for the seven standard actions in a controller:
get 'leagues/:id/schedules', :to => "schedules#index", :as => "league_schedules"
get 'leagues/:id/schedule/:schedule_id', :to => "schedules#show", :as => "league_schedule"
get 'leagues/:id/schedules/new', :to => "schedules#new", :as => "new_league_schedule"
post 'leagues/:id/schedules', :to => "schedules#create"
get 'leagues/:id/schedule/:schedule_id/edit', :to => "schedules#edit", :as => "ed it_league_schedule"
put 'leagues/:id/schedule/:schedule_id', :to => "schedules#update"
delete 'leagues/:id/schedule/:schedule_id', :to => "schedules#destroy"
As you can see, it's quite ugly. But, if you really really really want to do it this way, that's how you'd do it.
You can set "param" option on resource route to override the default "id" param:
resources :leagues do
resources :schedule, param: schedule_id
end
refs to the Rails Routing Doc: http://guides.rubyonrails.org/routing.html#overriding-named-route-parameters
It appends the ID to the nested_param which is a bummer because I would like mine to be without the singular name. It looks like they really don't want you to make it only like :id as it could have conflicts. Plus it would be a bit of a diff from the normal restful routing that rails likes to use.
https://github.com/rails/rails/blob/5368f2508651c92fbae40cd679afbafdd7e98e77/actionpack/lib/action_dispatch/routing/mapper.rb#L1207
namespace :account, defaults: { type: 'account' }do
resources :auth, param: :lies_id, only: [] do
get :google
end
end
Rake routes returns the following
$ rake routes | grep /account/auth
account_auth_google GET /account/auth/:auth_lies_id/google(.:format)
So the solution which seams simpler is to just change the controller to use the nested param name it creates.