Thursday, February 12, 2009

Some of the First Lessons I learned about being more productive...

1. Get a mac
Seriously... there just isn't a really good excuse not to... I work with ruby... I assume that if you're reading this you work with ruby... if you do not work with ruby this doesn't really apply to you. (why are you reading this?)

I realize that mac isn't cheap... but it's well worth it... can't afford a mac? company won't pay for mac? ... then go linux... cheap hardware and free software... there's just no excuse...

first and foremost... you want your tools to work... the first time... all the time... every minute spent maintaining your tools is minutes you aren't being productive... I'm not saying that you should not maintain your tools... every good craftsman understands the importance of keeping their tools in good working order... but in my experience... it requires far less time to keep my mac purring like a kitten than it ever did my windows machines...

so... do yourself a huge favor... invest in your tools... but remember you don't have to spend a fortune... get the tools that 'just work'... even if they cost more... you'll be happy you did...
2. Use Version Control
You write code without version control?
Do you jump from planes without a parachute?
Coding without with version control is equally retarded...

just say no... and install a version control system... it's free... and it will save your life someday...

Which version control system? Well naturally I'm going to suggest Git... it is the new hotness after all... and after using SVN for a few years... the learning curve for Git is well worth it... just do it... tutorials are free...
3. Commit, and Commit Often and for the love of beer leave a message...
Now you have your development platform, and you have version control. Commit!!!
Commit your work... commit it often... don't be afraid to make micro commits...

Early in my career i was lucky if i committed my work once a day... these days i make alot more... I committed my work more than twenty times today alone...

Why? Why so many commits in a day? Simple...
  1. accountability...
  2. traceability...
  3. portability...
I can look back at my log and see exactly what I did... each commit corresponds to a single task... each log entry tells what that task was... should i decide i want to port functionality from one application to another i can cherry-pick the commits i want to merge between projects.. I simply could not do that with the once daily commits of a couple years ago...

Commit! No change is too small to commit...
4. Don't get bogged down in debates over what is 'best'
Don't try to be the best... that's impossible... instead...
only try to realize the truth...
there is no best...

Best is what works for you... what you are most comfortable with... what allows you to get the job done and done right... and no matter how good it gets... you will eventually always find something better... so don't waste precious time debating with anybody over what is 'best'... always be on the search for what's better...

The Acts As Coder Mission Statement

I kinda figure you're a lot like me..

You spend most of your day at a keyboard banging away at that thing to score your points, maintain your velocity, and keep your boss happy... and somewhere in there you make time to keep up in one or many of your pseudo-social networks... but mostly you do your best to keep your boss happy... After all he's going to have to approve your next time off request... which is right around the corner... so... you work hard...

But seriously... we coders are pretty lazy... now wait... before you get your Utili-kilt in a bunch... maybe lazy isn't the right word... after all i just said we work hard, didn't I?

We work hard... but we are always looking for a way to do our job more efficiently... which means more points in a day... which means higher velocity... which means happier boss... which might just lead to more time off... or more time to spend logged in to your favorite pseudo-social network... or more work done and bigger bonuses... I'll not judge what you do with your spare time...


One of my goals over the last couple years was to find ways to automate as much of my daily drudgery as i could... I mean, really, the core concept of the DRY (Don't Repeat Yourself) paradigm of coding is that you should never have to write the same code twice...

My plan for the foreseeable future is to use this space as my soap box... and share as many of my collection of time-saving, productivity enhancing tips and techniques as i can muster..

Time is money, Time is happiness.. and however you use your spare time... it's always good to have penty of it...

So... stay tuned...

Tuesday, February 3, 2009

link_to with prompt for rails 2.2.2

The feature request said: Create a mechanism whereby a user will be notified when an administrator suspends their account... and further... ensure that the administrator inputs a reason for the suspension. And include that reason in the notification email to the user..

So.. I thought to myself... sure... lets not stop at merely asking the administrator if they are sure about what they're doing when they press that shiny red button that makes the database row magically implode... Lets go a step further and ask the user why they want to press the shiny red candy-like button... that makes the record to vanish in a fiery ball of liquid hot mag-ma.

I thought about this issue for a few moments and decided:

  1. I want this to be as painless as possible to implement (i mean retarded-simple)... i need to be able to do this after a long morning of skulling Irish coffee...
  2. I want to be able to seriously annoy my users and administrators by asking them to explain themselves for every single action they ever do... (not that I would... but I could)
  3. I don't want to have to overload actions or create duplicate actions for every single explainable action in the system... (after all, duplicating work means i have to type that much more... or hit command-c, command-v alot... and how much fun is that... really?)
  4. It would be a huge bonus if this was as easy as link_to :confirm=>'blah blah'
So, in a brief brain dump with my coworkers... somebody (the boss... this is probably why he's the boss)... says in a moment of pure brilliance... use a javascript prompt...

To which i scratched my head... and thought way back to those yonder days of yore... yes, there were alert-style pop-ups that contained text inputs... (that was way-way-back in the days of never-ending q&a sessions with a pre-programmed script... the great-grandfather of being rick-rolled)... i've not seen one of those in a long time... it's crazy... but it just might work...

But wait... Seriously... i figured that somebody else had surely done this already... like maybe the rails core team... surely such basic function already existed... right... I mean, those guys that write this stuff think of everything, don't they?

Seriously... no sarcasm meant in that line... really... nine out of ten times i start doing anything in ruby these days i come to realize that somebody else has already done it... and usually done it far better than i was planning to... so... I scan the API docs, do some serious Googling and eventually scan the source code for link_to... and verify as best i can that nobody has done this yet...

Thinking that nobody has ever done this... This sometimes makes me nervous (like any time i have this feeling... i start to question my motives)... if nobody else has done it... does that mean there is a good reason... has nobody ever needed it... or maybe, like genetic manipulation... maybe it's better that we don't do it... but i think i'm getting a little off track here...


After much source code tracing and digestion the three simple methods below crafted into a strategically placed barrel-of-monkey-patch will have your rails link_to method capturing that extra explanation string and passing in on through to your controller so you can decide what to do with it... i.e. Email the user whose account just got suspended that they won't be able to log in anymore... or whatever you want... the possibilities are truly limitless.

The beauty is: you get all this using the same conventions you already use.. that is assuming 'you' are my fellow ruby on rails coders and 'you' do things like i do... i know it'a stretch... but ya never know...

link_to 'my Action', action_url, :prompt=>'why do you want to do this?'

This little gem will confront your user with a nifty javascript alert with a string input and will refuse to pass go until the user has entered an excuse for their request. Additional validation on the supplied string should be done server-side and perhaps a flash message and redirect tells the user their excuse wasn't up to snuff..

And i do suppose it's important to mention that the supplied reason will be posted in to your controller action in the form or params[:prompt_reply] ...

Hooray for perpetuating the everlasting nag-screen!!!

And for those of you have been ever-so-patient and read this far i give you... the code... and better yet... forget the code... i mixed this into a simple plugin... snag it from github.

module ActionView
module Helpers
module UrlHelpers

def convert_options_to_javascript!(html_options, url = '')
prompt, confirm, popup = html_options.delete("prompt"), html_options.delete("confirm"), html_options.delete("popup")
method, href = html_options.delete("method"), html_options['href']

html_options["onclick"] = case
when popup && method
raise ActionView::ActionViewError, "You can't use :popup and :method in the same link"
when confirm && popup
"if (#{confirm_javascript_function(confirm)}) { #{popup_javascript_function(popup)} };return false;"
when confirm && method
"if (#{confirm_javascript_function(confirm)}) { #{method_javascript_function(method)} };return false;"
when confirm
"return #{confirm_javascript_function(confirm)};"
when prompt
method ||= :post
"if(prompt_reply) { #{send_prompt_javascript_function(method, url, href)} }; return false;"
when method
"#{method_javascript_function(method, url, href)}return false;"
when popup
"#{popup_javascript_function(popup)} return false;"

def prompt_javascript_function(prompt)
"var prompt_reply = prompt('#{escape_javascript(prompt)}');"

def send_prompt_javascript_function(method, url = '', href = nil)
action = (href && url.size > 0) ? "'#{url}'" : 'this.href'
submit_function =
"var f = document.createElement('form'); = 'none'; " +
"this.parentNode.appendChild(f); f.method = 'POST'; f.action = #{action}; "+
"var p = document.createElement('input'); p.setAttribute('type', 'hidden'); p.setAttribute('name', 'prompt_reply'); p.setAttribute('value', prompt_reply); f.appendChild(p);"

unless method == :post
submit_function << "var m = document.createElement('input'); m.setAttribute('type', 'hidden'); "
submit_function << "m.setAttribute('name', '_method'); m.setAttribute('value', '#{method}'); f.appendChild(m);"

if protect_against_forgery?
submit_function << "var s = document.createElement('input'); s.setAttribute('type', 'hidden'); "
submit_function << "s.setAttribute('name', '#{request_forgery_protection_token}'); s.setAttribute('value', '#{escape_javascript form_authenticity_token}'); f.appendChild(s);"

submit_function << "f.submit();"