2012-07-26 15 views
6

ActiveRecordには、デフォルトスコープを指定するためのdefault_scopeクラスメソッドがあります。たとえば、Sequelのdefault_scope

class User < ActiveRecord::Base 
    default_scope where(:deleted => false) 
end 

User.all # => SELECT * FROM users WHERE deleted = 0; 

Sequel::Modelでこれを行うにはどうすればよいですか?

EDIT:

は、いくつかのグーグルの後、私は最終的にいくつかの有用な情報を見つけました。

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 

生成されたクエリは、次のようになります方法では

User.all # => SELECT * FROM `users` WHERE (`deleted` IS FALSE) 

unscopedと同等のunfiltered次のとおりです。

User.unfiltered.all # => SELECT * FROM `users` 

しかし、一つの問題があります。フィルタリングされていないデータセットから取得したユーザを更新しようとすると、指定されたデータセットを使用してユーザを更新しようとします。

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 

私は最初に戻っています。この問題を回避するには?

答えて

5

最高の回避策は、デフォルトスコープを持たないことで問題を回避することです。ほとんどの場合、デフォルトスコープは悪い考えです。ほとんどのクエリでスコープを使用する場合は、これらのクエリで手動でスコープを適用し、デフォルトのスコープを使用せず、他のクエリでスコープを取り消そうとします。クエリのすべてがそのスコープを使用する場合、デフォルトのスコープが意味を持ちます。

サブクラス化することでこれを処理することもできます(ユーザーはスコープではなく、ActiveUser <ユーザーはスコープあり)。しかし、明示的なスコープ設定の方が効果的です。

すべてのことは、あなたが本当にデフォルトのスコープを使用したい場合は、以下のモデルのデフォルトの範囲外のモデルインスタンスを更新する問題を回避することが、言われている:

User.instance_dataset.unfiltered! 
関連する問題