1

What I want to accomplish is to create POST and DELETE links into my views, as a like button, for example.

I have created a method (def liked) in my user model (user.rb) that will check if a user has liked a bookmark or not, and show 'unlike' or 'like' buttons, respectively based on the response of my liked method.

I have the following code:

Routes.rb:

Rails.application.routes.draw do

  resources :topics do
    resources :bookmarks do
      resources :likes, only: [:create, :destroy]
    end
  end

  devise_for :users

  get 'welcome/index'
  get 'welcome/about'

  root to: 'welcome#index'

  post :incoming, to: 'incoming#create'
end

User.rb:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :confirmable

  has_many :topics, dependent: :destroy
  has_many :bookmarks, dependent: :destroy
  has_many :likes, dependent: :destroy

  def admin?
    role == 'admin'
  end

  def moderator?
    role == 'moderator'
  end

  def liked(bookmark)
    likes.where(bookmark_id: bookmark.id).first
  end

end

likes_controller.rb:

class LikesController < ApplicationController

  def create
    @bookmark = Bookmark.find(params[:bookmark_id])
    like = current_user.likes.build(bookmark: @bookmark)

    if like.save
      flash[:notice] = "Bookmark was Liked!"
      redirect_to [@bookmark.topic, @bookmark]
    else
      flash[:error] = "Unable to Like Bookmark"
      redirect_to @bookmark
    end
  end

  def destroy
    @bookmark = Bookmark.find(params[:bookmark_id])
    like = current_user.likes.find(params[:id])

    if like.destroy
      flash[:notice] = "Bookmark was Un-liked."
      redirect_to [@bookmark.topic, @bookmark]
    else
      flash[:error] = "Error Un-liking bookmark."
      redirect_to [@bookmark.topic, @bookmark]
    end
  end

end

And finally my like partial, _like.html.erb:

<div>
  <% if like = current_user.liked(bookmark) %>
    <%= link_to [bookmark, like], class: 'btn btn-danger', method: :delete do %>
      <i class="glyphicon glyphicon-star-empty"> </i>&nbsp; Unlike
    <% end %>
  <% else %>
    <%= link_to [bookmark, Like.new], class: 'btn btn-primary', method: :post do %>
      <i class="glyphicon glyphicon-star"> </i>&nbsp; Like
    <% end %>
  <% end %>
</div>

Which I want to use in my topics#index view:

<h2 id="page-title">All Bookmarks</h2>

<div class="row">
  <div class="col-md-8">
    <% @topics.each do |topic| %>
      <h4><%= link_to "##{topic.title}", topic_path(topic.id) %></br></h4>
      <% topic.bookmarks.each do |bookmark| %>
        <%= render partial: 'likes/like', locals: { bookmark: bookmark } %>
        <%= link_to "#{bookmark.url}", "http://#{bookmark.url}", target: "_blank" %></br>
      <% end %>
    <% end %>
  </div>
  <div class="col-md-4">
    <%= link_to "New Topic", new_topic_path, class: 'btn btn-primary' %>
  </div>
</div>

When I run my server and go to my index view, I receive the following NoMethodError:

undefined method `bookmark_likes_path' for #<#:0x007ffe2817b5a0>

Pointing to this line:

<%= link_to [bookmark, Like.new], class: 'btn btn-primary', method: :post do %>

Which is located in my like partial (_like.html.erb)

I think that the problem is a routing problem, because as far as I know, the problem is saying that the method bookmark_likes_path is nil, and if I check my rake routes, I get the following: (with grep)

topic_bookmark_likes POST   /topics/:topic_id/bookmarks/:bookmark_id/likes(.:format)     likes#create
     topic_bookmark_like DELETE /topics/:topic_id/bookmarks/:bookmark_id/likes/:id(.:format) likes#destroy

So that indicates my routes for likes, which says the (because is a nested resource) correct route for access the POST and DELETE actions, which are inside topics, so the path needs to be /topics/:topic_id/bookmarks/:bookmark_id/likes for create, and /topics/:topic_id/bookmarks/:bookmark_id/likes/:id for delete, so I updated my like partial like this:

<div>
  <% if like = current_user.liked(bookmark) %>
    <%= link_to [@topic, bookmark, like], class: 'btn btn-danger', method: :delete do %>
      <i class="glyphicon glyphicon-star-empty"> </i>&nbsp; Unlike
    <% end %>
  <% else %>
    <%= link_to [@topic, bookmark, Like.new], class: 'btn btn-primary', method: :post do %>
      <i class="glyphicon glyphicon-star"> </i>&nbsp; Like
    <% end %>
  <% end %>
</div>

And still the same error. I've been trying to debug this error for a long time, and I'm unable to fix it, I need some help.

Thanks in advance!

fuzzyalej
  • 5,903
  • 2
  • 31
  • 49
bntzio
  • 1,274
  • 14
  • 27

1 Answers1

0

I've already fix it.

The problem was with the nested resources indeed, what I did was to separate the resources like this:

  resources :topics do
    resources :bookmarks
  end

  resources :bookmarks do
    resources :likes, only: [:create, :destroy]
  end

And that solved it, so I didn't have to mess with long routes in order to get into the nitty gritty.

bntzio
  • 1,274
  • 14
  • 27