· ruby

Ruby: Active Record - Using 'exclusive_scope' in IRB

Ashwin and I have been working recently on a bit of code to make it possible to ‘soft delete’ some objects in our system.

We’re doing this by creating an additional column in that table called ‘deleted_at_date’ which we populate if a record is ‘deleted’.

As we wanted the rest of the application to ignore ‘deleted’ records we added a default scope to it:

class Foo < ActiveRecord::Base
   default_scope :conditions => "deleted_at_date is null"   

This works fine but we wanted to be able to see the status of all the records in IRB and with the default scope ‘Foo.all’ no longer returns ‘soft deleted’ records.

Luckily Active Record provides a protected method called ‘with_exclusive_scope’ which we can use to get around this:

Foo.send(:with_exclusive_scope) { Foo.find(:all) }

Since it’s a protected method we can only access it in IRB by using ‘send’ which is a bit hacky, something David Heinemeier Hansson would refer to as syntactic vinegar.

Interestingly our first attempt to use ‘with_exclusive_scope’ involved writing the above code like this…

Foo.send(:with_exclusive_scope) { find(:all) }

..which results in the following error because when the closure was created ‘self’ referred to the main object rather than to ‘Foo’:

NoMethodError: undefined method `find' for #<Object:0xb77cd94c>
    from (irb):62
    from /var/lib/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2143:in `with_scope'
    from /var/lib/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2151:in `with_exclusive_scope'
    from (irb):62:in `send'
    from (irb):62
    from :0

Since the main object has no method called ‘find’ we get an exception thrown.

  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket