I just recently started programming in Ruby on Rails, and I was wondering if some of you could look over my routes.rb file that I am using so far and tell me if I am over thinking this.
I am aware of the whole RESTful approach in RoR and I am trying to stick to it, but I am not sure if I am on track. So far my application only has the following functionality:
User registration
User activation (via email link)
User can request activation to be resent
User log in
User log out
User requests password reset (gets an email)
Basic UCP (change email and password)
I am using a lot of redirect_to *_url and *_path, so I want a lot of named routes. I am trying to explicitly declare only routes that are allowed. Thanks for your input.
MyApp::Application.routes.draw do
get 'home' => 'pages#index', :as => 'home'
get 'testing' => 'pages#testing', :as => 'testing'
get 'register' => 'users#new', :as => 'register'
post 'users/create'
resources :users, :only => [
:new,
:create
]
get 'activation' => 'activations#new', :as => 'activation'
get 'activate/:token' => 'activations#activate', :as => 'activate'
post 'activations/edit'
resources :activations, :only => [
:new,
:activate,
:edit
]
get 'login' => 'sessions#new', :as => 'login'
get 'logout' => 'sessions#destroy', :as => 'logout'
get 'sessions/destroy'
resources :sessions, :only => [
:new,
:create,
:destroy
]
get 'forgot_password' => 'resets#new', :as => 'forgot_password'
post 'resets/create'
get 'activate_password/:token' => 'resets#activate', :as => 'activate_password'
put 'save_password' => 'resets#save', :as => 'save_password'
resources :resets, :only => [
:new,
:create,
:activate,
:save
]
get 'ucp' => 'ucp#show', :as => 'ucp'
post 'ucp_update' => 'ucp#update', :as => 'ucp_update'
resources :ucp, :only => [
:show,
:update
]
root :to => 'pages#index'
end
When you use resources, it automatically makes named routes for you. I won't go through your entire routes file, but one example:
get 'activation' => 'activations#new', :as => 'activation'
get 'activate/:token' => 'activations#activate', :as => 'activate'
post 'activations/edit'
resources :activations, :only => [
:new,
:activate,
:edit
]
Could be:
resources :activations, :only => [:new, :edit] do
get 'activate', :on => :member
end
which will produce new_activation_path, edit_activation_path, and activate_activation_path
Go to the Rails Routing Guide for a lot of cool stuff you can do in routes. For example, if you want to use "register" instead of "new" for your Users paths:
resources :users, :only => [:new, :create], :path_names => [:new => 'register']
Related
I'm setting up my website such that
www.website.com/articles/2013/07 will list all articles from 2013 in July and
www.website.com/articles/2013 will list all articles in 2013
www.website.com/articles/2013/07/title-of-article will list just the specific article
However, I am able to get only the first and last of the above 3 to work. Entering the url
www.website.com/articles/2013 is not working properly. Specifically, I get a noMethodError in Articles#show which doesn't make sense to me because I have matched the route to Articles#index.
Can someone please explain what's going on here? I don't see where I am making a mistake.
Routes:
match "/articles/:year", :to => "articles#index",
:constraints => { :year => /\d{4}/ }, :as=> :posts_year
match "/articles/:year/:month", :to => "articles#index",
:constraints => { :year => /\d{4}/, :month => /\d{1,2}/ }, :as => :posts_month
match "/articles/:year/:month/:slug", :to => "articles#show",
:constraints => { :year => /\d{4}/, :month => /\d{1,2}/, :slug => /[a-z0-9\-]+/ }, :as => :posts_date
and in my model I have:
def year
created_at.year
end
def month
created_at.strftime("%m")
end
Do you have resources :articles in your routes file? If you do, that explains the error. Move resources :articles below the routes you mentioned in your question and everything should work fine. Alternatively you could change it to:
resources :articles, :except => :show
Guessing that if you've defined articles as a resource, then the default show/:id route is taking precedence over your :posts_year route. Maybe try resources :articles, :except => [:show]
I would like to add a url to my comments route so I can call "post_comments_latest_path". I added something like 'get "comments/latest" => "comments#latest", :as => "latest"' but the route adds and the :commend_id to the path that is not needed. Any suggestions?
resources :posts, :except => [:index] do
resources :comments, :except => [:index, :show] do
post "replies" => "comments#create_reply", :as => "create_reply"
get "replies/new" => "comments#new_reply", :as => "new_reply"
end
end
This should work:
resources :posts, :except => [:index] do
resources :comments, :except => [:index, :show] do
post "replies" => "comments#create_reply", :as => "create_rely"
get "replies/new" => "comments#new_reply", :as => "new_reply"
get "latest", :on => "collection"
end
end
A Member route is one that links to a specific resource; requires an id.
A Collection route is one that links to a resource collection; does not require an id.
See the Rails Routing Guide for more information.
Pretty simple question, but I can't seem to figure out how to do this, even after scouring the Rails Routing guide.
Assume Topics has nested resource Posts.
The Posts for a Topic are all listed in Posts#index (/topics/:topic_id/messages). Topics#show does not serve any purpose. I would like Posts#index to be retrieved when the request is for /topics/:topic_id, without having to stick a redirect in the Topics controller.
Thank you!
UPDATE
I was able to get the desired result with this:
routes.rb
match 'forums/:forum_id' => 'topics#index', :as => 'forum_topics', :via => :get
match 'topics/:topic_id' => 'messages#index', :as => 'topic_messages', :via => :get
resources :forums, :shallow => true, :except => :show do
resources :topics, :shallow => true, :except => :show do
resources :messages
end
end
However, I'm not sure if this is the best method.
UPDATE 2
My method above breaks the other CRUD methods (like #create). Still looking for a solution to keep /messages out of the url.
add this route
get "/topics/:topic_id" => redirect("/topics/%{topic_id}/messages")
UPD
without redirecting:
get "/topics/:id" => "topic::Messages#index"
Or, if you're using shallow:
get "/topics/:id" => "messages#index"
resources :forums, :shallow => true, :except => :show do
resources :topics, :shallow => true, :except => :show do
resources :messages
end
end
I'm developing a rails app with an admin section and a public section. In the public section I want to resolve only index and show routes
resources :services, :only => [:index, :show]
However, when I hit the standard URL for the new action it resolves to the show action with an id of 'new'. That is http://foo.com/services/new returns an error "Couldn't find Service with ID=new". Is there anyway I can tell rails NOT to resolve /services/new?
I've already tried
resources :services, :only => [:index, :show], :except => :new
and
resources :services, :except => :new, :only => [:index, :show]
without success.
ETA (by request):
My entire routes file (sans comments):
MyApp::Application.routes.draw do
resources :services, :only => [:index, :show]
resources :packages,:only => [:index, :show]
get "pages/home"
get "pages/about"
get "pages/help"
root :to => 'packages#index'
namespace "admin" do
get "pages/home"
get "pages/about"
get "pages/help"
resources :services
match "/services/:id/add_to_package/:package_id" => "services#add_package", :as => :add_package_to_service, :via => :post, :id => /\d+/, :package_id => /\d+/
match "/services/:id/remove_from_package/:package_id" => "services#remove_package", :as => :remove_package_from_service, :via => :post, :id => /\d+/, :package_id => /\d+/
resources :packages
match "/packages/:id/add_service/:service_id" => "packages#add_service", :as => :add_service_to_package, :via => :post, :id => /\d+/, :service_id => /\d+/
match "/packages/:id/remove_service/:service_id" => "packages#remove_service", :as => :remove_service_from_package, :via => :post, :id => /\d+/, :service_id => /\d+/
resources :users
root :to => 'pages#home'
end
end
You can try to putting a constraint on your :id param
resources :services, :constraints => {:id => /\d+/}, :only => [:index, :show]
This is assuming your :ids are all number based.
I had a similar situation with a redirect vs resource collision, this fixed it.
Well I have the following code for routing with nested resources:
map.resources :cities, :as => "cidade", :only => [:index, :show] do |city|
city.resources :offers, :as => "oferta", :only => [:show], :collection => [:recents], :member => [:share, :buy, :add, :add_gift, :remove, :validate_buy, :want_more, :withdraw_credits], :path_names => { :want_more => "quero-mais", :recents => "recentes", :buy => "comprar", :add_gift => "comprar-presente", :share => "compartilhar", :add => "adicionar", :remove => "remover", :validate_buy => "validar-compra", :withdraw_credits => "resgatar-creditos" } do |offer|
offer.resources :photos, :as => "fotos", :only => [:index]
offer.resources :videos, :as => "videos", :only => [:index, :show]
offer.resources :comments, :as => "comentarios", :only => [:index, :new, :create]
end
end
The thing is I don't want all those ':as =>' to be on the url, by this I mean that I don't want the controllers names on the url, istead of generating /cidades/curitiba/ofertas/1 I only want /curitiba/1.
I've tried :path_prefix and :as => "", but those did not work.
any help?
thanks
What if you try this after the map.resources definition in routes.rb?
match '/:city_name/:id', :to => "offers#show"
Then you do whatever you want in offers_controller#show