Zeno
Zeno

Reputation: 1829

Ruby on Rails: link_to action, no route matches

I'm getting into Rails and trying to add a "vote" feature on a blog setup from here: http://guides.rubyonrails.org/getting_started.html

In app/controllers/posts_controller.rb I created this:

  def incvotes
    @post = Post.find(params[:id])
    post.update_attributes(:upvotes => 1 )
    format.html { redirect_to(@post, :notice => 'Vote counted.') }
    format.xml  { head :ok }
  end

In app/views/posts/index.html.erb I created this:

<%= link_to 'Vote', :controller => "posts", :action => "incvotes", :id => post.id %>

But the link is giving the error

No route matches {:controller=>"posts", :action=>"incvotes", :id=>1}

I'm missing something here, but not sure what.

rake routes:

incvotes_post POST   /posts/:id/incvotes(.:format) {:action=>"incvotes", :controller=>"posts"}
        posts GET    /posts(.:format)              {:action=>"index", :controller=>"posts"}
              POST   /posts(.:format)              {:action=>"create", :controller=>"posts"}
     new_post GET    /posts/new(.:format)          {:action=>"new", :controller=>"posts"}
    edit_post GET    /posts/:id/edit(.:format)     {:action=>"edit", :controller=>"posts"}
         post GET    /posts/:id(.:format)          {:action=>"show", :controller=>"posts"}
              PUT    /posts/:id(.:format)          {:action=>"update", :controller=>"posts"}
              DELETE /posts/:id(.:format)          {:action=>"destroy", :controller=>"posts"}
   home_index GET    /home/index(.:format)         {:action=>"index", :controller=>"home"}
         root        /(.:format)                   {:action=>"index", :controller=>"home"}

Upvotes: 5

Views: 15101

Answers (4)

monteirobrena
monteirobrena

Reputation: 2620

Try using button_to instead link_to:

In your view:

<%= button_to 'Vote', incvotes_post_path(post) %>

In your config/routes.rb add the route to incvotes action as post:

resources :posts do 
  member do
    post 'incvotes'
  end
end

And in your controller, create the incvotes action:

def incvotes
  # Something
  redirect_to :posts
end

Upvotes: 0

stephenmurdoch
stephenmurdoch

Reputation: 34603

try

= link_to "vote", incvotes_post_path(post), :method=>:post

and if that doesn't work, try changing the method to :put

Upvotes: 3

Brett Bender
Brett Bender

Reputation: 19738

My guess is that you probably do not have a definition in your routes file for the action you just defined in the controller. Both an action in the controller and an action in the routes file must be defined for Rails to generate urls correctly.

Your routes file probably has something like this:

resources :posts

But you want to add more than the standard actions generated by the resources keyword, so try something like this:

resources :posts do 
  member do
    post 'incvotes'
  end
end

This tells routes that you have another action in your posts controller called incvotes that accepts HTTP post requests as long as they are pointed at a member route with the correct action (/posts/14 is a member route, while /posts/ is a 'collection' route). So you will have a new route probably like /posts/14/incvotes that you can post a form to and everything should start working properly.

EDIT:

Actually I guess since you are just adding 1 to an attribute on a model, you don't need a POST action (which are normally associated with posting forms as with create and update). To send a post, you might need to change the HTML in the view to include a form and have it post to the correct url. So you can try that, or you can change your routes file to read get 'incvotes' instead of post 'incvotes'. Sorry for the confusion, hope that helps!

Upvotes: 3

Michiel de Mare
Michiel de Mare

Reputation: 42420

The incvotes_post route only accepts a HTTP POST, and a link always produces a HTTP GET.

Use a form with a button instead (or do a POST using AJAX).

Upvotes: 1

Related Questions