0

I am trying to unscope multiple model as below User Model which has acts_as_paranoid

class User
  acts_as_paranoid
  has_one :category
  has_one :brand
  has_one :item         

  INDEXED_FIELDS = {
    only: [:name],
    include: {
      category: { only: [:name] },
      item: { only:[:name] },
      brand: { only: [:name]},
    }
  }

  def custom_json
    Category.unscoped do
      Item.unscoped do
        Brand.unscoped do
          self.as_json(INDEXED_FIELDS)
        end
      end
    end
  end
end

User model has following association which also has acts_as_paranoid

Sample Category model, Brand and Item model have same code

class Category
  acts_as_paranoid
  belongs_to :user
end

Can I do this dynamically with 'N' number of models, like iterating over array as below

def custom_json
  [Category, Item, Brand].each do 
    # do unscoping 
  end
end 

Association looks like

Pramod Shinde
  • 1,802
  • 1
  • 15
  • 28

2 Answers2

1

I think the approach you may have is to unscope the class manually, by setting default_scopes to [], and then putting it back.

classes_to_unscope = [Category, Item, Brand]
# remove default_scopes, saving them in previous_scopes
previous_scopes = classes_to_unscope.map do |klazz| 
  scopes = klazz.default_scopes
  klazz.default_scopes = []
  scopes
end 
self.as_json(INDEXED_FIELDS)
# put default_scopes back
classes_to_unscope.each_with_index do |klazz, i|
  klazz.default_scopes = previous_scopes[i]
end 
Xavier Delamotte
  • 3,519
  • 19
  • 30
0

As extra method:

def unscope_all(*models, &block)
    # the order does not matter, but preserve it
    blocks = [block] + models.reverse.map do |model|
      proc do |inner_block|
        model.unscoped { inner_block.call }
      end
    end

    blocks.inject do |inner, outer|
      proc { outer.call(inner) }
    end.call
  end

Then you would use it:

unscope_all(Category, Item, Brand) do 
    # do unscoping 
  end

unscoped pitfall: when leaving the block you loose the "unscopability", so make sure you don't return a relation (it won't be unscoped). Instead you have to resolve it in the block (e.g. by returning an array where(...).to_a.

estani
  • 24,254
  • 2
  • 93
  • 76