在我的模型MediaFileAsset上,我通过一个包含的lib添加了以下内容:
default_scope ->{eager_load(:service_asset_core).where(service_asset_cores: {archived: false})}
不考虑不使用default_scopes的原因,有没有办法使用unscope从查询中删除此范围?
所以,例如,也许有人通过了我
assets = MediaFileAsset.where(custom_conditions)
我希望将所有这些忽略archived
service_asset_cores
字段。如果archived
是media_file_assets
的字段,我可以使用
assets.unscope(where: :archived).count
但这不起作用,因为archived
是ServiceAssetCore
上的字段,而不是MediaFileAsset
。
使用unscoped
和unscope(:where)
工作来删除存档条件,但这些条件不仅仅删除了这个条件,这不是我正在寻找的条件。我相信这就是首先添加unscope()
方法的原因,并且我试图了解是否可以使用它来删除已连接表格上的查询条件。
供参考:
2.2.2 > MediaFileAsset.unscoped.count
(505.8ms) SELECT COUNT(*) FROM `media_file_assets`
=> 3078951
为了解决具体的地方:: archived子句,我试过了:
2.2.2 > MediaFileAsset.unscope(where: {service_asset_cores: :archived}).count
(0.5ms) SELECT COUNT(DISTINCT `media_file_assets`.`id`) FROM `media_file_assets` LEFT OUTER JOIN `service_asset_cores` ON `service_asset_cores`.`service_asset_id` = `media_file_assets`.`id` AND `service_asset_cores`.`service_asset_type` = 'MediaFileAsset' WHERE `service_asset_cores`.`archived` = 0
=> 10
2.2.2 > MediaFileAsset.all.merge(ActsAsServiceAsset::ServiceAssetCore.unscoped).count
(0.5ms) SELECT COUNT(DISTINCT `media_file_assets`.`id`) FROM `media_file_assets` LEFT OUTER JOIN `service_asset_cores` ON `service_asset_cores`.`service_asset_id` = `media_file_assets`.`id` AND `service_asset_cores`.`service_asset_type` = 'MediaFileAsset' WHERE `service_asset_cores`.`archived` = 0
=> 10
2.2.2 > MediaFileAsset.unscope(where: :archived).count
(0.8ms) SELECT COUNT(DISTINCT `media_file_assets`.`id`) FROM `media_file_assets` LEFT OUTER JOIN `service_asset_cores` ON `service_asset_cores`.`service_asset_id` = `media_file_assets`.`id` AND `service_asset_cores`.`service_asset_type` = 'MediaFileAsset' WHERE `service_asset_cores`.`archived` =
Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1: SELECT COUNT(DISTINCT `media_file_assets`.`id`) FROM `media_file_assets` LEFT OUTER JOIN `service_asset_cores` ON `service_asset_cores`.`service_asset_id` = `media_file_assets`.`id` AND `service_asset_cores`.`service_asset_type` = 'MediaFileAsset' WHERE `service_asset_cores`.`archived` =
ActiveRecord::StatementInvalid: Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1: SELECT COUNT(DISTINCT `media_file_assets`.`id`) FROM `media_file_assets` LEFT OUTER JOIN `service_asset_cores` ON `service_asset_cores`.`service_asset_id` = `media_file_assets`.`id` AND `service_asset_cores`.`service_asset_type` = 'MediaFileAsset' WHERE `service_asset_cores`.`archived` =
2.2.2 > MediaFileAsset.all.merge(ActsAsServiceAsset::ServiceAssetCore.unscope(where: :archived)).count
# output omitted, same error as pervious
最后两个似乎是一个Rails(4.2.3)错误,因为生成的SQL无效。也许这就是我需要的地方,但这个错误在我的方式。还有其他方法我应该尝试,还是我坚持不可避免的default_scope的恐怖?
答案 0 :(得分:1)
从Rails 6.1开始,可以仅取消限制指定表中的列。
posts = Post.joins(:comments).group(:"posts.hidden")
posts = posts.where("posts.hidden": false, "comments.hidden": false)
posts.count
# => { false => 10 }
# unscope both hidden columns
posts.unscope(where: :hidden).count
# => { false => 11, true => 1 }
# unscope only comments.hidden column
posts.unscope(where: :"comments.hidden").count
# => { false => 11 }
这里是a link to the corresponding PR。
所以,我想,以下可以解决您的问题:
MediaFileAsset.unscope(where: :"service_asset_cores.archived").where(custom_conditions)
答案 1 :(得分:0)
你非常接近。
MediaFileAsset.unscoped返回ActiveRecord::Relation,这意味着您可以在其上调用.count, .where, .includes,
等。
所以完整的查询将是:
MediaFileAsset.unscoped.where(service_assset_cores: :archived).count
或者,您可以在MediaFileAsset
上定义一个名为archived的命名范围,并在取消它后对其进行重新扫描:
class MediaFileAsset < ActiveRecord::Base
scope :archived, { where service_asset_cores: :archived }
# ...
end
MediaFileAsset.unscoped.archived.count
def self.without_default_scope
klass = self.dup
klass.default_scopes = []
klass
end