Timmy Von Heiss
Timmy Von Heiss

Reputation: 2218

How to do redirect and give an error message after failed put

class FavoritePhoto < ActiveRecord::Base
  belongs_to :user
  belongs_to :photo
  validates :user_id, uniqueness: { 
   scope: [:photo_id],
   message: 'can only favorite an item once'
   }
end

PhotosController
def favorite
  @photo = Photo.find(params[:id])
  if request.put?
    current_user.favorites << @photo
    redirect_to :back, notice: 'You successfully favorited this photo'
  else request.delete?
    current_user.favorites.delete(@photo)
    redirect_to :back, notice: 'You successfully unfavorited this photo'
  end
end

<%= link_to favorite_photo_path("#{photo.id}"), method: :put do %>
  <span class="glyphicon glyphicon-heart"></span>
<% end %>

resources :photos do
  match :favorite, on: :member, via: [:put, :delete]
end

This works in preventing the User from favoriting the same photo more than once and the error message "User can only favorite an item once" shows up in my Heroku log, however, when they attempt to favorite a photo twice there is no redirect and message explaining to the User what has happened, it just times out at favorite_photo_path('#{photo.id}").

Upvotes: 0

Views: 119

Answers (3)

Timmy Von Heiss
Timmy Von Heiss

Reputation: 2218

  def favorite
    @photo = Photo.find params[:id]
    if request.put?
      response = current_user.favorite_photos.new(photo: @photo)
      if !response.valid?  
       redirect_to :back
       flash[:danger] = "You have already favorited this photo"
      else
       response.save
       redirect_to :back 
       flash[:success] = "You have successfully favorited this photo"
     end
   else request.delete?
     current_user.favorites.delete(@photo)
     redirect_to :back, notice: 'You successfully unfavorited this photo' 
   end 
 end

This is the only one I have gotten to work thus far.

Upvotes: 1

Richard Peck
Richard Peck

Reputation: 76784

The issue is that you're relying on ActiveRecord validations to populate your view, when they're separate layers of abstraction.

You will need to include some sort of conditional logic to determine whether the @photo passes the validations you've set:

#app/controllers/photos_controller.rb
class PhotosController < ApplicationController
  def favorite
    @photo = Photo.find params[:id]

    response = current_user.favorites << @photo if request.put?
    response = current_user.favorites.delete @photo if request.delete?   

    if response.valid? 
      message = response.errors.full_messages.first
    else
      message = request.put? ? "You have successfully favourited this photo" : "You have successfully unfavourited this photo"
    end
    redirect_to @photo, notice: message
  end
end

Upvotes: 0

oreoluwa
oreoluwa

Reputation: 5633

I'm not totally sure the best approach is to perform a delete and an update in the same action, but if you'd like to do it this way, you could do something like:

User
  has_many :favorite_photos

PhotosController
def favorite
  @photo = Photo.find(params[:id])
  if request.put?
    favorite = current_user.favorite_photos.new(photo: @photo)
    if favorite.save
       redirect_to :back, notice: 'You successfully favorited this photo'
    else
       redirect_to photo_path(@photo), notice: favorite.errors.full_messages
    end
  else request.delete?
    current_user.favorites.delete(@photo)
    redirect_to :back, notice: 'You successfully unfavorited this photo'
  end
end

Upvotes: 0

Related Questions