Archive for the 'Rails' Category

Friday, August 29th, 2008

ActionMailer: Changing the subject in the template

Here's another little bit to go along with the previous post.

Another thing I didn't quite get/like about some of the ActionMailer setup is that even though you're putting all the email body text in a file somewhere that's not your Mailer class, you put the text of you're subject in there. Some more snooping in the source reveals setting the subject from within the template is easy - your Mailer instance is exposed to the template as 'controller':

<% controller.subject = 'Change of subject' %>
Hello <%= @user.display_name %>

Thank you for your order. 

Love <%= controller.from %>
Thursday, August 28th, 2008

ActionMailer: Hacking multiple template paths

I was up against a little wall this afternoon and I had to monkey patch my way out.

It struck me as weird that with ActionView you can have a whole array (really Array) of view/template paths that are iteratively searched for a matching template, however, with ActionMailer (even though it uses ActionView) you can only define or override the single template_root.

Bizarre, right? I bet rails core had some good reason for this, but in this specific project I'm relying heavily on using ActionView::Base.prepend_view_path() to have the app structured with default templates that are easily replaced by dropping templates in to a different view path. So if I'm doing that for an entire site it would make sense to do the same for my 'Notification' templates as well. The rails docs were pretty unhelpful, but a quick dive into the source proved fruitful. If you drop the code below into config/initializers/action_mailer_extensions.rb:

module ActionMailer
  class Base
    class_inheritable_accessor :view_paths
    
    def self.prepend_view_path(path)
      view_paths.unshift(*path)
      ActionView::TemplateFinder.process_view_paths(path)
    end

    def self.append_view_path(path)
      view_paths.push(*path)
      ActionView::TemplateFinder.process_view_paths(path)
    end

    private
    def self.view_paths
      @@view_paths ||= [template_root]
    end
    
    def view_paths
      self.class.view_paths
    end
    
    def initialize_template_class(assigns)
      ActionView::Base.new(view_paths, assigns, self)
    end

  end
end
You can do:
ActionMailer::Base.prepend_view_path('/my/other/path/to/search/first/')
# or
ActionMailer::Base.append_view_path('/my/other/path/to/search/last/')
Friday, February 29th, 2008

DRYing up Rails Flash with Flashdance

Flashdance

The scenario: Its 3AM. You've been coding all day and youre just about ready to launch this sweet social networking app for steel workers who love to dance. One last thing - you need to replace all the crappy copy you stuck in to your 'flash' messages with real informative text. "sucesfil post" might make sense to you, but wont make sense to the blue collar guy doing the electric slide all over your server. You go to replace these warnings and feedback messages but theyre all over your code. You think: If Rails is so DRY and the business and display logic are all supposed to be separate, then why am I putting messages that will end up in my views all through my controllers?!

Introducing Flashdance

The get-the-view-out-of-the-controller-so-you-can-rest plugin.

Instead of all-up-in your controller files, messages are stored in a single YAML file:

# in app/views/shared/flash.yml

all_is_good: This is great
this_failed: This failed
using_erb: you are an idiot, <%= @email %>
section:
  subsection: I'm nested
my_controller:
  my_action:
    message: I'm soaking wet

Examples

At its most unobtrusive:

# in your controller
  def update
    # . . . booring part where record gets updated
    flash[:warning] = flashdance(:this_failed) #=> This failed
  end

A little nicer:

def update
    # . . .
    flash(:message => 'all_is_good') # YAML entries can be referred to by strings or symbols
    # equivalent to flash[:message] = "This is great"
  end

ERB is evaluated in the context of the controller so you can do fun things like:

  def tell_off_the_spammer
    # . . .
    @email = 'jon@example.com'
    flash(:warning => :using_erb)
    # equivalent to flash[:warning] = "you are an idiot, jon@example.com"
  end

So what if your app is huge and you use these flash thingies all over the place? Your YAML file might get big and unreadable. Well, thats why you can nest! Nested sections are refered to by arrays.

  def make_a_nest
    #  . . .
    flash(:nest => [:section,:subsection])
    # equivalent to flash[:nest] = "I'm nested"
  end

Flashdance automatically checks for entries nested in the controller/action path where you call it from. And heres where you get splashed with that big bucket of water:

class MyController < ApplicationController
  # . . . 
  
  def my_action
   # . . . where you dance your heart out
   flash(:message)
   # equivalent to flash[:message] = "I'm soaking wet"
  end
end

Install it

From subversion:

./script/plugin install -x svn://svn.quirkey.com/quirkey_tools/trunk/flashdance

or Download: flashdance.tar.gz

You can email me at aaron at this domain for bug reports/comments/suggestions - and I'm looking to set up Trac or something else soon.

Photo credit: http://www.flickr.com/photos/tzofia/185003069/

Thursday, February 28th, 2008

QuirkeyTools

I’ve been such a Rails mooch. Relying on everyone else’s plugins, gems, and helpful blog posts. A while ago I said how I wanted to be a real part of this community. Well its time to stop coding (briefly) and start sharing. It’s time to give back.

Over the past year and a half (!!!) of doing Rails and Ruby full time, I’ve come up with a lot of code thats useful, at least to me. For a while its all been packaged as a plugin on my private SVN server called QuirkeyTools. It’s chock full of helpers, generators, extensions, macros - its bursting at the seems.

So the idea over the next couple of weeks is to start splitting out the code, cleaning up the tests, and releasing them as separate Rails plugins. I’m also going to look into packaging some gems - which sounds like fun.

All of this is made possible in part by the fact that I’ve got a new VPS from slicehost. I’m not getting paid to say this but its awesome! Super fast, haven;t had any reliability problems and its a blank slate - meaning install whatever you want. They also have some great of the best tutorials for setting up. This blog remains (for the time being) on my shared host at Site5, but I’ve set up an SVN server and repositories with public read permissions. So here comes the code . . .

Photo Credit: http://www.flickr.com/photos/docman/36125185/sizes/m/

Monday, February 18th, 2008

Recent Project: Wejetset

WeJetSet.com

Sexy and cool and full stuff is wejetset.com, an online store + blog, highlighting some of the neatest travel and general awesome products available.

I coded this application from scratch and I can say that the back-end is pretty sexy too. E-commerce sites aren’t always the most fun to work on, but with this gorgeous design - a collaboration between Staple Design, friend and stranger and Intersect - I can easily say I was very proud to be a part of this project.

Its gotten some good press already. I kind of want to buy everything in the store (action books? Sweet GTDness.).