views:

67

answers:

2

We have a web app which serves typical social content(blogs/forums/streams etc).

All the content is optionally marked with a city. I.e. if a blog post is specific to New York, it will be marked so.

The task is to show only city specific information(all over the site) if user has set city view preference and show everything to all others.

So I have to add 'and city == current_city' if city_specifc_view? to all my finders in all my model classes, which is a maintenance night mare(especially as there is a risk of this logic changing).

I am wondering what is the right way to apply this logic. Can I do it a central place(like overrinding the default find), instead of if/else all over the models. Is monkey patching ActiveRecord an option?

Thanks

+2  A: 

In ActiveRecord::Base there is a feature called scopes. A query being issued in a certain scope will be combined with this scope's find-options ie.:

  class Person < ActiveRecord::Base
    default_scope :order => 'last_name, first_name'
  end

Maybe this is a feature you want to look into?

flitzwald
+1  A: 

Don't know if modifying AR.find is the best choice for you but it worked for me:

class Content < AR::base
  def self.find(*args)
    if logged_user.preferred_city
      choose_city(super(*args))
    else
      super(*args)
    end
  end
protected #to be inherited by content subtypes (post, pic, stream...)
  def self.choose_city(target) 
    case target
      when Array target.select{|t| choose_city(t)}
      when Person (target.city == logged_user.preferred_city ? target : nil)
      else target
    end
  end
end

Hope this may help you

Fer
Thanks Fer. You solution is nice. I was thinking if I can avoid bringing the filtered data from DB at all by adding a query to the filter. I managed it for finders by patching AR with a with_scope. But yet to tackle queries generated for associations.
I avoid associations related queries with includes BUT there is a pitfall, if your DB is local, more small (indexed) queries might be better than one big (in come cases with joins), if it is remote, the less network connections to your db the better. Hope that helps you, but as always: Benchmark your solutions before you choose!
Fer