Rails member routing, should be easy? - ruby-on-rails

For this route:
resources :projects do
member do
resources :stakeholders
end
end
The generated routes are:
projects_stakeholders GET /projects/projects/:id/stakeholders(.:format) {:action=>"index", :controller=>"projects/stakeholders"}
POST /projects/projects/:id/stakeholders(.:format) {:action=>"create", :controller=>"projects/stakeholders"}
new_projects_stakeholder GET /projects/projects/:id/stakeholders/new(.:format) {:action=>"new", :controller=>"projects/stakeholders"}
edit_projects_stakeholder GET /projects/projects/:id/stakeholders/:id/edit(.:format) {:action=>"edit", :controller=>"projects/stakeholders"}
projects_stakeholder GET /projects/projects/:id/stakeholders/:id(.:format) {:action=>"show", :controller=>"projects/stakeholders"}
As these routes have two times a :id parameter, if I have, for instance the URL 'projects/4/stakeholders/11'
In my log file I see this:
Parameters: {"id"=>"11"}
How can I then access my project_id from inside my controller?
Thanks!!!

You don't need the member do block around it. Just do this, and you should start seeing a project_id in your params:
resources :projects do
resources :stakeholders
end

Related

Dropping second model name in nested resource route

I'm using slugs for IDs, so wanting URLs like /songs/radiohead/karma-police instead of /artists/radiohead/songs/karma-police.
Slugs can be achieved with:
def to_param
slug
end
But how is there any way to drop the model name - "songs" - from the standard RESTful URL?
You can override the path segment by passing the :path option to your resources call.
resources :songs, path: "songs/:artist_id"
this will generate these routes
songs GET /songs/:artist_id(.:format) {:action=>"index", :controller=>"songs"}
POST /songs/:artist_id(.:format) {:action=>"create", :controller=>"songs"}
new_song GET /songs/:artist_id/new(.:format) {:action=>"new", :controller=>"songs"}
edit_song GET /songs/:artist_id/:id/edit(.:format) {:action=>"edit", :controller=>"songs"}
song GET /songs/:artist_id/:id(.:format) {:action=>"show", :controller=>"songs"}
PUT /songs/:artist_id/:id(.:format) {:action=>"update", :controller=>"songs"}
DELETE /songs/:artist_id/:id(.:format) {:action=>"destroy", :controller=>"songs"}
Put this in your routes.rb and it should work.
match 'artists/:artist_id/:id' => 'songs#show', :as => 'artist_song'
Make sure if you do the :as that the other routes don't take precedence over this one.
Then check out this Routing match reference

No Route Matches error - with Nested Resource

I have the following Nested Resource in my routes.rb file
resource :issuer do
resources :certificates
end
My Models:
class Issuer < ActiveRecord::Base
has_many :certificates
end
class Certificate < ActiveRecord::Base
belongs_to :issuer
end
I get the following error when i visit: /issuer/2/certificates
No route matches {:action=>"edit", :controller=>"certificates"}
Any help would be appreciated.. Thanks in advance!
EDIT : MY rake routes
issuer_certificates GET /issuer/:issuer_id/certificates(.:format) {:action=>"index", :controller=>"certificates"}
POST /issuer/:issuer_id/certificates(.:format) {:action=>"create", :controller=>"certificates"}
new_issuer_certificate GET /issuer/:issuer_id/certificates/new(.:format) {:action=>"new", :controller=>"certificates"}
edit_issuer_certificate GET /issuer/:issuer_id/certificates/:id/edit(.:format) {:action=>"edit", :controller=>"certificates"}
issuer_certificate GET /issuer/:issuer_id/certificates/:id(.:format) {:action=>"show", :controller=>"certificates"}
PUT /issuer/:issuer_id/certificates/:id(.:format) {:action=>"update", :controller=>"certificates"}
DELETE /issuer/:issuer_id/certificates/:id(.:format) {:action=>"destroy", :controller=>"certificates"}
You should use resources (plural) instead of resource in refer to :issuer. So please try this:
resources :issuers do
resources :certificates
end
and issuers/2/certificates will work.
In your routes.rb file you are defining issuer as a singular resource
resource :issuer do # <----- using resource instead of resources
resources :certificates
end
With singular resources, the routes you get won't allow an :id to be matched, so in your example,
issuer/2/certificates
it's the "2" that's giving you grief. You should either get rid of it or define :issuer as a standard (non-singular) resource in your routes.rb file.
You don't have PUT defined for /issuer/2/certificates. instead you have it defined for /issuer/2/certificates/123. That's why you get that error.
If you are trying to edit the certificate then make sure you generate a correct link and include certificate_id.

Problem with rails routing

I have the following in my routing config:
resources :users do
resources :apps, :controller => :user_apps
end
rake routes includes the following:
user_apps GET /users/:user_id/apps(.:format) {:action=>"index", :controller=>"user_apps"}
user_apps POST /users/:user_id/apps(.:format) {:action=>"create", :controller=>"user_apps"}
new_user_app GET /users/:user_id/apps/new(.:format) {:action=>"new", :controller=>"user_apps"}
edit_user_app GET /users/:user_id/apps/:id/edit(.:format) {:action=>"edit", :controller=>"user_apps"}
user_app GET /users/:user_id/apps/:id(.:format) {:action=>"show", :controller=>"user_apps"}
user_app PUT /users/:user_id/apps/:id(.:format) {:action=>"update", :controller=>"user_apps"}
user_app DELETE /users/:user_id/apps/:id(.:format) {:action=>"destroy", :controller=>"user_apps"}
However, when I try to access eg user_apps_path(1,2) I get /users/1/apps.2 rather than /users/1/apps/2.
Where am I going wrong?
I'm using rails 3.
The correct route is user_app_path(1,2) The pluralized version goes to the index action, making the second argument the format / extension of the request.

Rails 3 Routing Resources with Variable Namespace

Is it possible to have a variable namespace? I have restful resources like the following:
resources :articles
resources :persons
But I need to scope these inside a variable namespace, such that it responds to URLs of the form:
':edition/:controller/:action/:id'
for example:
/foobar/article/edit/123 or /bazbam/person/edit/345
for each of the resources. Is this possible with the resources method, or must I hand-craft these? I will not know the possible values for :edition ahead of time; these get looked up in a before_filter in my ApplicationController.
Is this all I need to do?
scope ':edition' do
resources :articles
resources :matches
resources :teams
end
UPDATE: When using the scope directive above, I get routes like I want:
articles GET /:edition/articles(.:format) {:action=>"index", :controller=>"articles"}
POST /:edition/articles(.:format) {:action=>"create", :controller=>"articles"}
new_article GET /:edition/articles/new(.:format) {:action=>"new", :controller=>"articles"}
edit_article GET /:edition/articles/:id/edit(.:format) {:action=>"edit", :controller=>"articles"}
article GET /:edition/articles/:id(.:format) {:action=>"show", :controller=>"articles"}
PUT /:edition/articles/:id(.:format) {:action=>"update", :controller=>"articles"}
DELETE /:edition/articles/:id(.:format) {:action=>"destroy", :controller=>"articles"}
matches GET /:edition/matches(.:format) {:action=>"index", :controller=>"matches"}
POST /:edition/matches(.:format) {:action=>"create", :controller=>"matches"}
new_match GET /:edition/matches/new(.:format) {:action=>"new", :controller=>"matches"}
edit_match GET /:edition/matches/:id/edit(.:format) {:action=>"edit", :controller=>"matches"}
match GET /:edition/matches/:id(.:format) {:action=>"show", :controller=>"matches"}
PUT /:edition/matches/:id(.:format) {:action=>"update", :controller=>"matches"}
DELETE /:edition/matches/:id(.:format) {:action=>"destroy", :controller=>"matches"}
teams GET /:edition/teams(.:format) {:action=>"index", :controller=>"teams"}
POST /:edition/teams(.:format) {:action=>"create", :controller=>"teams"}
new_team GET /:edition/teams/new(.:format) {:action=>"new", :controller=>"teams"}
edit_team GET /:edition/teams/:id/edit(.:format) {:action=>"edit", :controller=>"teams"}
team GET /:edition/teams/:id(.:format) {:action=>"show", :controller=>"teams"}
PUT /:edition/teams/:id(.:format) {:action=>"update", :controller=>"teams"}
DELETE /:edition/teams/:id(.:format) {:action=>"destroy", :controller=>"teams"}
I'm now able to reference :edition in my ApplicationController:
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :authenticate_user!
before_filter :get_edition
def get_edition
#edition = Edition.first(:conditions => { :FriendlyName => params[:edition] } )
end
end
Now I just want to make sure this is the best way to accomplish this.
Actually, you can just do the following :
my_var = "persons"
resources my_var.to_sym
The to_sym method on a string changes it to a symbol
If you don't know the possible values for edition - then you can't use namespaces which seem like they might have solved this issue.
That said, I'd just handcraft them - your case here seems like the ideal case foregoing resources and going straight to a handcrafted path.

Default segment name in rails resources routing

I want to create a route in my rails application along the lines of
/panda/blog
/tiger/blog
/dog/blog
where panda, tiger, and dog are all permalinks (for an animal class)
The normal way of doing this
map.resources :animals do |animal|
animal.resource :blog
end
would create routes along the lines of
/animals/panda/blog
/animals/tiger/blog
/animals/dog/blog
But i do not want the first segment, as it will always be the same.
I know I could do this by manual routing, but I want to know how to do using rails resources, as having animals and blogs is a requirement for me.
In rails 3.x, you can add path => "" to any resource or resources call to remove the first segment from the generated path.
resources :animals, :path => ""
$ rake routes
animals GET / {:action=>"index", :controller=>"animals"}
POST / {:action=>"create", :controller=>"animals"}
new_animal GET /new(.:format) {:action=>"new", :controller=>"animals"}
edit_animal GET /:id/edit(.:format) {:action=>"edit", :controller=>"animals"}
animal GET /:id(.:format) {:action=>"show", :controller=>"animals"}
PUT /:id(.:format) {:action=>"update", :controller=>"animals"}
DELETE /:id(.:format) {:action=>"destroy", :controller=>"animals"}
You can use this plugin:
http://github.com/caring/default_routing/tree/master

Resources