Finally took some time to jump in and refactor some nested forms at Thredded using Rails 2.3’s accepts_nested_attributes_for. Thanks to Ryan Bates’ screencasts on the topic it was fairly easy. A little code cleanup and everything worked as it should … other than one thing.
Can’t mass-assign these protected attributes
Noticed that error in my development logfiles after a particular form wasn’t being saved. A User class had some protected, and some not, attributes and until I added the Profile attributes to it, the nested form submitting a User and it’s associated Profile record would not save.
class User < ActiveRecord::Base has_one :profile accepts_nested_attributes_for :profile attr_accessible :login, :email, :password, :password_confirmation # ... end
Needed just the Profile attributes set as accessible and ready for mass assignment
class User < ActiveRecord::Base has_one :profile accepts_nested_attributes_for :profile attr_accessible :login, :email, :password, :password_confirmation, :profile_attributes # ... end
Another case where you need to know at all times where and if properties of your classes are locked down or not.

I’m pretty set in my ways professionally these days, so it’s hard sometimes to make a shift from what I’m comfortable with to a methodology that’s contrary to something that still works.
Like CSS – what the what needs to change in my work-flow regarding CSS at this point? I’m more than comfortable with box-models, browser hacks, sprites, peek-a-boo and double-float margin bugs. Waking up one day and thinking – “I could be better” was the kick in the pants to try something new. Enter Sass.
Sass is a meta-language on top of CSS that’s used to describe the style of a document cleanly and structurally, with more power than flat CSS allows. Sass both provides a simpler, more elegant syntax for CSS and implements various features that are useful for creating manageable stylesheets.
I won’t go into the syntactic sugar that makes Sass so much fun – John Long [1] [2] and Adam Darowski have already done excellent jobs rounding up the high, and lower, level concepts and tricks. I highly recommend visiting and bookmarking those links for future reference.
A few things I’ve bumped into, however, that bear mentioning here involve a few tools and code snippets that I went looking for as I went down that sassy path. The first being a Textmate bundle for sass I found to help out during rapid and uninterrupted development. The syntax highlights are, of course, fantastic, but the killer feature is easily the quick CSS generation keyboard shortcut. Command-R will parse and generate your CSS file right there from inside Textmate. If there are any issues a tool-tip will pop up with the error. If you switch over and reload your browser too fast to see the tool-tip you’ll see an unstyled page – a big honking notice that you were doin’ it wrong.
The few bits of code, of many, that I needed to find, or create, quickly before getting down to business – Eric Meyer’s reset stylesheet, and maybe a mixin or two that I’m quick to use in a pinch – like .clearfix.
// Reset
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td
:margin 0
:padding 0
:border 0
:outline 0
:font-size 100%
:vertical-align baseline
:background transparent
body
:line-height 1
ol, ul
:list-style none
blockquote, q
:quotes none
// remember to define focus styles!
\:focus
:outline 0
ins
:text-decoration none
// remember to highlight inserts somehow!
del
:text-decoration line-through
table
:border-collapse collapse
:border-spacing 0
// ----------- Clearfix ---------------
.clearfix
*display: inline-block
&:after
content: " "
display: block
height: 0
clear: both
visibility: hidden
// ----------- Clearfix as mixin ---------------
=clearfix
*display: inline-block
&:after
content: " "
display: block
height: 0
clear: both
visibility: hiddenThose are two solid examples of how easy it is to just jump right in. So give it a shot – `sudo gem install haml` to install what you need, and get to work playing.

Option 1 – Don’t do it.
And if that’s not on the table (haha – get it?), I present to you …
Option 2 – With a few things in mind when you approach the assignment you’ll get through it. It might not be the most fun, but it’s all doable.
My first suggestion would be to take whatever time you estimated, and double it. Maybe triple it. If you’re reading this post in its entirety then I’m guessing it’s safe to assume these HTML emails aren’t a daily routine for you. If such is the case, the time it’ll take between your first <table> tag, and the moment the email is spammed sent out will not be insignificant – 2-3 times the markup, 2-3 times the complexity in testing esoteric email clients. Your mileage may vary, depending on what the targeted visual design is. It’s always up to your discretion – but the one thing I didn’t anticipate, that I know is a rule, not an exception, is the time you spend on the testing process.
Before starting – these are the things you should have up front to make your life semi-easier.
The following are the gotchas and tips I’ve become familiar with recently through the course of developing a handful of these emails. These somewhat defy the logic you might be used to when developing for the regular web – a medium that’s already tricky and nuanced. Coding for email clients is downright dumb in comparison.
Final thoughts – You will no longer take for granted the wonder and beauty that is good, clean, lovely, semantic markup. It absolutely boggles the mind that corporate IT managers will fall over themselves getting new versions of Office rolled out to their IT infrastructure, but OMG A POX ON NEW VERSIONS OF INTERNET EXPLORER (OH THE HORROR!).
Last but not least – know where the closest liquor/booze/package store is. You’ll need a drink or two by the time this is over.
(hat tip to @bmenoza for the nudge in getting this post up)