Today, I found a bug in Rails.

On a project, I need to mail PDF files to users, and I would like to use PDFKit for that. The contents of the PDF are generated by rendering a view, but I don’t really want PDFKit to hit the server to get the content. Both because this breaks down in unit tests where the server may not be running, but also because there’s just no reason to go through the entire stack.

So I decided to generate the HTML with render_to_string, then convert it to PDF with PDFkit, and finally mail it to the user.

However, it turned out that this doesn’t work. Here is a minimal example:

class NoteMailer < ActionMailer::Base
  default :from => "from@example.com"

  def foo
    @notes = []
    render_to_string(:template => "notes/index.html.erb")
    # self.instance_variable_set(:@lookup_context, nil) # <-- Workaround
    mail(:to => "example@example.com")  
  end
end

It turns out that the call to render_to_string initializes the @lookup_context of the controller (== mailer in this case). The lookup context is the object that is responsible for locating templates to render, so it contains (among other things) a list of template extensions to look for.

The call to mail() renders the actual mail, but the mailer now reuses the lookup context that was created by render_to_string. This prevents it from finding the mail template, which is (in this example) named “foo.text.erb”, because the lookup context doesn’t recognize the “.text.erb” extension.

A workaround is to manually clear the lookup context on the mailer after the call to render_to_string, but obviously this is a really bad solution.

Here is a very simple tip that has been really useful to me over the last few months.

The way I work in Emacs is by opening lots and lots of files and then quickly selecting the buffer I want with ido-mode.

However, this breaks down if I have more than one project loaded in my Emacs session. For example, when working on Rails projects, I want to be able to find the routes.rb file with just a few keystrokes. To avoid restarting Emacs whenever I switch project, I need multiple instances running simultaneously, which is not “supported” in OSX (or rather, it’s just not the OSX way).

To workaround this, I use a really simple hack: Copying Emacs

So to create Emacs2 and Emacs3 in addition to just Emacs, do

cp -r /Applications/Emacs.app /Applications/Emacs2.app
cp -r /Applications/Emacs.app /Applications/Emacs3.app

That’s it! Now you can fire up three Emacs instances at the same time. Next step will be to replace the icons of the clones to make it easier to spot them when switching applications.

[EDIT]

As discussed in the comments below, I can just start new instances with “open -n -a Emacs.app”. Thanks tali713 for bringing this to my attention!

Follow

Get every new post delivered to your Inbox.