Posts Tagged ‘rails’

Extend has_many with the :extend option

Wednesday, December 9th, 2009

The method has_many has several options that help you refine an association. The :extend option is one that I found myself using recently, and thought it would be nice to share with the internet.

Say you have a Friendship class that belongs to a User class, and that your User class has_many :friends, :through => :friendships. A good old fashioned @user.friends would return all the user records for @user’s friends.

Let’s also say your friendships table contains the fields user_id:integer, friend_id:integer, and state:string, where state can either be ‘active’, ‘requested’, or ‘pending’.

You might be tempted to do something like this in your User class:
has_many :friends do
def active
...some query...
end
...and so on for each state
end

I suppose, this would be fine if you only needed one method. You need something for each state, though, and this direction leads to unsightliness quite fast. Enter :extend.

Using this method, you can define methods in a module and call that module using extend. So the association looks like this:
has_many :friends, :through => :friendships, :extend => FriendshipState

FriendshipState is the module where your methods are defined:
module FriendshipState
Order = "users.last_name asc, users.first_name desc"
def pending
find(:all, :conditions => ['friendships.state = ?', 'pending'], : order => Order)
end
def requested
find(:all, :conditions => ['friendships.state = ?','requested'], : order => Order)
end
def active
find(:all, :conditions => ['friendships.state = ?','active'], : order => Order)
end
end

NOTE: there should be no space between ‘:’ and ‘order’. I did that to prevent god forsaken emoticons

The join is handled for you, so @user.friends.active returns all user records for @user’s active friendships; and so on with pending and requested.

SELECT `users`.* FROM `users` INNER JOIN `friendships` ON `users`.id = `friendships`.friend_id WHERE ((`friendships`.user_id = 1) AND (friendships.state = 'active')) ORDER BY users.last_name asc, users.first_name desc

Nice, huh?

Simple Two Way Encryption for Ruby on Rails

Saturday, November 14th, 2009

There are many options to choose from when you need to store an encrypted value in a database. After trying a few, I recently settled on Sean Huber’s delightful attr_encrypted gem.

To use attr_encrypted you’ll need to first install the gem (gem install shuber-attr_encrypted --source http://gems.github.com), then either require it in your class or via config.gem. I’ll demonstrate how to use attr_encrypted with a User record that, for whatever reason, needs to store the users Social Security Number (SSN).

Starting from scratch, let’s generate a User model with columns for the users name and encrypted SSN:

script/generate model User name:string encrypted_ssn:string.

You probably noticed that I created the column encrypted_ssn rather than ssn. This is because attr_encrypted expects the attribute you want to encrypt to be titled encrypted_#{attribute}. I’ll show you how to manipulate this in a moment.

Let’s encrypt the users SSN by calling attr_encrypted in our User model:

class User < ActiveRecord::Base
require 'attr_encrypted' #if you aren't using config.gem
attr_accessible :name, :ssn
attr_encrypted :ssn, :key => "some_key_you_like"

Be sure to declare :ssn in both your mass-assignment allowance and your encrypted attributes. Otherwise, you will get the famous “can’t mass assign…” warning in your log, or if you are validating presence of any encrypted attributes you will receive an error that they are blank.

From here, feel free to proceed as normal. Save the users SSN to the database from a form using the :ssn method, not the :encrypted_ssn method (text_field_tag 'ssn'). This will save the encrypted SSN to your db. Calling @user.ssn will yield the users decrypted SSN.

A Couple Extras

Pass the :attribute option to attr_encrypted if you would like the column to be something other than encrypted_#{attribute}.

attr_encrypted :ssn, :key => "some_key", :attribute => "private_ssn"

You will probably need to make sure that the SSN is unique, yes? In this case you want to validate the encrypted value:

validates_uniqueness_of :encrypted_ssn

As long as you are encrypting every SSN record with the same :key this will validate properly. Cover your bases and add a unique index on encrypted_ssn in your database, also.

attr_encrypted offers quite a bit more functionality, such as custom encryptors, custom algorithms, default options and marshaling. Be sure to read through the documentation at github.com/shuber/attr_encrypted.

Finally, thanks to Sean for helping me clear up a few things in my own use. He’s quite accessible.

A New Year, A New Website

Sunday, January 11th, 2009

2009“New Year” blog posts typically deal with lists. Lists of the best and worst of the preceeding year. This post will be no different. Observe

2008: The Best

Discovering that my pr0n name is Jake Ponderosa and getting people to actually refer to me accordingly.

2008: The Worst

We have a tie between Mamma Mia! and being rejected for Celebrity Rehab.

I do not really want to focus on 2008 with 2009 currently so shiny. 2009 holds so much promise: a new new deal, a new president, new friends, a new Star Trek movie that actually looks good, and a new motto “Feelin’ fine in oh-nine!”

I figured the new year was a great time to redesign erichurst.com. I kicked around a few approaches before settling on this package. I started rewriting the blog engine with Rails. Then realized that to do this the way I really wanted to I would need a virtual private server which I would have to maintain. Rails is a blast for me, but maintaining a server is not. That’s why this blog continues to be powered by good old fashioned Wordpress.

This turned out to be beneficial since at UCLICK we also decided that we would provide creator sites – to those who want them – powered by WP. This leaves us with the task of skinning the app appropriately and adding plugins and widgets as desired. I decided to experiment with my own site and what you now see is the result of said experiments.

I don’t know what to call the design. I’ve narrowed it down to Asian Cowboy, Parquet Party, Fake Brass, & Booyah Bowler. Your thoughts are certainly welcome. I’ll announce a winner this time in 2010.

Besides blogging and developing more there are a few things I’m looking forward to in the coming year.

First, Jen, my wife, is scheduled to give birth to our first child. We’re hoping for a Panda since they are so rare.

Second, in March I’m going to attend SXSWi for the first time. I’m hoping to make new friends, learn a lot, and make convention lanyards sexy again.

Third, I will be joining the Under 200lbs Club again. I’ve been hitting the gym with a buddy and I’m liking how much spandex agrees with me.

I hope you will join me here often in 2009. I’ll share a little of my world, if you will share a little of yours.