2017-10-30 25 views
0

알아 두어야 할 Rails Pundit Policy 범위가 있습니다.Rails 활성 레코드 where OR 절 (조부모 속성 포함)

나는이 세 모델이있는 경우 :

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] 

아이디어를 어떻게 작성하여 원하는대로 할 수 있습니까?

scope.joins(story: :user).where("(stories.published = ? AND chapters.published = ?) OR stories.user_id = ?", true, true, @user.id) 

이 더 비 SQL 문 방법을 기대했다,하지만 오 아니라, 누군가가 비 SQL 방법을 알고하지 않는 한이 할 것 같아요

답변

0

나는 마침내 그것을 거 같아요.

0

Arel을 보셨습니까?

이 뭔가를 할 수 :

chapters = Arel::Table.new(:chapter) 
stories = Arel::Table.new(:story) 
rel = chapters.joins(stories) 
    .where(chapters[:published].eq(true) 
    .where(stories[:published].eq(true)) 
    .or(stories[:user_id].eq(@user.id)) 
scope.where(rel) 
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)