Display error_messages_for for a single flash error using a helper

So error_messages_for has been deprecated in Rails 3. However, you can still download the plugin from here and it’s still in use in a number of projects that we come across. It’s quite often that you see flash error messages appear outside of this error messages for style box but what if you just wanted to display a standardised form across your page.
In it’s simplest form the standard error_messages_for accepts an active model object and will display all of the errors found on that object. But what if we want to just pass in the error message that it should display?

The following snippet allows you to make use of the same template used by default but accepts a string containing the error message.

  def error_from_message(error_message, options = {})
    return nil unless error_message
    
    header_message = options[:header_message] || t(:header, :count => 1, :scope => [:activerecord, :errors, :template], :model => 'item')
    message = options[:message] ||  t(:body, :scope => [:activerecord, :errors, :template])
    
    contents = ''
    contents << content_tag(options[:header_tag] || :h2, header_message)
    contents << content_tag(:p, message)
    contents << content_tag(:ul, content_tag(:li, error_message))
    content_tag(:div, contents.html_safe, :id => 'errorExplanation', :class => 'errorExplanation')
  end

If you place that into your application helper you can then call the following in the view to render the standard active model style error message for the string you supply:

<%= error_from_message flash[:error_message] %>

You can also pass some of the standard parameters to change the tag or override the default header message. There’s nothing amazing in this but hopefully it will at least show where to get started to access the standard i18n translations used by the Rails helpers.

Language List Gem – a list of languages (ISO-639-1 or ISO-639-3) for Ruby

For a project I had been working on we needed to allow users to select the Languages that they could speak as part of a profile page. After a bit of research I found it difficult to find a comprehensive list of languages available in a format that could easily be used by Ruby.

Rails’ build in language files means that we’re all used to these shorthand prefixes like en to mean English. The issue was finding a nice list of all possible languages that could resolve to these codes. If we don’t take localised dialects into account such as en-gb or en-us then we can make use of the ISO standard list of languages housed in ISO-639-1 and ISO-639-3 for example.

After creating a script to compile these languages into a yml file that could easily be retrieved I launched this as a Ruby Gem that can be used in the following way:

all_languages = LanguageList::ALL_LANGUAGES

# Finding a language based on its ISO-639-1 or ISO-639-3 code
english = LanguageList::LanguageInfo.find('en')
english.name.inspect #=> "English"
english.iso_639_1.inspect #=> "en"
english.iso_639_3.inspect #=> "eng"

The only thing left was to add some helpers to be able to retrieve a list of common languages. Rather than re-invent the wheel I found a list of common langauges on this website. The author has compiled the list of common languages based upon the list of langauges that Microsoft use and a Wikipedia page of common languages.

I then added a common? flag to these langauges allowing for the following:

all_languages = LanguageList::ALL_LANGUAGES
common_languages = LanguageList::COMMON_LANGUAGES

# Finding a language based on its ISO-639-1 or ISO-639-3 code
english = LanguageList::LanguageInfo.find('en')
english.name.inspect #> "English"
english.iso_639_1.inspect #=> "en"
english.iso_639_3.inspect #=> "eng"
english.common? #=> true

I’m not 100% certain of the license of the ISO country list so use it at your own risk but any of the code I have created is released under the MIT license.

I am also sure that the datafile itself could be tweaked to include better names and punctuation so send any pull requests to the project on GitHub.

Some really quick git helpers

Here I’ve added a couple of useful tips for working with git. I’ll keep adding to it as I think of more but for now it’s a start.

So we all know it can be dangerous to remove remote branches and tags but once we know we need to do it what can we do?

Delete a Branch Locally:

$ git branch -d branch_name

Delete a remote branch:

$ git push origin :branch_name
This basically pushes nothing to the branch resulting in it being deleted.

Change the path (url) of a remote branch:

git remote set-url remote_name new_path

Delete a Tag Locally:

$ git tag -d tag_name

Delete a remote tag:

$ git push origin :refs/tags/tag_name

git ls-files

This one can be especially useful if you accidentally reset head –soft and want to delete your untracked files. In order to list all untracked files use $ git-ls -o. You could then for example run $ git ls-files -o | xargs rm to delete all of these files. Be aware that this command will list all files though. Including those you chose to ignore.

Update: It’s been a while since I’ve updated this but I thought I’d add a few more that I’ve found really useful lately:

Show all branches containing a commit:

$ git branch --contains 3a98e3
Make sure you git fetch before running this locally. If the commit isn’t found then git will probably list all the arguments as if `–contains sha` isn’t a valid option. If the commit is known but not on a branch you’ll see nothing.

You can also check remote branches with:
$ git branch -r --contains 3a98e3

Remove merged branches

Be careful this this one! Make sure you’re on master before you run this too!
git branch --merged | grep -v "\*" | xargs git branch -d

This will do the following:

List all branches that have been merged with the current branch, remove the entry with * as a prefix (the current branch), delete each branch name extracted by the previous grep.

 

Using factory girl in a Rake task – uninitialized class variable @@configuration in Rails

Over the last few days we have been working on a Rails 2.3 app for a client. We wanted to create a rake task that adds a couple of entries to the database (Seeds.rb is obviously better if you are seeding) and thought that we would use factory_girl to help us do this.

When we added factory girl we created something like the following:

require 'factory_girl'
require File.dirname(__FILE__) + '/../../spec/factories.rb'

namespace :db do
  desc "do something"
  task :create => :environment do
     ...
  end
end

When running this rake task we got the following error which seemed really confusing:

uninitialized class variable @@configuration in Rails
/Users/stevesmith/Documents/projects/profinda/.bundle/ruby/1.8/gems/rails-2.3.10/lib/initializer.rb:20:in `configuration'
/Users/stevesmith/Documents/projects/profinda/.bundle/ruby/1.8/gems/factory_girl-1.2.4/lib/factory_girl.rb:25

We were loading the environment so what was the problem? Well actually it’s pretty obvious once you know. In the above example we are trying to load factory girl before we actually set up the rails environment which won’t work.

Instead if you do the following everything runs fine:

namespace :db do
  desc "do something"
  task :create => :environment do
     require 'factory_girl'
     require File.dirname(__FILE__) + '/../../spec/factories.rb'
     ...
  end
end

This is really obvious if you think about it but it might just save someone a few minutes of debugging!

Receiving and Saving Incoming Email Images and Attachments with Paperclip and Rails 3

The last post showed how the use of Test Driven Development can help create Rails apps that can receive email offline that can be plugged into one of the incoming email solutions to receive email. The example was a movie poster model that took the subject of the email and added it as the title of that movie. The thing is what’s a movie poster without images? In this post I am going to cover how you can extract an image out of an email and attach it to a model using Paperclip.

We’ve already covered how to receive the email using CloudMailin and the app’s controller and pass it onto a mailer so I’m only going to cover the code we need in our mailer and models here.

Getting Paperclip setup

The first step is to get paperclip installed into our app. I would recommend following the instructions in the Paperclip readme here to get your app set up with Paperclip and test everything works with a normal controller and form. Our movie poster will need the following setup:

We start by adding the migration to add the Paperclip columns to the migration

t.string    :poster_file_name
t.string    :poster_content_type
t.integer   :poster_file_size
t.datetime  :poster_updated_at

We also need to add the magic Paperclip line to our Movie model

has_attached_file :poster, :styles => { :medium => "300x300>", :thumb => "100x100>" }

So far everything has been exactly the same as we would normally have to do if we were using the normal forms based approach to upload, next we’ll add the code to our mailer.

Setting up the Mailer to Receive Attachments

Normally when Rails receives an uploaded file it has to be through a multipart/form-data. When a Rails app receives these files it recognises the attachment parameter and behind the scenes a temporary file is created containing that content. This is to stop the attachment being stored in memory. This file is then extended by Paperclip to contain a few additional bits of information it’s original file name and the content type of the upload. Our email however is stored in memory and it’s attachments don’t get stored as files. For that reason we need to emulate the temporary file so that Paperclip can correctly work with out attachments.

In order to do this we can use the following mailer:

class MovieMailer < ActionMailer::Base
  # Create an attachment file with some paperclip aware features
  class AttachmentFile < Tempfile
    attr_accessor :original_filename, :content_type
  end

  # Called whenever a message is received on the movies controller
  def receive(message)
    # For now just take the first attachment and assume there is only one
    attachment = message.attachments.first

    # Create the movie itself
    Movie.create do |movie|
      movie.title = message.subject

      # Create an AttachmentFile subclass of a tempfile with paperclip aware features and add it
      poster_file = AttachmentFile.new('test.jpg')
      poster_file.write attachment.decoded
      poster_file.flush
      poster_file.original_filename = attachment.filename
      poster_file.content_type = attachment.mime_type
      movie.poster = poster_file
    end
  end
end

Here we can see the AttachmentFile class that fakes the parameters needed by Paperclip to work with the file. We then create the AttachmentFile class passing in a filename to be used for the temporary file. Then we write to the file, flush the contents and set the required parameters for Paperclip.

Now when we receive an email the first attachment is taken from the email and stored as our movie poster with by Paperclip.

If you don’t want to use a temporary file you can also use a StringIO object and see the same benefits.

In addition to this @pedrodelgallego pointed out another posible solution that extends a StingIO class anonymously using class eval using the following code:

attachment = message.attachments.first

file = StringIO.new(attachment.decoded)
file.class.class_eval { attr_accessor :original_filename, :content_type }
file.original_filename = attachment.filename
file.content_type = attachment.mime_type

Hopefully this will be of use for anyone trying to store attachments extracted from emails. The real benefit is that Paperclip doesn’t only work with images, you can store all sorts of attachments and push them to S3 if you need to. If anyone has any other suggestions or better ways to achieve this I’d also love to hear them.

Receiving Test Driven Incoming Email for Rails 3

One of the most frequent questions we are asked at CloudMailin is how can you develop your application and receives email offline, without opening ports, in a Rails app.

There are options that spring to mind. The first is to write a script that delivers a local email to your app simulating the response that you would get from an email server. The second solution is far simpler. You can perform test driven development and it can be really easy  get things up and running in development and even easier to move to production.

Here we are going to create a really simple example to take the subject of an email and create a model called movie poster from that subject. In a later post we will show how we can also use the attachments to create the images for the poster.

The First Step, a Controller to Receive the Email

In a previous article I highlighted a number of options for Receiving Email in Rails 3. Using some of the approaches you don’t even need to use a controller but in that case where email is delivered to your app via an HTTP POST the controller is needed. The controller doesn’t have to be complicated though. All we really want to do is pass a mail object to the receive method of our mailer. So supposing we have a mailer called MovieMailer we can do the following:

class IncomingMailsController < ApplicationController
   skip_before_filter :verify_authenticity_token
   
   def create
     # create a Mail object from the raw message
     movie_poster = MovieMailer.receiver(Mail.new(params[:message]))
     # if the movie poster was saved then send a status of 201 else give a 422 with the errors
     if !movie_poster.new_record?
        render :text => "Success", :status => 201, :content_type => Mime::TEXT.to_s
    else
      render :text => movie_poster.errors.full_messages.join(', '), :status => 422, :content_type => Mime::TEXT.to_s
   end
  end
end

The example above assumes that you are using at least Rails 3.0 but it can easily be converted to work with older versions of Rails and you could use the TMail gem rather than Mail if you need to.

Now we have this controller we can create a functional test to check this in the same way we would any other controller in our app (note I’m doing this the wrong way round for illustration you should really write your test first!). If we mock the response from the Mailer for now we can use something like this with Shoulda but you could use RSpec or any other testing framework just as easily:

class IncomingMailsControllerTest < ActionController::TestCase
   context "An IncomingMailsController" do
     context "on POST to :create with an invalid item" do
        setup do
           MoviePoster.any_instance.expects(:valid?).returns(false)
           post :create, :message => "From: #{@user.email}\r\nSubject: New Poster\r\n\r\nContent"
      end

      should_respond_with 422
      should "not create the item" do
        assert assigns(:item).new_record?
      end
    end

    context "on POST to :create with a valid item" do
      setup do
        MoviePoster.any_instance.expects(:valid?).returns(true)
        post :create, :message => "From: #{@user.email}\r\nSubject: New Task\r\n\r\nContent"
      end

      should_respond_with 201
      should "set the items title to be the message subject" do
        assert_equal "New Task", assigns(:item).title
      end
    end
  end
end

I have also created a really simple email message to pass as the message param here as an example with the header and body separated by two carriage return new lines but this isn’t really necessary with the use of mocha.

From: example@example.com
Subject: Subject

content

So on to the Mailer

Now that we have our controller sorted and fully tested we can create our Mailer, which will automatically create a functional test. It’s then just a case of adding the tests to test the receive method. The first step is to create a sample email that we can use in each of our tests. I am using the Mail gem again to do this.

  context "A MoveMailer" do
    setup do
      @message = Mail.new do
        from "test@example.com"
        to "test@example.com"
        subject "New Movie"
      end
    end

Then we can add our tests making use of the example mail we added and changing any of the parts we want to.

  should "create a new movie poster with the email subject" do
    @message.subject = "new subject"
    assert_difference("Movie.count", 1) do
      movie_poster = MovieMailer.receive(message)
      assert movie_poster.persisted?, movie_poster.errors.full_messages
      assert_equal "new subject", movie_poster.subject
    end
  end

In this case we’re just going to add one test and we can now create our simple movie mailer to take the subject from the email and store it as a poster.

class MovieMailer < ActionMailer::Base

  # Called whenever a message is received on the movies controller or through the rails runner
  def receive(message)
    # For now just take the first attachment and assume there is only one
    attachment = message.attachments.first

    # Create the movie itself
    Movie.create do |movie|
      movie.title = message.subject
    end
  end
end

Now when your app goes into production you just deliver the message to the controller using the HTTP Post approaches, directly to the mailer using any of the other approaches discussed in the previous article.

Although the example is a little contrived you can hopefully See how you can benefit from testing at the development machine to ensure you system works perfectly once you put your code into production. You also have the added benefit of not having to keep checking things whenever you change your code. Just re-run your tests, same as you would with any other part of your app!

A Step by Step Guide to Receiving Email in your Web Application with CloudMailin

In this post, we’re going to take a step by step guide approach to configuring and receiving your first email in you web app with CloudMailin. CloudMailin allows you to receive email in your web app via an HTTP POST. You setup the server to point to your site’s public url and your email is sent straight to the site. We will also cover how to add your own domain name and set it up so that you can give customers your own email address.

The first step is to head to http://CloudMailin.com and signup for a free account.

As soon as you sign up, you will be presented with the option to create your CloudMailin address. Here you enter the url of page that you wish to receive your email via HTTP Post at. After you click submit, an email address will be generated for you and anything you send to that email address will be sent to your website.

Once you click the submit button, the site will generate your email address and you will be ready to go. You will be redirected to the address list page. Here you can see each of your CloudMailin addresses, the target, that your HTTP Post will be sent to when an email is received and the plan details. Each CloudMailin address sits in its own plan so you can have different allocations for each address and therefore web app you want to receive email within. Currently the site is in beta so there is only one free plan. However once the site launches, there should always be a free plan to get started.

If you click on the address listed in the address list, you are taken to the page for that address. On this page are a number of configuration options for the address but also the delivery status list. The delivery status list is a powerful feature that allows you to see each email that passes through the system and the status of that message.

So lets go ahead and send an email to the address that CloudMailin has given us. We should almost instantly get a response back saying that the message delivery has failed.

What? The delivery failed? When we take a look at the delivery status page we can not only see that the message has failed but see that the target gave a status code of 404 because we never set up a page to receive the email. CloudMailin is clever enough to know the difference between the status codes that it receives when it delivers the email. If it receives a status code like 200 it assumes that everything was ok and the message was received successfully. If the target server has an error then or is unavailable then CloudMailin will tell the server that an error has occurred and that it should retry later. Finally if a status code like 404 or 422 occurs then it will tell the server that the message was rejected and that it should not try again later. More details about the HTTP responses that you can give to CloudMailin and the actions taken can be found in the HTTP status codes documentation. You can even send a custom bounce message when you reject the delivery of an email so long as your response is in plain text.

Ok so now its time to write some code and receive our email. If you are using Rails, you can take a look at some previous blog posts. There are also some examples in the parsing the email documentation. CloudMailin is language agnostic though, you can use it to receive incoming email in Java, PHP, Python, .Net, Scala, Small Talk or any other language that you want (so long as it can parse HTTP Posts). We are hoping to expand the languages in the documentation and they are all on github so feel free to contribute documentation for your favorite language! The request is sent to your server in the same way as any other form that you would fill in on your site as a multipart/form-data request. The plaintext and html parts are also nicely separated out to make life easier but the full email is available to allow more detail and attachments if it’s needed. The HTTP Post format documentation should help here.

Great, so now we have our server configured correctly, we’re ready to receive our email. So lets go ahead and send another email to our CloudMailin email address.

Awesome, Green lights! So now we’re successfully receiving our emails and processing the contents. What else can we do? Well, if you take a look down the right hand side of our address page, there’s a button labeled custom domains. This allows us to use our own domain name to receive email with whatever address we want. In order to do this though we need to start by configuring our DNS server to point any emails sent to our domain to the CloudMailin server. The documentation has a page dedicated to showing you how to configure your DNS server’s MX records to point to the CloudMailin servers and allow you to receive email via your own domain.

Once we have configured our DNS records we can go ahead and add our domain name to the custom domains form that we can open using the custom domains button. If you want to create client subdomains like anything@x.example.com and anything@y.example.com you can also add subdomains.

So that’s it. Using CloudMailin we can pretty easily receive email in our web apps. We’d love to hear what you create and also remember all of the documentation is on Github so if you have changes or additions or importantly examples for other programming languages and frameworks then please fork the documents and send a pull request. Most importantly feedback is always appreciated.