2
votes

Hi I have a simple app with user, venue and heart models

User Model

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

  has_many :hearts, dependent: :destroy
  has_many :venues, through: :hearts

  def hearts?(venue)
    venue.hearts.where(user_id: id).any?
  end
end

Venue Model

class Venue < ApplicationRecord
    has_many :hearts, dependent: :destroy
    has_many :users, through: :hearts
end

Heart Model

class Heart < ApplicationRecord
  belongs_to :user
  belongs_to :venue

  validates :user_id, uniqueness: { scope: :venue_id }
end

The problem I have is that when I go to create a heart through the venue view I get the ActionController::RoutingError (No route matches [POST] "/venues/2/heart/2"):

app/views/venues/show.html.erb

<div class="row mb-3">
  <div class="col text-center">
    <h1><%= @venue.name %></h1>
  </div>
</div>
<div class="row mb-3">
  <div class="col text-center">
    <%= render partial: 'heart', locals: {venue: @venue} %>
  </div>
</div>

app/views/venues/_heart.html.erb

 <% if user_signed_in? &&  current_user.hearts?(venue) %>
      <%= link_to venue_heart_path(venue), method: :delete, remote: true do %>
        <i class="fas fa-heart fa-2x" style="color: #cc0000"></i>
      <% end %>
    <% else %>
      <%= link_to venue_heart_path(venue), method: :post, remote: true do %>
        <i class="far fa-heart fa-2x" style="color: #cc0000"></i>
      <% end %>
    <% end %>
  <p><%= venue.hearts.count %> <%= (venue.hearts.count) == 1 ? 'Heart' : 'Hearts'%></p>
  <% @venue.hearts.each do |heart| %>
  <%= image_tag heart.user.avatar_url, width: 20 %>
<% end %>

here is my controller for hearts and my routes|grep venue

app/controllers/venues/hearts_controller.rb

class Venues::HeartsController < ApplicationController
  before_action :authenticate_user! 
  before_action :find_venue!

  def create
    @venue.hearts.where(user: current_user).first_or_create
    redirect_to venue_path(@venue), :notice => 'Hearted!'
  end

  def destroy
    @venue.hearts.where(user: current_user).destroy_all
    redirect_to venue_path(@venue), :notice => 'UnHearted, you are heartless!'
  end

  private

    def find_venue!
      @venue = Venue.find(params[:venue_id])
    end
end

rake routes | grep venue
warning ../package.json: No license field                                                                                                                                                                                
                    venue_heart_index GET    /venues/:venue_id/heart(.:format)                                                        venues/heart#index
                                      POST   /venues/:venue_id/heart(.:format)                                                        venues/heart#create
                      new_venue_heart GET    /venues/:venue_id/heart/new(.:format)                                                    venues/heart#new
                     edit_venue_heart GET    /venues/:venue_id/heart/:id/edit(.:format)                                               venues/heart#edit
                          venue_heart GET    /venues/:venue_id/heart/:id(.:format)                                                    venues/heart#show
                                      PATCH  /venues/:venue_id/heart/:id(.:format)                                                    venues/heart#update
                                      PUT    /venues/:venue_id/heart/:id(.:format)                                                    venues/heart#update
                                      DELETE /venues/:venue_id/heart/:id(.:format)                                                    venues/heart#destroy
                               venues GET    /venues(.:format)                                                                        venues#index
                                      POST   /venues(.:format)                                                                        venues#create
                            new_venue GET    /venues/new(.:format)                                                                    venues#new
                           edit_venue GET    /venues/:id/edit(.:format)                                                               venues#edit
                                venue GET    /venues/:id(.:format)                                                                    venues#show
                                      PATCH  /venues/:id(.:format)                                                                    venues#update
                                      PUT    /venues/:id(.:format)                                                                    venues#update
                                      DELETE /venues/:id(.:format)                                                                    venues#destroy

config/routes.rb

require 'sidekiq/web'

Rails.application.routes.draw do

  resources :venues do
    resources :heart, module: :venues
  end

I really appreciate your help

3

3 Answers

1
votes

As the previous answer suggests, the path you're using in the link to create a new heart for a venue is not correct. Have a look at the route for creating a heart. It seems like it has no prefix, but the same prefix as the route before (for heart#index) applies. So the link to create a new heart should have the venue_heart_index_path(venue). I assume you didn't use resources in your routes.rb file?

1
votes

ok so with the help of @arieljuod and @clara I was able to find my solution:

the problem stemmed from the follow along i was doing from here https://github.com/gorails-screencasts/gorails-24-liking-posts/blob/master/config/routes.rb

because i had resource and not resources rails asked for a singular on the create.

venue_heart_path didnt work, venue_heart_index_path threw a

ActionController::RoutingError (uninitialized constant Venues::HeartController
Did you mean?  Venues::HeartsController): error

I went back to

<%= link_to venue_hearts_path(venue), method: :post, remote: true do %>
    <i class="far fa-heart fa-2x" style="color: #cc0000"></i>
  <% end %>

and changed the routes to

resources :venues do
    resources :hearts, module: :venues
  end

and the create worked... but the delete didnt. I had to change that to:

<%= link_to venue_heart_path(venue), method: :delete, remote: true do %>
    <i class="fas fa-heart fa-2x" style="color: #cc0000"></i>
  <% end %>

and boom it worked

0
votes

You don't have a route with that format and POST method:

                      venue_heart GET    /venues/:venue_id/heart/:id(.:format)                                                    venues/heart#show
                                  PATCH  /venues/:venue_id/heart/:id(.:format)                                                    venues/heart#update
                                  PUT    /venues/:venue_id/heart/:id(.:format)                                                    venues/heart#update
                                  DELETE /venues/:venue_id/heart/:id(.:format)

Use PATCH por PUT methods instead to update an object.