An update on Judge
I’ve just released Judge 1.5.0 and since it’s been a while since the last update, I thought I’d run through some of the improvements that have been made since version 1.0.0 and also introduce some ideas for future improvements.
gem "judge", "~> 1.5.0"
Callbacks
The various validate()
methods now accept callback functions. Yep, real modern. The cool thing about this is that we can handle what happens after validation a little more elegantly. Behold!
watcher.validate([callback])
var watcher = new judge.Watcher(document.getElementById('foo'));
watcher.validate(function(valid, messages, element) {
element.style.background = valid ? 'green' : 'red';
});
judge.validate(elements, [callback])
// callback is executed once for each input
judge.validate(document.getElementsByTagName('input'), function(valid, messages, element) {
element.style.background = valid ? 'green' : 'red';
});
judge.store.validate(key, [callback])
judge.store.save('foo', document.getElementById('foo'));
// callback is executed once for each element stored
// against key 'foo' (in this case just once)
judge.store.validate('foo', function(valid, messages, element) {
element.style.background = valid ? 'green' : 'red';
});
I18n
Internationalized error messages are sweet. Remember when Rails didn’t do this? Oh man. Bad times. They’re still a bit confusing though. There are a lot of bad custom validator examples sitting around on the web, just waiting to be copied and pasted into some poor, unsuspecting app. Don’t do this:
class FooValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
if value != "foo"
record.errors[attribute] << "ain't foo"
end
end
end
That rogue error message is doing nobody any favours. The errors object has an add
method which will handle i18n translation lookup for you:
class FooValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
if value != "foo"
record.errors.add(attribute, :not_foo)
end
end
end
You can read about how the error message is looked up over on rubyonrails.org.
Since Judge is all about porting stuff from server- to client-side for great DRY justice, you can now use declare_messages
in your custom EachValidator
to specify which messages will be made available to your validation methods on the client-side:
class FooValidator < ActiveModel::EachValidator
declare_messages :not_foo
def validate_each(record, attribute, value)
if value != "foo"
record.errors.add(attribute, :not_foo)
end
end
end
This means that we can access our translated message like this:
judge.customValidators.foo = function(valid, messages, element) {
console.log(messages.not_foo);
};
Documentation
The Judge docs have been spruced up a little too. Please do let me know if anything is unclear.
The future
I have a few things that I’m planning on adding to Judge in the very near future.
Uniqueness validation
This isn’t currently possible with Judge but given the updates to Engines in Rails >= 3.1, I’m excited about tackling this issue in a clean, unobtrusive way. Watch this space.
Backbone.Model validation
Backbone.js models have a validate method which, with a little extra work, I think could work really nicely with Judge. I’m not settled on how to implement this but I have some vague ideas. Suggestions welcome as always.