== Simple Filtering Example This will implement the acts_as_filterable mixin for an ActiveRecord class. It'll...uhh...you know. Filter stuff. Let's see an example: class Badger < ActiveRecord::Base has_many :beers end frank = Badger.create(:name => 'Frank') james = Badger.create(:name => 'James') drinky = Badger.create(:name => 'Drinky') This is great. We have a couple badgers, everything is going pretty smooth. Frank, James, Drinky have fun adventures damn-near constantly. Though, as we could have guessed, Drinky has a bit of a drinking problem. We'd really rather just not even know he exists if he's had too much. Really, we'd rather not know about any badgers who have been drinking. class Badger < ActiveRecord::Base has_many :beers acts_as_filterable def too_much_to_drink? beers.size > 3 end invisible_if :too_much_to_drink? end Cool. So, at the moment, we're kicking: Badger.find(:all).each do |badger| puts "#{badger.name} drank #{badger.beers.size} Beers!" end > Frank drank 0 Beers! > James drank 0 Beers! > Drinky drank 0 Beers! Now! On to the drinking! frank.beers << [Beer.create, Beer.create, Beer.create] james.beers << [Beer.create, Beer.create] drinky.beers << [Beer.create, Beer.create, Beer.create, Beer.create] Christallmighty. Looks like Drinky's had too much to drink again. Let's run the roll call, to see if anyone's going to tell us semi-truthful stories with copious volume and slurring. Badger.find(:all).each do |badger| puts "#{badger.name} drank #{badger.beers.size} Beers!" end > Frank drank 3 Beers! > James drank 2 Beers! == Instantiating Invisible Items Effing sweet. Drinky's just gone. His antics got a little old. But let's say Frank wants to go find Drinky...he has a awesome story to tell him. Badger.find_by_name('Drinky') > nil Badger.find(3) # Drinky's id > ActiveRecord::RecordNotFound exception and so-forth! No. Drinky's gone until he sobers up. End of story. == Making Exceptions Well, let's say that Frank can handle his own a bit better than Drinky can. He just gets friendly, and tells good stories. Nothing ends up broken, and he leaves no stains on anyone's carpets. We'll let Frank drink as much as he wants. class Badger < ActiveRecord::Base has_many :beers acts_as_filterable def too_much_to_drink? beers.size > 3 end def is_frank? name == "Frank" end invisible_if :too_much_to_drink? visible_if :is_frank? end The results are as expected. The rules are executed in sequential order. If we had a deleted flag or something -- and we didn't want to waste our time screwing around with access rules if it evaluated, we could just pass a flag as follows: invisible_if :deleted?, :always => true and execution of the rules would halt if that rule was evaluated to true. == The Big Exception Let's say Animal Control rolls into town, and they want a head count on badgers -- drunk or not. We need to make some kinda back-door to get accurate info on all our model objects. Check it out: ActiveRecord::Base.security_ignore do Badger.find(:all).each do |badger| puts badger.name end end > Frank > James > Drinky Ah, the good times.