Files
prism/examples/blog/app/controllers/likes_controller.rb
T

44 lines
1.8 KiB
Ruby

class LikesController < ApplicationController
before_action :require_authentication
# Only Post/Comment may be liked - likeable_type otherwise rides in fully
# client-controlled request params, so without this whitelist a crafted
# request could aim a Like at an arbitrary model by name (e.g. User) and
# #likeable would happily resolve it.
LIKEABLE_TYPES = { 'Post' => Post, 'Comment' => Comment }.freeze
def create
likeable = find_likeable!
Like.create(user_id: current_user.id, likeable_id: likeable.id, likeable_type: likeable.class.name)
redirect url_for(:post, slug: post_slug_for(likeable))
rescue Prism::Orm::RecordNotFound
respond_not_found(t('likes.not_found'))
end
def destroy
like = Like.find(params['id'])
authorize(like)
likeable = like.likeable
# really_destroy!, not the paranoid-aware plain #destroy - unliking is
# a permanent, unremarkable action with no "restore my unlike" concept
# in this app, unlike Post.acts_as_paranoid's actual trash/restore UI.
# Left as a soft delete, every unlike/relike cycle would pile up a
# dead Like row forever (uniqueness scope only sees live rows, so
# nothing would ever stop a visitor from accumulating one per cycle),
# and a post's dependent: :destroy cascade would then have no way to
# tell "trashed along with its post" apart from "explicitly unliked
# ages ago" when a restore brings the post's likes back.
like.really_destroy!
redirect url_for(:post, slug: post_slug_for(likeable))
rescue Prism::Orm::RecordNotFound
respond_not_found(t('likes.not_found'))
end
private
def find_likeable!
klass = LIKEABLE_TYPES.fetch(params['likeable_type']) { raise Prism::Orm::RecordNotFound }
klass.find(params['likeable_id'])
end
end