我有一个Rails Pundit政策范围,我试图弄清楚。
如果我有这3个型号:
User - has many stories
Story - belongs to a user and has many chapters
Chapter - belongs to a story
我希望任何用户都能够查看任何发布的章节或用户编写的任何章节(甚至是未发布的章节)。
显然,如果我是一个撰写故事的作者,我应该能够查看我自己的故事以及我的所有章节,即使它们没有发表。但是,其他所有人只能查看我发表的故事,并在这些已发表的故事中发表章节。
我试过这个:
class ChapterPolicy < ApplicationPolicy
class Scope < Scope
def resolve
scope.where(published: true).or(scope.where("story.user.id = ?", @user.id))
end
end
end
据说我们需要使用我读过的JOINS,所以我也尝试了这个:
scope.where(published: true).or(scope.joins(:story).where(stories: { user: @user }))
但我收到错误:
Relation passed to #or must be structurally compatible. Incompatible values: [:joins, :references]
任何想法如何编写查询以执行我想要的操作?
答案 0 :(得分:0)
我想我终于明白了:
scope.joins(story: :user).where("(stories.published = ? AND chapters.published = ?) OR stories.user_id = ?", true, true, @user.id)
希望有更多的非SQL语句方式,但哦,好吧,猜想这样做除非有人知道非sql方式。
答案 1 :(得分:0)
答案 2 :(得分:0)
您可以使用Arel表达式来写这个:
Chapter.joins(story: :user)
.where(Chapter.arel_table[:published].eq(true))
.where(Story.arel_table[:published].eq(true))
.or(Chapter.joins(story: :user).where(Story.arel_table[:user_id].eq(user.id)))
该表达式产生此查询:
SELECT "chapters".* FROM "chapters" INNER JOIN "stories" ON "stories"."id" = "chapters"."story_id" INNER JOIN "users" ON "users"."id" = "stories"."user_id" WHERE ("chapters"."published" = 't' AND "stories"."published" = 't' OR "stories"."user_id" = 1)