Boaz
Boaz

Reputation: 5084

rendering a partial fails only on ajax

My code is rather similar in concept to the railstutorial by Michael Hartl - the following users part, however it is different enough to ask this question.

The problem before all the details: When I remove the remote: true from _like, everything works smoothly, When _like.html.erb has remote: true I'm getting:

No route matches {:action=>"destroy", :controller=>"likes", :artwork_id=>1} missing required keys: [:id]

And I don't understand why.

The code snippets:

views/artworks
show.html.erb:

<div id="like_link">
    <% if @artwork.liked_users.include?(current_user) then %>
        <%= render 'unlike' %>
    <% else %>
        <%= render 'like' %>
    <% end%>
</div>

_unlike.html.erb:

<%= link_to 'UNLike', like_path(artwork_id: @artwork.id), method: :delete, remote: true %>

_like.html.erb:

<%= link_to 'Like', likes_path(artwork_id: @artwork.id), method: :post, remote: true %>

views/likes
create.js.erb:

$("#like_link").html("<%= escape_javascript(render("artworks/unlike")) %>")
$("#likes").html('<%= @artwork.likes_count %>')

destroy.js.erb:

$("#like_link").html("<%= escape_javascript(render("artworks/like")) %>")
$("#likes").html('<%= @artwork.likes_count %>')

and the likes controller - controllers/likes_controller.rb

class LikesController < ApplicationController
  respond_to :html, :js

  def create
    @artwork = Artwork.find(params[:artwork_id])
    current_user.like!(@artwork)
    respond_with @artwork
  end

  def destroy
    @artwork = Artwork.find(params[:artwork_id])
    current_user.unlike!(@artwork)
    respond_with @artwork
  end
end

routes.rb:

resources :artworks
resources :likes, only: [:create, :destroy]

Upvotes: 1

Views: 189

Answers (3)

HarsHarI
HarsHarI

Reputation: 911

here you create routes of

resources :likes, only: [:create, :destroy]

According RAILS convention it create routes for likes controller there it use :id such as "likes/:id" not likes/artwork_id so please create likes routes manually or follow convention.

Upvotes: 1

Nitin Jain
Nitin Jain

Reputation: 3083

you do not have o pass artwork id

<%= link_to 'Like', likes_path(@artwork), method: :post, remote: true %>

<%= link_to 'UNLike', like_path(@artwork), method: :delete, remote: true %>

and now you can access this in controller by

params[:id]

Upvotes: 0

vee
vee

Reputation: 38645

Here is the problematic line:

# _like.html.erb
<%= link_to 'Like', likes_path(artwork_id: @artwork.id), method: :post, remote: true %>

The problem here is likes_path(artwork_id: @artwork.id), method: :post. If you check the output of rake routes you should see the following two lines for your likes resources:

likes POST    /likes(.:format)               likes#create
like  DELETE  /likes/:id(.:format)           likes#destroy

As you can see the likes_path does not take in a parameter except the format, so your likes_path(artwork_id: @artwork.id) cannot be mapped to any path.

You should update your route definition with the following:

# app/config/routes.rb
resources :artworks do 
  resources :likes, only: [:create, :destroy]
end

With this route definition, your link_to calls will be:

# _like.html.erb
<%= link_to 'Like', artwork_likes_path(artwork_id: @artwork.id), method: :post, remote: true %>

# _unlike.html.erb
# Replace this_like_id with like_id attribute for this like being destroyed.
<%= link_to 'UNLike', artwork_likes_path(artwork_id: @artwork.id, id: this_like_id), method: :delete, remote: true %>

Upvotes: 0

Related Questions