Skip to content

Instantly share code, notes, and snippets.

@lwe
Created June 13, 2012 10:37
Show Gist options
  • Save lwe/2923336 to your computer and use it in GitHub Desktop.
Save lwe/2923336 to your computer and use it in GitHub Desktop.
Module which provides the ability to unscope associations
# Provides the ability to unscope associations, this solves problems described in
# http://stackoverflow.com/questions/1540645/how-to-disable-default-scope-for-a-belongs-to/11012633#11012633
#
# Examples
#
# class Document < ActiveRecord::Base
# default_scope where(deleted: false)
# end
#
# class Comment < ActiveRecord::Base
# extend Unscoped
#
# belongs_to :document
# unscope :document
# end
#
module Unscoped
# Public: Ensure a previously defined association is not scoped by a default_scope.
#
# associations - The Symbol with the name(s) of the associations to unscope.
#
# Examples
#
# # Unscope a single assoication
# unscope :document
#
# # Unscope multiple in one way.
# unscope :document, :comments
#
# Raises ArgumentError if the named association does not exist on the model, so ensure
# the association is defined _before_ calling `unscope`.
#
# Returns nothing.
def unscope(*associations)
associations.flatten.each do |association|
raise ArgumentError, "no association named #{association} exists on this model" unless self.reflect_on_association(*association)
class_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{association}
self.class.reflect_on_association(#{association.inspect}).klass.unscoped { super }
end
RUBY
end
end
end
@ziaulrehman40
Copy link

ziaulrehman40 commented Jan 17, 2022

Still works with rails 6.1
A-mazing!

PS: Not sure if it will break anything else :D

@lwe
Copy link
Author

lwe commented Jan 17, 2022

Haha, wow, this is indeed amazing. Power of Rails. 👍

PS: I just tried to remember where I've required this, as this bit was written ages ago.

@Ezveus
Copy link

Ezveus commented May 5, 2025

Still relevant and useful in Rails 7.2 (and probably 8 too).
I made it a concern:

# Provides the ability to unscope associations, this solves problems described in
# http://stackoverflow.com/questions/1540645/how-to-disable-default-scope-for-a-belongs-to/11012633#11012633
#
# Examples
#
#    class Document < ActiveRecord::Base
#      default_scope where(deleted: false)
#    end
#
#    class Comment < ActiveRecord::Base
#      include Unscoped
#
#      belongs_to :document
#      unscope :document
#    end
#
module Unscoped

  extend ActiveSupport::Concern

  class_methods do
    # Public: Ensure a previously defined association is not scoped by a default_scope.
    #
    # associations - The Symbol with the name(s) of the associations to unscope.
    #
    # Examples
    #
    #    # Unscope a single assoication
    #    unscope :document
    #
    #    # Unscope multiple in one way.
    #    unscope :document, :comments
    #
    # Raises ArgumentError if the named association does not exist on the model, so ensure
    # the association is defined _before_ calling `unscope`.
    #
    # Returns nothing.
    def unscope(*associations)
      associations.flatten.each do |association|
        unless reflect_on_association(*association)
          raise ArgumentError,
                "no association named #{association} exists on this model"
        end

        class_eval <<-RUBY, __FILE__, __LINE__ + 1
          # def document
          #   self.class.reflect_on_association(:document).klass.unscoped { super }
          # end

          def #{association}
            self.class.reflect_on_association(#{association.inspect}).klass.unscoped { super }
          end
        RUBY
      end
    end
  end

end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment