Refresh attitude in the field?

How can I get something like ActiveRecord scope

that changes the relationship it acts on?

Specifically, I want to be able to do this:

Model.some_scope.fake_destroy_all

      

Where fake_destroy_all

is the functionality I'm trying to create. It will be pretty much equivalent .update_all(deleted: true)

.

A weak alternative might be:

def fake_destroy_all(relation = Model)
    relation.update_all(deleted: true)
end

#...

Model.fake_destroy_all(Model.some_scope)

      

But this is not ideal. What I would like to do is something like:

scope :fake_destroy_all, update_all(deleted: true)

      

But it doesn't work.

Is it possible to do something like what I am describing?

+3


source to share


1 answer


Try the following:

def self.fake_destroy_all
  self.update_all(deleted: true)
end

      

It turns out that the relationship is preserved by all methods of the class. Scopes are also methods of a class, and they are the exact mechanism that allows scopes to be bound to targets.

Hence a relationship with this model will also have this method with self

being an instance of the relationship.

The scope syntax could probably be captured like this (can't test right now, but note the lambda instead of just a method call):



scope :fake_destroy_all, -> { update_all(deleted: true) }

      

I suppose without updating inside the lambda, it effectively calls this method when called scope

, in the class definition. It works with simple where

-type scopes because it has no side effect , it only returns a matching filter. It is evaluated once and stored as is in the method for future use. where

When using a lambda, execution continues until the scope is applied, until it is defined. This is necessary because it update_all

has a side effect .

The same trick is useful if you are specifying an area with an ever-changing condition, with the simplest case depending on Time.now

, which changes over time and needs to be re-evaluated each time.

However, I suggest you use a class method: the scope is more like a filter, whereas it is more like "enforcing a filter". While this might work as well, scopes are applied semantically for different use cases.

+3


source







All Articles