【问题标题】:How to unscope multiple models in rails?如何在rails中取消多个模型的范围?
【发布时间】:2017-10-27 09:44:20
【问题描述】:

我正在尝试取消多个模型的范围,如下所示 具有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

用户模型有以下关联,也有acts_as_paranoid

Sample Category model, Brand 和 Item model 有相同的代码

class Category
  acts_as_paranoid
  belongs_to :user
end

我可以用“N”个模型动态地做到这一点吗,比如遍历数组,如下所示

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

联想看起来像

【问题讨论】:

  • 你想通过取消范围来做什么??
  • @NarasimhaReddy 我想从多个模型中排除默认范围条件
  • 没关系。但是一次取消多个模型的范围是什么情况。我们可以边做边做吗?
  • 请提供CategoryItemBrand模型文件。所以我们可以看到它们之间的关系
  • 当我们调用self.as_json(INDEXED_FIELDS)时,它会查询关联来构建json,我想要unscope关联并构建json。

标签: ruby-on-rails ruby activerecord acts-as-paranoid


【解决方案1】:

我认为您可能采用的方法是手动取消类的范围,将default_scopes 设置为[],然后将其放回原处。

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 

【讨论】:

  • 什么是klazz.default_scoping,它给出的错误是未定义的方法?
  • 对不起,错字,是default_scopes
【解决方案2】:

作为额外的方法:

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

然后你会使用它:

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

无范围陷阱:离开块时,您会失去“不可范围性”,因此请确保您不返回关系(它不会是无范围的)。相反,您必须在块中解决它(例如,通过返回数组 where(...).to_a

【讨论】:

    猜你喜欢
    • 2018-03-23
    • 2015-01-20
    • 2017-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-22
    • 1970-01-01
    • 2011-10-23
    相关资源
    最近更新 更多