
On a recent project, we decided it would be nice to have “templated attributes” for certain fields in a form. A templated attribute has a helpful initial value—kind of like a default value—except that these aren’t valid data or saved in the database. They’re suggestions to the user about the expected formatting or content of a field.
So the game is:
- keep these values out of the database
- specify these values once in the model, super-duper-DRY
- create a user experience that clearly implies that these values are just templates for valid data
Case one: a website attribute
We wanted a website attribute to be prefilled with http:// as a suggestion to the user about proper URL formatting—most users will just enter “example.com” when prompted for a URL. This is to avoid XSS problems with javascript: URIs and the like, and to keep browsers from resolving short URLs to be internal—nothing quite like being sent to http://yoursite.com/www.theirsite.com.
(Aside: there are better ways to handle this specific situation: a :before_validation callback to fix invalid URLs and check for XSS attacks, or the fantastic white_list plugin. But for now I’m interested in the general case.)
This attribute needed certain behavior:
- When the user hits the form, the field should be pre-filled with
http://if the real value is empty or nil. - If the field is left as
http://, we should convert it to nil before validation. - Client-side: to imply that the initial value is a suggestion, we’ll make the text color gray until the user makes a change. If the user’s only change is to empty the field, we should reset it to
http://and gray again on blur.
Case two: label attributes
There’s another use case, which you’ve seen before: a text field’s initial value is used as a replacement for its label. When the user clicks in the field, the “label” disappears. My example of this is a phone attribute, where we’d like to suggest a standard US area code format. Something like (123) 555-1234.
We don’t want the user to have to delete our dummy numbers and put in their own; it’s too much work. Instead we think that the reminder will help coax the right format out of the user by itself—so this field gets blanked on focus, unlike the website attribute.
You also see this pattern used for content suggestions instead of formatting hints: for example, search fields and login forms which are space-constrained, like the built-in search in Firefox and Safari.
Get on with the plugin, already
OK, OK. So we have two kinds of templated attributes: those with starting values, which are potentially the start of valid data, and labels, which are just helpful, ephemeral reminders.
Check out the goods:
1 2 3 4 |
class User < ActiveRecord::Base templated_attribute :website, :starting_value => 'http://' templated_attribute :phone, :label => '(123) 555-1234' end |
Validations work as expected, since unchanged template values get removed in a :before_validation callback. So you can sprinkle on a little :validates_presence_of and :validates_format_of for a really good time.
There’s also some nice, unobtrusive Javascript you can generate to get the behavior I mentioned above. If you’re using form_for, it’s totally automatic. It gets installed when you install the plugin, or you can install and remove manually with these rake tasks:
1 2 |
rake templated_attribute:install rake templated_attribute:remove |
To turn off the Javascript for a given templated_attribute—say, because the generated stuff doesn’t jibe with your fancy-pantsy, AJAX-validating, Grey Poupon of a form—just throw :templated_javascript => false in the options hash for text_field or text_area. You’ll have to do any styling and event handling by yourself.
I’d like to make this work for fields other than text_field and text_area; the other contenders were file_field, which we can’t do because the Javascript security model doesn’t let us touch its value at runtime, and password_field, which I haven’t done because showing the template value would require dynamically switching the element to a text_field and back (to avoid all those asterisks). That one’s on the list, though.
Plugin resources
- Browse the code:
http://railsplugins.code.shiftcommathree.com/browser/templated_attribute - Generated rdocs (with installation instructions):
http://docs.shiftcommathree.com/rails_plugins/templated_attribute - Raw svn action:
https://svn.shiftcommathree.com/rails_plugins/templated_attribute - Feed for svn changesets:
http://railsplugins.code.shiftcommathree.com/changesets.atom

Subscribe to
Thanks for the Browse the code! Nice artwork,too, throughout.
Hi, nice idea for a plugin - very useful.
However, when I try to use it I get an error “uninitialized constant x” with x being whatever the name of the object is. This happens on all textfield and textarea functions.
Any ideas what the problem might be?
Daniel: it’s hard to say without seeing some more details. If you want to shoot me an email with the full stack trace, as well as the snippets from your model and views where you’re using it, I’ll be happy to take a look.
Hi,
i am using your plugin for my rails app.
i have formfor insted of formtag
and this plugin is not work for me in this case can u please guide me where i am wronge
Arun: nice to hear you’re trying out the plugin. Everything should be fully automatic with
form_for; are you seeing an error message? What’s not working? I can’t help without some more details.On this end, I’m using the plugin in a couple Rails 2.0.2 projects and it’s working as advertised.
Hi Chris,
Thanks for your reply! I think the problem was that in our formfor we were being lazy and not providing the object itself. for e.g. formfor(:customer, :url .. ) not form_for(:customer, @customer, :url .. )
So that fixed the problem! Thanks heaps!
Cheers, Arun
Hi Chris,
I’m working with Arun and I think there might be a teensy weensy problem that you may give us an idea on.
We’re using templatedattributed on an associated entity. We’ve got a customer model which has a belongsto association with the address. The Pincode of the address is a templated_attribute.
Usually the name of pincode field turns out to be customer[temp_address][pincode] with the id as customer_temp_address_pincode. Now when we use the templated_attribute, the name of the field gets changed to address_pincode and and the observer is looking for element customer[temp_address]_pincode. Which basically doesnt work.
I’m trying to fiddle around in field_with_templating method’s last line and the bit where you generate the javascript part. Seeking your opinion/help!
Cheers, Aditya
Hi Chris,
I’m working with Arun and I think there might be a teensy weensy problem that you may give us an idea on.
We’re using templated_attributed on an associated entity. We’ve got a customer model which has a belongsto association with the address. The Pincode of the address is a templatedattribute.
Usually the name of pincode field turns out to be customer[temp_address][pincode] with the id as customer_temp_address_pincode. Now when we use the templated_attribute, the name of the field gets changed to address_pincode and and the observer is looking for element customer[temp_address]_pincode. Which basically doesnt work.
I’m trying to fiddle around in field_with_templating method’s last line and the bit where you generate the javascript part. Seeking your opinion/help!
Cheers, Aditya
Hi Chris,
Sorry about the repeat posts… i think i stuffed up the formatting.
I’ve now got it working so that it works with sub-models also. See Pastie – lines 16-17 and 27
http://pastie.caboo.se/141954
Do let me know if this is okay?
Thanks heaps!!!
Cheers, Aditya
Hi Chris-
Thanks for all the work on this plugin. I have heard good things about it and think it will be just what I need. That being said, when I try to install the plugin using:
ruby script/plugin install https://svn.shiftcommathree.com/railsplugins/templatedattribute/
I get:
Plugin not found: [“https://svn.shiftcommathree.com/railsplugins/templatedattribute/”]
I have added all repositories via the discover command. I am also able to install other plugins.
Any idea what may be going on?
Thanks for any help.
Regards,
Josh
Hey Josh,
I think you’ve run into a bug with the
pluginscript where it can’t handle non-verified SSL certificates (mine is self-signed). Check out this ticket on the Rails trac for a workaround. (Or, look into Piston for plugin management – it’s what I’m using these days.)