bellmyer / validates_blacklist

Easily create and manage blacklists that become part of a model's validation.

This URL has Read+Write access

bellmyer (author)
Sat Aug 29 13:43:04 -0700 2009
commit  76739862cbefe98b18cfbb07375dc29d3884218a
tree    87890026eb32344300b81368254b57cc70e62db9
parent  ede1cd031adfa2fad4a040cb61b9b056596b0dff
README
validates_blacklist
===================

The ridiculously paranoid don't want anything getting past them.  Wouldn't you
feel the same if everyone was out to get you?  How do you know they're not?

When it comes to validations, paranoia is pricey.  You need a tool to simplify
the process. Time is of the essence, and those aluminum foil hats aren't going to
fashion themselves.

In all seriousness, validations are great for general rules that describe what type
of data is or isn't acceptable.  What they're not good for is muddying up your
model with lists, possibly large lists, of specifically blacklisted data.

You may not want chunkeymonkey47@aol.com joining your online forum because you know
they're just going to spam your users with viagra ads.  Maybe there are dozens of
chunkymonkeys out there, as it were, and that sort of config data is just
hideous in your model, if you care anything about beautiful code.  I say one
chunkymonkey is too much.


What can be done?
=================

What if we create a list *outside* the model, that can be validated against? What 
if we gave each model its own blacklist file in the config folder so you knew 
exactly where to find them?  Maybe a yaml file would make it easy to blacklist at
the attribute level. And what if I wrote a nify little mixin for you, so calling
"validates_blacklist" inside a model would automatically read this list and handle
the validation for you?

Well, I'd be a swell guy.  And as it turns out, I kind of am.


Installation
============

Stick this little line in your environment.rb:

  config.gem 'bellmyer-validates_blacklist', :lib => 'validates_blacklist', :source => 'http://gems.github.com'

Then, for fun, run these two rake tasks:

  rake gems:install
  rake gems:unpack
  

Usage
=====

Run this command to create blacklist files for all your models in the config/blacklists/ folder:

  script/generate blacklists
  
Don't worry, it won't overwrite your existing blacklist files, only create the ones
you're missing. This means you can run it after every new model is added, no worries.

Now, call this in your models:

  validates_blacklist
  
And populate the yaml files using the example below to guide you. Have fun!


Example
=======

As an example, we'll imagine a high school girl named Heather. Although she has
mad Ruby skillz (perhaps BECAUSE) she's a snob.  All her potential friends must 
submit applications for friendship via her Rails website. She uses 
validates_blacklist to weed out the "undesireables".

# config/blacklists/user_blacklist.yml
    email:
     - greasy_pete@yahoo.com # We kissed once when we were 5. Get over it already.
     - /@aol.com$/           # Like, yeah right, AOL is for losers!

    age:
     - <14    # Junior high?  Need not apply.
     - >25    # Gross, you perv!

    parents_salary:
     - 50_000..150_000    # Poor kids are gullible. Rich kids have money. Middle class is so passe.

# app/models/user.rb
    class User < ActiveRecord::Base
      validates_blacklist
    end


Explanation
===========

Basically, under each attribute (email, age, parents_salary, etc) you can list 
as many blacklisted values as you like. They can be a simple strings:

    greasy_pete@aol.com
    
or regular expressions, if you wrap them in forward slashes:

    /aol.com$/
    
or numbers (not very exciting):

    5

or ranges of numbers:

    5..15
    
or any other conditionals you can think of:

    != 'sadness'
    =~ /happiness/
    !~ /sad/
    > 12
    < 99
    
The only limits are your imagination, and my forethought.  You can even specify
the error message that is generated:

  email:
   - [stinky_pete@aol.com, cannot be greasy pete from biology]
  
  age:
   - [>25, cannot be a pervert]
   
  parents_salary
   - [50_000..150_000, cannot be middle class]
  
Otherwise, the user will receive a generic message like:

  Email is not allowed
  
Of course, you can change that for an entire model with the mixin call:

  validates_blacklist :message => 'is not valid'
  
or per attribute:

  validates_blacklist :message => "is not valid',
    :attributes => { :email => 'has been banned', :age => 'is not allowed' }

For the record, I think even a 21 year old hitting on high school girls is a
pervert, but I'm trying to approach this thing from Heather's point of view.


Copyright (c) 2009 Jaime Bellmyer, released under the MIT license