0

Catalog model:

has_many :categories, dependent: :destroy
has_many :docs, through: :categories

Doc model:

belongs_to :category

My goal is to obtain a collection of all Doc objects that meet my query, but only those docs that are in a catalog that the user is authorized for via Pundit.

I currently have:

catalogs = Pundit.policy_scope(user, Catalog) #get only catalogs I'm authorized for
docs = []
catalogs.each do |catalog|
  catalog.docs.where(["title like ?", query]).each do |doc|
    docs.push doc
  end
end 

This returns the records I want, but seems inefficient to me, and I would prefer to have an ActiveRecord collection rather than an array. Is there a way to obtain these records more directly? I initially tried something like:

docs = Pundit.policy_scope(user, Catalog).docs

But that didn't work. Couldn't find a method named docs on the collection. Seems like normally you could use some kind of join for this, but I can't figure out how to make this work using Pundit to filter the catalog.

Using meagar's suggestions, I've come up with this:

category_ids = Pundit.policy_scope(user, Catalog).joins(:categories).flat_map(&:category_ids)
docs = Doc.where(category_id: category_ids).where(['title like ?', query])

Which works. Is this as efficient as I can go? Is there a more "Railsy" way to do this?

Community
  • 1
  • 1
croceldon
  • 4,511
  • 11
  • 57
  • 92
  • 1
    Knowing nothing else about Pundit, your loop could be written: `docs = catalog.docs.where(["title like ?", query]).flat_map(&:docs)`. That said, what you're after is a `join` or an `includes`, but I don't know if Pundit's `policy_scope` returns something like an ActiveRecord association on which you can `join` things. – user229044 Jan 11 '17 at 14:25
  • Regardless, you can still turn your list of catalogs into a list of category IDs and perform the lookup of all documents in a single query: `cat_ids = catalogs.where('title like ?', query).pluck(:id); documents = Document.where(catalog_id: cat_ids)`. – user229044 Jan 11 '17 at 14:27

0 Answers0