44 lines
1.8 KiB
Ruby
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
|