International Mailing Addresses

Posted by Lance Ivy Wed, 15 Jul 2009 23:42:00 GMT

Wow, is it complicated to format mailing address for international delivery!

Let’s do something about it.

I’ve started a library called Snail based on quality resources like Frank’s Compulsive Guide to Postal Addresses and the USPS International Mailing Manual. But it’s far from complete. So far it’s set up to format addresses from the United States to many other countries. That fills most of my needs at the moment. But what I’d love to see is:

  • Support for other origin countries
  • Support for more destination countries
  • Validation tools based on each destination country. Just knowing which fields are required in which countries would be a great start!
  • Form helpers to generate some of the best-practice address forms.

So! If this scratches an itch, then please consider helping out wherever you can.


Seamless Deploys with Ec2 on Rails 0.9.9.1

Posted by Lance Ivy Mon, 01 Jun 2009 20:57:00 GMT
I've been using a simple Capistrano recipe to deploy fixes to a production environment, and I figured hey, maybe other people want to do the same. I know there are other scripts out there, but this is particular to Ec2 on Rails and is tested against version 0.9.9.1. Also, I've created a /stat page that responds with a 200 when the site is running. The recipe uses that url, but any other would work as well.
namespace :deploy do
  desc "Hot deploy, only usable w/o migrations"
  task :hot do
    update
    reroll
  end

  desc "Rolling restart for Mongrels"
  task :reroll, :roles => :app_admin do
    (8000..8005).each do |port|
      sudo "monit -g app unmonitor mongrel_#{port}"
      sudo "/usr/local/ec2onrails/bin/mongrel_stop --only #{port}"
      sudo "/usr/local/ec2onrails/bin/mongrel_start --only #{port}"
      sudo "wget --no-verbose localhost:#{port}/stat && rm -f stat" # this should block until the mongrel has booted
      sudo "monit -g app monitor mongrel_#{port}"
    end
  end
end

Mass Assignment in ActiveRecord

Posted by Lance Ivy Mon, 25 May 2009 23:31:00 GMT

New plugin! From the README:

What It Is

A robust mass assignment method with a small and obvious syntax.

The normal mass assignment protection comes from attr_protected and attr_accessible. There are a many problems with this approach:

  • Often never implemented, leaving a wide-open system. And once implemented, easy to forget when adding new attributes, leading to bugs (in an attr_accessible system) or security holes (in an attr_protected system).
  • Restricts coding syntax. You can’t easily use update_attributes() or attributes= because your whitelist/blacklist gets in your own way.
  • Not contextual. The list of allowed attributes can’t change to accomodate different user permissions or situations.

This plugin’s solution is to let you specify an obvious list of allowed attributes when you mass assign attributes.

  • The list of allowed attributes is in your controller at calltime, so it’s easier to remember and update (it’s not a hidden, magical system).
  • The list of allowed attributes is optional, so it doesn’t get in your way.
  • Your controller can easily enforce permissions by evaluating the current user (Admin Controller) or the current situation (creates vs updates).

Example

Let’s take a very plausible situation where you would want three separate lists of allowed attributes. You have users that sign up to your application. But after they have signed up, they may not change their username. Admins, however, may manually change a username as needed.

class UsersController < ApplicationController
  def create
    @user = User.new
    # during signup a user may pick a username
    @user.assign(params[:user], [:username, :email, :password, :password_confirmation])
    @user.save!
    ...
  end

  def update
    @user = User.find(params[:id])
    # username is no longer accepted later
    @user.assign(params[:user], [:email, :password, :password_confirmation])
    @user.save!
    ...
  end
end

class Admin::UsersController < ApplicationController
  before_filter :admin_required

  def update
    @user = User.find(params[:id])
    # admins, on the other hand, may change the username as needed, but may not set passwords
    @user.assign(:params[:user], [:username, :email])
    @user.save!
    ...
  end
end

Get it here: http://github.com/cainlevy/mass_assignment/tree/master