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
Related
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
I accidentally generated a singular controller comm_log without 's'. 's' was added to controller name, helpers, views, specs and routes. The customer_comm_log_path(f.customer_id, f.id) seems not right.
The relation is a comm log belongs to a customer and a customer has many comm logs.
resources :customers do
resources :comm_logs
end
The output of rake routes (related) is:
comm_logs_index GET /comm_logs/index(.:format) {:controller=>"comm_logs", :action=>"index"}
comm_logs_new GET /comm_logs/new(.:format) {:controller=>"comm_logs", :action=>"new"}
comm_logs_create GET /comm_logs/create(.:format) {:controller=>"comm_logs", :action=>"create"}
comm_logs_show GET /comm_logs/show(.:format) {:controller=>"comm_logs", :action=>"show"}
comm_logs_destroy GET /comm_logs/destroy(.:format) {:controller=>"comm_logs", :action=>"destroy"}
customer_comm_logs GET /customers/:customer_id/comm_logs(.:format) {:action=>"index", :controller=>"comm_logs"}
POST /customers/:customer_id/comm_logs(.:format) {:action=>"create", :controller=>"comm_logs"}
new_customer_comm_log GET /customers/:customer_id/comm_logs/new(.:format) {:action=>"new", :controller=>"comm_logs"}
edit_customer_comm_log GET /customers/:customer_id/comm_logs/:id/edit(.:format) {:action=>"edit", :controller=>"comm_logs"}
customer_comm_log GET /customers/:customer_id/comm_logs/:id(.:format) {:action=>"show", :controller=>"comm_logs"}
PUT /customers/:customer_id/comm_logs/:id(.:format) {:action=>"update", :controller=>"comm_logs"}
DELETE /customers/:customer_id/comm_logs/:id(.:format) {:action=>"destroy", :controller=>"comm_logs"}
Is there a way to fix the singular controller? Thanks.
Try script/destroy your_controller_name using the same controller name used to create it.
I think I have a handle on nested routes (great url helpers, and access and much more) and nested resources in forms with accepts_nested_attributes_for but what do I use in routes as I see both:
resources :schools do
resources :documents
end
and also
resources :schools :has_many => :documents
end
please can you tell me the difference between these.
Obviously has_many is for a one-to-many relationship. does it produce path helpers and require correct routing and for the do block what relationship does that imply, none? just path helpers (/schools/documents) and what if I want multiple resources (other than books, say documents) under schools, the first way I can add it into the do-end block but what about the second way, just two lines, one for each has_many?
Though I've read the guides and api's I don't quite get the difference/usage here and anyone that can provide a clear explanation of the distinction between the two (in the form 'a does x whereas b does y' would be great) would be much appreciated :)
Oh and of course how they relate to having the has_many in the model - so I guess these relationships can be in the model with has_many, the controller (mostly thru usage of paths) and in the view (through forms with nested attributes).
They both do the same thing, its up to you to choose which one
I prefer the do block format as its easier to read
btw with the has_many format you could do :has_many => [:docs, :otherthings] for multiple nested routes
I think the has_many syntax was something added to Rails 2 as a shorthand for those that didn't like the block syntax. You can see a blog post about it here. I just tried it and it seems that Rails 3 ignores the has_many option. So the output for me was:
resources :schools do
resources :documents
end
created the routes:
school_documents GET /schools/:school_id/documents(.:format) {:action=>"index", :controller=>"documents"}
POST /schools/:school_id/documents(.:format) {:action=>"create", :controller=>"documents"}
new_school_document GET /schools/:school_id/documents/new(.:format) {:action=>"new", :controller=>"documents"}
edit_school_document GET /schools/:school_id/documents/:id/edit(.:format) {:action=>"edit", :controller=>"documents"}
school_document GET /schools/:school_id/documents/:id(.:format) {:action=>"show", :controller=>"documents"}
PUT /schools/:school_id/documents/:id(.:format) {:action=>"update", :controller=>"documents"}
DELETE /schools/:school_id/documents/:id(.:format) {:action=>"destroy", :controller=>"documents"}
schools GET /schools(.:format) {:action=>"index", :controller=>"schools"}
POST /schools(.:format) {:action=>"create", :controller=>"schools"}
new_school GET /schools/new(.:format) {:action=>"new", :controller=>"schools"}
edit_school GET /schools/:id/edit(.:format) {:action=>"edit", :controller=>"schools"}
school GET /schools/:id(.:format) {:action=>"show", :controller=>"schools"}
PUT /schools/:id(.:format) {:action=>"update", :controller=>"schools"}
DELETE /schools/:id(.:format) {:action=>"destroy", :controller=>"schools"}
while
resources :schools :has_many => :documents
created the routes:
schools GET /schools(.:format) {:action=>"index", :controller=>"schools"}
POST /schools(.:format) {:action=>"create", :controller=>"schools"}
new_school GET /schools/new(.:format) {:action=>"new", :controller=>"schools"}
edit_school GET /schools/:id/edit(.:format) {:action=>"edit", :controller=>"schools"}
school GET /schools/:id(.:format) {:action=>"show", :controller=>"schools"}
PUT /schools/:id(.:format) {:action=>"update", :controller=>"schools"}
DELETE /schools/:id(.:format) {:action=>"destroy", :controller=>"schools"}
I think the real answer to your question is that those are/were supposed to do the same thing, just with different syntax.
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.
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.