ibl*_*lue 7 ruby activerecord default-scope sequel
在ActiveRecord中,有一个default_scope
类方法来指定默认范围.例如
class User < ActiveRecord::Base
default_scope where(:deleted => false)
end
User.all # => SELECT * FROM users WHERE deleted = 0;
Run Code Online (Sandbox Code Playgroud)
我怎么能这样做Sequel::Model
?
编辑:
经过一些谷歌搜索后,我终于找到了一些有用的信息.
class User < Sequel::Model
# Define some "scopes" (filters on the dataset)
dataset_module do
def existing
filter(deleted: false)
end
def active
filter(disabled: false)
end
end
# This is the equivalent to a default_scope. Set one of the datasets
# as the default dataset for this model.
set_dataset(self.active)
end
Run Code Online (Sandbox Code Playgroud)
生成的查询如下所示:
User.all # => SELECT * FROM `users` WHERE (`deleted` IS FALSE)
Run Code Online (Sandbox Code Playgroud)
顺便说一句:相当于unscoped
是unfiltered
:
User.unfiltered.all # => SELECT * FROM `users`
Run Code Online (Sandbox Code Playgroud)
但是,有一个问题.如果您尝试更新未经过滤的数据集中的用户,则会尝试使用给定的数据集更新用户.
User.create(disabled: true, deleted: true)
User.all # => []
u = User.unfiltered.first # => Given user
u.disabled = false
u.save # => UPDATE users SET ... WHERE (disabled IS FALSE AND id = 1)
# => Sequel::NoExistingObject: Attempt to update object did not result in a single row modification
Run Code Online (Sandbox Code Playgroud)
所以我回到了开头.有什么解决方法吗?
最好的解决方法是通过没有默认范围来避免问题.在大多数情况下,默认范围是一个坏主意.如果您希望大多数查询使用范围,则在这些查询中手动应用范围,不要使用默认范围并尝试在其他查询中退出范围.只有所有查询都使用该范围时,默认范围才有意义.
您也可以通过子类化来处理这个问题(用户不是作用域,ActiveUser <用户是作用域的).但是,我发现明确的范围界定方法更好.
总而言之,如果您真的想要使用默认范围,以下内容可能会解决在模型默认范围之外更新模型实例的问题:
User.instance_dataset.unfiltered!
Run Code Online (Sandbox Code Playgroud)