Сильные параметры Rails предназначены для защиты массовых назначений и не подходят для этого случая.
Чтобы правильно создать дополнительный метод CRUD, вы можете просто добавить дополнительный маршрут к ресурсам:
resources :hacks do
post :upvote
delete :downvote
end
Обратите внимание, что мы используем POST
, а не GET
, поскольку это неидемпотентная операция.
Вам также не нужно передавать какие-либо параметры.:hacks_id
будет присутствовать в пути, и вы должны получать текущий идентификатор пользователя из сеанса, а не параметры запроса.
Передача идентификатора пользователя через параметры - очень плохая практика, так как очень просто подделатьиспользуя только веб-инспектор.
class HacksController < ApplicationController
before_action :set_hack!, except: [:new, :index, :create]
# POST /hacks/:hack_id/upvote
def upvote
@vote = @hack.votes.new(user: current_user)
if @vote.save
redirect_to @hack, success: 'Vote created'
else
redirect_to @hack, error: 'Vote could not be created'
end
end
# DELETE /hacks/:hack_id/downvote
def downvote
@vote = @hack.votes.where(user: current_user).first!
@vote.destroy
redirect_to @vote, success: 'Vote deleted'
end
private
# this will raise ActiveRecord::RecordNotFound if
# the id or hack_id param is not valid. This triggers a 404 response
def set_hack!
if params[:id].present?
Hack.find(params[:id])
else
Hack.find(params[:hack_id])
end
end
end
Затем вы можете создать ссылки / кнопки следующим образом:
<% if current_user && @hack.votes.where(user: current_user) %>
<%= button_to 'Downvote', hack_downvote_path(@hack), method: :delete %>
<% else %>
<%= button_to 'Upvote', hack_upvote_path(@hack), method: :post %>
<% end %>