jeudi 21 janvier 2016

Is my "override default_scope" solution for rails 3.2(!) ok? or if not why not?

Pre 0: I post 2 questions with almost the same intro here, but the requested/expected answers are very different

Pre: my question belongs to Rails 3.2 & plz. I don't want to discuss using default_scope at all; I know, that there are a lot of arguments not to use it (in wrong way)

I have the 'classical' soft delete records problem that is - as I think - almost perfectly solved with a default_scope, in my case the soft delete is for undo reasons. But I do not want to use unscope or plain sql if I need to access a deleted record

Since my first attempt (link-after question schedule), to search the scopes already used, did not work, I found this solution that seems to work nice, but it is so easy, that I am not sure; I don't feel like a Rails "hacker"

Based on the sources and a hand full of debugging, I learned that the default_scope is resolved after all others, so the idea was just to make a dynamic default_scope based on this:

    # If you need to do more complex things with a default scope, you can alternatively
    # define it as a class method:
    #
    #   class Article < ActiveRecord::Base
    #     def self.default_scope
    #       # Should return a scope, you can call 'super' here etc.
    #     end
    #   end

in default.rb, I felt brave and tried following:

I have only a group of "soft delete candidates" in my models, and I want to handle them all the same way, i introduced a SoftDelRecord - module, that I include SoftDelRecord in all models, that are part.

The idea: "turn off default scope if a 'use all' scope was used before", so that i can use:

Toast.where(brownstate: 'fine')  # default scope ON

or

Toast.include_deleted.where(brownstate: 'fine') # default scope OFF

and all other scoped variants I tried

module SoftDelRecord

    def self.included base
        base.extend ClassMethods
    end

    module ClassMethods

        def default_scope
            if clr_default_scope
                set_clr_default_scope(false)
                where('')
            else
                where('active = true')
            end
        end


        def include_deleted
            set_clr_default_scope('true')
            where('')
        end

        def clr_default_scope
            Thread.current["#{self}_sdr_include_deleted"]
        end

        def set_clr_default_scope(tf)
            Thread.current["#{self}_sdr_include_deleted"]=tf
        end


    end
end

It's some how to easy, to believe, but all I tried works, or seems to work.

what have I overseen?

Aucun commentaire:

Enregistrer un commentaire