我的类Facebook应用程序让用户有机会从以下用户中删除不需要的消息。为此,我在用户和微博之间创建了MicropostQuarantine
关联:如果存在用户和微博之间的这种关联,那么该用户将不会在其提要中看到该微博。但是,微博也会在用户的个人资料页面中显示,包括那些已经隔离的微博。因此,如果我从我的Feed中删除了微博并访问了该微博用户的个人资料页面,我仍然会看到该微博并且可以访问会导致以下错误的删除按钮:
ActiveRecord::RecordNotUnique (PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "index_micropost_quarantines_on_user_id_and_micropost_id"
DETAIL: Key (user_id, micropost_id)=(1, 300) already exists.
: INSERT INTO "micropost_quarantines" ("user_id", "micropost_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"):
微博控制器中的隔离方法很简单:
def quarantine
current_user.micropost_quarantines.create!(micropost_id: @micropost.id)
end
before_action :entitled_user, only: :quarantine
定义如下:
def entitled_user
@micropost = Micropost.find(params[:id])
redirect_to root_url unless (current_user == @micropost.user || current_user.following.include?(@micropost.user))
end
正如您所看到的,用户只能隔离来自后续用户的微博和微博。为了避免UniqueViolation错误,我想到为entitled_user
方法添加一些代码,以检查关联是否已经存在:
def entitled_user
@micropost = Micropost.find(params[:id])
@quarantine = MicropostQuarantine.find_by(micropost_id: @micropost.id, user_id: current_user.id)
redirect_to root_url unless (current_user == @micropost.user || current_user.following.include?(@micropost.user) || @quarantine.nil?)
end
但是这不起作用:导出忽略/绕过entitled_user
方法由于某些未知原因,我一直从ActiveRecord接收UniqueViolation: ERROR
并忽略整个unless
条件,这样我就可以隔离非后续用户的微博。
答案 0 :(得分:1)
我认为我们不应该在复杂条件下使用unless
,请尝试以下方法:
redirect_to root_url if (current_user != @micropost.user && current_user.following.exclude?(@micropost.user)) || @quarantine.present?
提示:
def entitled_user
@micropost = Micropost.find(params[:id])
if (current_user.id != @micropost.user_id && !current_user.following.exists?(@micropost.user_id)) ||
current_user.micropost_quarantines.exists?(micropost_id: @micropost.id)
redirect_to root_path and return
end
end
:exists?
(SQL端)比:include?
(Ruby端)更有效@micropost.user_id
代替@micropost.user
因为我们不需要实例@user
,所以我们不需要这样做: SELECT (*) FROM users WHERE id = #{@micropost.user_id}
希望这有帮助!