我有一个易受关注的问题,允许用户丢弃("删除")某些事情。
问题在于,即使该项目可以被删除,如果您查看较旧的内容,仍然需要引用该项目。如果您现在这样做,它就不会找到该对象,因为我已将default_scope
更改为仅显示已删除错误的位置。
这是我的可销售模块:
module Trashable
extend ActiveSupport::Concern
included do
default_scope { where(trashed: false) }
scope :trashed, -> { unscoped.where(trashed: true) }
validates :trashed, inclusion: { in: [true, false] }
end
def trash
update_attribute :trashed, true
end
end
现在我有一个Order
模型,您可以在其中查看订单。如果我们例如垃圾产品,我仍然希望用户能够查看他们的订单并查看产品。
现在我无法使用模型关联来访问它,例如:
has_many :products
并使其包含trashed为false和true的位置。
有人知道如何实现这个目标吗?
答案 0 :(得分:1)
你可以通过几种方式实现这一目标,这就是我所知道的
解决方案1 像这样定义with_trashed
:
module Trashable
extend ActiveSupport::Concern
included do
default_scope { where(trashed: false) }
scope :trashed, -> { unscoped.where(trashed: true) }
# Define a new scope here
scope :with_trashed, -> { unscope(where: :trashed) }
validates :trashed, inclusion: { in: [true, false] }
end
def trash
update_attribute :trashed, true
end
end
然后你就可以使用它:
order.products.with_trashed
解决方案2 定义未范围的类
class UnscopedProduct < Product
self.default_scopes = []
belongs_to :order
end
class Order < ActiveRecord::Base
has_many :products
has_many :unscoped_products, foreign_key: :order_id, class_name: "UnscopedProduct"
end
然后你就可以使用它:
order.unscope_products
根据我的经验,我会使用解决方案1,但有一些奇怪的情况,这不再适用,例如,在复杂的查询中,所以请记住解决方案2,它将节省大量时间!
使用Default scope
会导致以后复杂查询出现这么多问题。这取决于你!
答案 1 :(得分:0)
你可以做几件事:
正如评论中提到的那样,您应该使用Acts as Paranoid Gem,这正是出于此目的。使用它,您可以使用方法with_deleted
或only_deleted
,它们也会返回相关的已删除对象。
您不能像上面那样简单地使用unscoped
。 Unscoped将删除所有条件,而不仅仅是trashed: false
。您还可以尝试创建另一个范围,该范围返回已删除的对象,并将第二个范围中找到的对象与第一个范围合并。
scope_1_results + scope_2_results
如果您使用的是Rails 5,则还可以OR
在Rails 4.x或更低版本中无法实现的范围。