Sunday, September 23, 2007

Updating checkboxes

Ran into the weirdest problem today. I have a couple check-boxes on a form. Using form_for to display the check-box fields for update. Even though the submit action on the form delivers the correct params for the check-box fields, the user.update_attributes(params[:user]) generates a SQL UPDATE statement with the wrong values - but only for the check-boxes. All other fields are fine. Here's two screen shots from the development.log that illustrate it.

To work around it, I just added user.update_attribute(:email_1, params[:user][:email_1]) and saved it.


Thursday, September 20, 2007

Setting focus to a form field

Rails doesn't set focus to the first form field automatically so you have to do it yourself with a little unobtrusive javascript. Here's a helper that does it:

def set_form_focus
javascript_tag("Event.observe(window, 'load', function() {
var firstForm = $A(document.getElementsByTagName('form'))[0];

Uses the Prototype library, so the page must have a javascript_include_tag("prototype") or javascript_include_tag("defaults") or equivalent. The Prototype Form.focusFirstElement requires a form id but my forms often don't have a name or id. So we look for the first form on the page using the DOM function getElementsByTagName. This function returns a node list and it's easier to treat this as an array by passing it to the $A prototype function so that [0] gives the first form. Finally, attach this function to the window load event instead of firing before that. Most browsers would show the focus fine if it fires earlier, but IE ends the whole page to be loaded first.

Place the helper after the element on the page, preferably after the <% end %> tag for the form. One tricky thing: if you use tables to build formatted forms (as I do) make sure the <table> tag is after the <% form_for... or <% form_tag... or <% form_remote_for... tag.

Sometimes I use a formless input field with an associated observer to return results via ajax. To set focus to this field I use this quick helper:

def set_focus(id)
javascript_tag("Event.observe(window, 'load', $('#{id}').focus());")

Again, it must be after the specified field on the page and this field must have an id.

Saturday, September 8, 2007

Stylesheets in ActionMailer

I love ActionMailer. When sending html emails you might want to reuse your existing CSS stylesheet(s). There are potential problems with doing this (see CampaignMonitor for a definitive run down on styling for email clients), but you might be clever enough to have a page layout that is directly usable for html emails, too.

Most/all email clients won't import a linked stylesheet like a browser does, instead you have to embed it directly in the email as an inline style.

To embed your styles in the email insert something like this in the <head> of your email template:

<style type="text/css">
<%= render :file=>"../../../public/stylesheets/admin.css", :use_full_path=>true %>

Then you can go ahead and use the similar layout as your Web pages in your email. As the Campaign Monitor guys will tell you, you want to avoid floated elements and any information in rendered images. This usually means you'll make a table-based layout for the email but you can reuse styling from the Web pages.