Simple routing error - ruby-on-rails

Total noob question.
I am building a simple photoblog in Rails which consists of Posts. Each post has its own id "/posts/1". I built Posts using rails scaffolding.
The problem is that I am unable to go to a url such as "/posts/index" or "/posts/anything" because it's trying to match anything after "/posts/" it to an id... So I get back an error like:
Couldn't find Post with ID=index
I'm sure this could be fixed with routes, but I'm not really sure how and I feel that there is some big-picture problem I am missing here.
You can clone my app from here: https://github.com/tbhockey/PhotoBlog
Thank you.

Running rake routes is usually pretty helpful. In this case, the route to your index should just be /posts (not /posts/index). If you run rake routes you'll probably see something like
posts GET /posts(.:format) {:action=>"index", :controller=>"posts"}
That's trying to tell you that the URL /posts will be directed to the index action of your posts_controller. Also, this may be referred to in your code as posts_path or posts_url.

Try to do this for your routes.rb :
scope :path => '/posts', :controller => :posts do
get 'show/(:id)' => :show, :as => 'show_post'
end
For a /posts/show/1, it will call the show action of the posts controller.
It's always a nice idea to learn about how routing works in Rails. It's very important and will help you understand many things about Rails. Especially looking at named routes is vital for good Rails programming.

Related

Nested routes in rails

I am someone who has always liked sinatra better than rails, and has never had to do a large enough scale project that rails was required (all the sources I have read say that rails is better for larger scale projects) and now I do have to do a large scale project. I have gotten very confused with the url structure of rails. What I am trying to do is the rails equivalent of this:
get "/" do
erb :index
end
get "/home" do
erb :dashboard
end
get "/home/profile" do
erb :profile
end
get "/home/friends" do
erb :friends
end
In the first one I understand that I should put in app/routes.rb I should put root home#index and in the home controller I should put def index end.
In the second one, I understand that I should do the same except replacing index with home.
But for the third and forth ones I have no idea what to do.
Also, is the a RESTful way to do the first two?
You probably want something like this
root 'home#index'
get 'home' => 'home#dashboard'
get 'home/profile' => 'home#profile'
get 'home/friends' => 'home#friends'
remember to use the command rake routes to see all your routes, where they lead and what their names are (if they have any)
I never understood what RESTful means, so someone else will have to answer that part of your question.
K M Rakibul Islam has shown you what can be called a "resourceful" way to do routes (because it uses the keyword resources) but it looks like you're just doing the static pages at this stage, so it's not necessary.
The simplest way to do routes is with this formula:
method url => controller::action, as: route_name
where method can be get, post, patch or delete so you can have different actions linked to the same URL depending on the method the request uses.
Putting a name on the route is optional, but it gives you a clean way to use the route in your views (route_name_path)
When you start making models then you'll find that using the resources keyword comes in handy. Read about it.
You can have this:
resources :home do
collection do
get :profile
end
collection do
get :friends
end
end
end
This will give you routes like this:
profile_home_index GET /home/profile(.:format) home#profile
friends_home_index GET /home/friends(.:format) home#friends
The standard way of declaring the root path:
root 'home#index'
And for the 2nd one, you have to do:
get 'home' => 'home#dashboard'
which will give you this route:
GET /home(.:format) home#dashboard
One route can be defined in many ways that works. But, Rails has conventions that should be followed while defining routes in your Rails app.
I would highly recommend you to take a look at the Rails Routing Guide

Changing the route from posts/article to blog/article in rails

I'm in trouble with routes in Rails. I've been trying to get a path like: home/blog/title-article but the closes I get is: home/blog/posts/title-article
I've tried with namespace, scope and one by one with get 'blog' => 'posts#blablabla', but I get errors like UrlGenerationError or NameError every time I change the paths. I've read the official guide and some answers in this forum, but I'm getting more confused hehe
In my last try I generated a controller Blog and a scaffold Post. The output of rake routes is: http://i.stack.imgur.com/gdfPc.png
routes.rb
Rails.application.routes.draw do
scope :blog do
resources :posts
end
get 'blog' => 'blog#index'
root 'pages#index'
...
Thank you!
Now my routes are like: http://i.stack.imgur.com/cKsFG.png
Thank you!
Not sure its what you expect but try:
resources :posts, path: 'blog'
Feels weird though.
Btw, I guess you have the errors due to url helpers.
use rake routes to check the existing routes and the related url helpers.
Doc lives here

Rails routes for cms cms powered site

I've been away from Rails for a while but I have a site that is running on rails where I have created a page editor. I need some help with my routes.
I want to have something like this for my URL on the front end of the site:
//domain/welcome/pagename/page or //domain/welcome/page/pagename
Then within the welcome_controller I have this:
def page
# I provide the user with the a page
#mypage = Contents.find_by_name(params[:pagename])
end
Then within the page view itself I can render aspects of the #mypage record as I see fit.
However, I need some help with the routes to get this all working the way I intend.
Currently, I have this for my welcome route:
resources :welcome do
collection do
get :site
get :home
get :page
get :thankyou
post :newslettersignup
post :sendcontact
end
end
I know that I need more... Just now sure exactly what it should be.
Any help would greatly be appreciated!
You can use non-resourceful routing to do this easily:
get '/welcome/:pagename/site', to: 'welcome#site'
get '/welcome/:pagename/home', to: 'welcome#home'
get '/welcome/:pagename/page', to: 'welcome#page'
get '/welcome/:pagename/thankyou', to: 'welcome#thankyou'
post '/welcome/:pagename/newslettersignup', to: 'welcome#newslettersignup'
post '/welcome/:pagename/sendcontact', to: 'welcome#sendcontact'
The :pagename syntax allows the value of that segment of the URL to be included in params[:pagename]. The to: 'welcome#site' bit means, "Route this to the WelcomeController#site action."
Please see Rails Routing from the Outside In for a great reference when working with routes.

A very basic issue with routes in ruby

I am new to ruby and while creating a sample application found out an issue that whenever I go to http://127.0.0.1:3000/people/index by default show action is executed and index is taken as a parameter. This is server log:
Started GET "/people/index" for
127.0.0.1 at 2010-12-23 18:43:01 +0500 Processing by PeopleController#show as
HTML Parameters: {"id"=>"index"}
I have this in my route file:
root :to => "people#index"
resources :people
match ':controller(/:action(/:id(.:format)))'
What is going on here and how can I fix the issue?
The route
resources :people
creates "sub"-routes
get '/people' => 'people#index'
get '/people/new' => 'people#new'
post '/people' => 'people#create'
get '/people/:id' => 'people#show'
get '/people/:id/edit' => 'people#edit'
put '/people/:id' => 'people#update'
delete '/people/:id' => 'people#destroy'
Actually, all of these sub-routes include (.:format) at the end of the recognized path.
The path /people/index would be recognized by the route /people/:id, mapping to the action #show.
The path /people would be recognized by the route /people, mapping to the action #index.
Use the URL helpers people_path and people_url for the /people route.
To get Rails to travel backward in time to before it espoused REST and to understand /people/index, do this:
resources :people do
get :index => 'people#index'
end
You might want to watch this Railscast episode.
A couple things to keep in mind when working with your routes:
rake routes dumps the map of URLs to your controllers
When providing backwards compatibility, redirect the user to the correct path
I personally have yet to upgrade my app to Rails 3, and I'll be dragging my feet until I really need to do it (just got it out the door not too long ago). In Rails 2.x you had resource routes, but if you kept the default controller/action/id route it would fall through and resolve. It appears that is no longer the case in Rails 3. Essentially your resource routes handle all URLs in that resource namespace (/people in your case).
To provide backwards compatibility, I would add a redirect route to resolve that incompatibility.
match "/people/index", :to => redirect("/people")
The main reason for that is to prevent users from saving an incorrect URL for their personal links--while allowing legacy users to still be able to get where they meant to go.
Edit: New answer, removed pointing out the typo in the question.

Strange routing error in Rails 3.0.1

This irritates me right now, and I've been at it for more than an hour. Maybe one of you has an idea.
I've defined the following routes in routes.rb:
resources :ads do
member do
post :preview_revision
get :revise
end
collection do
get :search
post :preview
end
end
When I run rake routes, the preview_revision route is shown correctly:
preview_revision_ad POST /ads/:id/preview_revision(.:format) {:action=>"preview_revision", :controller=>"ads"}
However, when I make a POST request to /ads/145/preview_revision, I get the following error:
Started POST "/ads/145/preview_revision" for 127.0.0.1 at Mon Nov 15 17:45:51 +0100 2010
ActionController::RoutingError (No route matches "/ads/145/preview_revision"):
Rendered /Library/Ruby/Gems/1.8/gems/actionpack-3.0.1/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.2ms)
The id (145) exists, yes.
The action and the controller (action: preview_revision, controller: ads) exist as well.
All the other routes work perfectly fine
I've tried restarting the server several times
I double-checked that it's actually a POST request, that the ID is correct, I really don't know what to do anymore.
Rails version is 3.0.1
--- UPDATE ---
I tried changing the method from POST to PUT, and now it works. Apparently POST routes on member level are not working, or not allowed.
Still, I want to know why. I do know that POST is for creating a member, so a POST request on a member makes no sense, but I didn't find this mentioned anywhere in the Rails guides, and why would rake routes display the route, if it doesn't actually work? Is that a bug?
--- UPDATE 2 ---
The Rails Routing guide (Edge version) specifically says:
2.9.1 Adding Member Routes
To add a member route, just add a
member block into the resource block:
resources :photos
do member do
get 'preview'
end
end
This will recognize /photos/1/preview
with GET, and route to the preview
action of PhotosController. It will
also create the preview_photo_url and
preview_photo_path helpers.
Within the block of member routes,
each route name specifies the HTTP
verb that it will recognize. You can
use get, put, post, or delete here. If
you don’t have multiple member routes,
you can also pass :on to a route,
eliminating the block [...]
So is the POST on member possible or not possible? Am I missing something? Just to be clear, I don't wanna use it anymore, but still, it bugs me not knowing why it doesn't work.
The best thing to do, if you find a bug in actively maintained open-source software, is:
to submit a bug report to the project's bug tracker isolating the problem as much as possible and with as much detail as possible, and, optionally,
to include a patch that fixes the bug if you can.
The bug tracker for Rails is at rails.lighthouseapp.com.
---edit---
The bug tracker for Rails is now at github.com/rails/rails/issues.
That should be working. I've created a blank app with 3.0.1 and added those routes and it worked.
Have you tried passing the :on param? Something like:
resources :ads do
post :preview_revision, :on => :member
get :revise, :on => :member
get :search, :on => :collection
post :preview, :on => :collection
end

Resources