Rails style subset validation
21 Jun 2015Do you suddenly wake up in a cold sweat, wondering if there is finally a way to validate that your data is a proper subset that you desire? I too have experienced this horror, and that is why I made a rails style subset validator.
Validations über alles
Data validation is important. Having data you can depend on is the difference between a great application and one that might be classified as: “amateur hour”. Rails provides a nice amount of validators via ActiveModel::Validations
, but not an exhaustive set (get it?). One of those missing pieces involves validating sets of data. Just in case you haven’t had your coffee yet, we define a set as an abstract data type that stores distinct values in no particular order.
Ruby does indeed have the Set
class but most code I’ve come across simply uses the Array
class. So, for simplicity’s sake, all examples will use Array
.
Now that we have all been convinced that subset validation is the greatest thing since sliced bread, how about some examples?
Example usage
To include validates_subset
, simply add gem 'validates_subset'
in your Gemfile of your projects. Or type gem install validates_subset
in your terminal.
For rails applications, the gem is automagically available to you. For other ruby frameworks, just add the line: require 'validates_subset'
wherever you need the library. For this, we can assume that our application is using Rails 4.0 and we have a class that looks like:
class HasASubset < ActiveRecord::Base
attr_accessor :foo
validates_subset :foo, [1, 2, 3]
end
Using our handy dandy test class, we can see that:
A valid subset is valid:
test = HasASubset.new
test.foo = [1]
test.valid?
# => true
An empty set is also very valid:
test = HasASubset.new
test.foo = []
test.valid?
# => true
An invalid set is… invalid:
test = HasASubset.new
test.foo = ['banana']
test.valid?
# => false
And a non-set is invalid:
test = HasASubset.new
test.foo = 99_999
test.valid?
# => false
Holy guacamole that is some sweet validation. But wait, there’s more! Since this validator is built on top of rock solid ActiveModel::Validations
logic, all modifiers are supported.
Modification nation
If your particular dataset needs something to be a subset or nil
, it is a simple as:
class HasASubset < ActiveRecord::Base
attr_accessor :foo
validates_subset :foo, [1, 2, 3], allow_nil: true
end
If you needed the data to allow_nil
and only validate on create
, you could easily define the validation as:
class HasASubset < ActiveRecord::Base
attr_accessor :foo
validates_subset :foo, [1, 2, 3], allow_nil: true, on: :create
end
Any combination of modifiers is supported by validates_subset
. For a complete list of modifiers, have a look at the rails documentationn.
As always, please contribute to and use this software for the low low price of free.