9

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

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

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

でこれを行うにはどうすればよい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

生成されたクエリは次のようになります。

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

ちなみに: に相当するのunscopedunfiltered:

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

だから私は最初に戻っています。これに対する回避策はありますか?

4

1 に答える 1

9

最善の回避策は、デフォルトのスコープを持たないようにして問題を回避することです。ほとんどの場合、デフォルトのスコープはお勧めできません。ほとんどのクエリでスコープを使用する場合は、それらのクエリでスコープを手動で適用し、既定のスコープを使用せず、他のクエリでスコープをバックアウトしてみてください。デフォルトのスコープは、すべてのクエリがそのスコープを使用する場合にのみ意味があります。

サブクラス化によってこれを処理することもできます (ユーザーはスコープされず、ActiveUser < ユーザーはスコープされます)。ただし、明示的なスコープ アプローチの方がうまく機能することがわかりました。

そうは言っても、本当にデフォルトのスコープを使用したい場合は、モデルのデフォルトのスコープ外でモデル インスタンスを更新する問題を次のように回避できます。

User.instance_dataset.unfiltered!
于 2012-07-26T20:48:02.250 に答える