Search code examples
ruby-on-railsactiverecordpundit

Rails active record where OR clause with grandparent property


I've got a Rails Pundit Policy scope which I'm trying to figure out.

If I have these 3 models:

User - has many stories
Story - belongs to a user and has many chapters
Chapter - belongs to a story 

I want any user to be able to view any published chapters or any chapters which were written by the user (even non-published ones).

Obviously if I am an author who wrote a story, I should be able to view my own stories as well as all my chapters for my stories, even if they are not published. Everyone else though, can only view my published stories and published chapters within those published stories.

I have tried this:

class ChapterPolicy < ApplicationPolicy
  class Scope < Scope
    def resolve
     scope.where(published: true).or(scope.where("story.user.id = ?", @user.id))
    end
  end
end

Supposedly we need to use JOINS I read, so I have also tried this:

scope.where(published: true).or(scope.joins(:story).where(stories: { user: @user }))

but I get error:

Relation passed to #or must be structurally compatible. Incompatible values: [:joins, :references]

Any ideas how I can write the query to do what I wanted?


Solution

  • I think I finally got it:

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

    Was hoping for a more non SQL statement way, but oh well, guess this will do unless someone know's the non-sql way.