A Clean, Well-Lighted Place

Scoping Resources in ActiveAdmin

Here’s the use case I had yesterday.

We’re using ActiveAdmin in our current Rails 3 project. It’s really cool and gives you an easy way to jump start your admin section. Of course the more you want to customize, the more code you have to write. In our case we wanted to soft delete resource (lets say - a blog post). Actual marking of post as deleted is the easy part. You just need to customize the form:

# app/admin/blog_posts.rb
form do |f|
...
  f.input :is_deleted, :label => 'Mark as deleted'
...
end

Then you have to hide those posts, right? The easiest way was to use a default scope.

# app/models/blog_post.rb
class BlogPost < ActiveRecord::Base
  default_scope where(:is_deleted => :false)
end

Cool! But now all those “deleted” posts are hidden for admins too. Not cool…

I couldn’t find anything about that in the docs, so I took a look at the source code. First good candidate was scoped_collection, but it’s comments explicitly say

“Note, unless you are doing something special, you should use the scope_to method from the Scoping module instead of overriding this method.”

Here’s what I’ve found about that mysterious config option named scope_to.

This was my first attempt:

ActiveAdmin.register BlogPost do
...
  scope_to Proc.new { BlogPost.unscoped }
...
end

That was throwing an error saying

undefined method `blog_posts’ for #<ActiveRecord::Relation:0xb511be48>

Obviously whatever scope_to returns have to respond to :blog_posts (plural form for your resource). Next I’ve tried

ActiveAdmin.register BlogPost do
...
  scope_to do
    Class.new do
      def self.blog_posts
        BlogPost.unscoped
      end
    end
  end
...
end

Yay! It worked.

Actually there’s other way too - you can add your own Admin:BlogPostsController, define your method there and pass it’s name as symbol to scope_to. For now I prefer to keep all ActiveAdmin related stuff at one file per resource.

Is there better way to do that? Please drop a comment if you know one.

Comments