Serialize “stuff” in your tables with ActiveRecord
An Example
So, you’re building a Web application that allows users to customize a car before they purchase it.
Here’s what the current car table looks like ( in Migration speak ):
create_table "cars" do |t|
t.column "make", :string
t.column "model", :string
t.column "new_smell", :boolean
end
The tasking…
You boss comes in and says “Hey! I got a great idea! Let’s give users the ability to manipulate/change the color of the car…” Immediately your brain snaps into design mode. Hmmm…each car may have many color choices…do I need to add another table just for colors? You ask your boss, “Do we care what colors people are choosing? For example, will we ever want to ask the question how many people chose a Red car”? “No”, your Boss replies, “keep it simple and have it done yesterday!”
ActiveRecord to the rescue
Ok, I like keeping it simple. I’m just going to stuff it all into the car table. Fortunately the Rails Gods have dealt with this before. So like many other things in Rails, it’s easy to do. I want to store the colors in a simple Array.
Let’s modify the table.
create_table "cars" do |t|
t.column "make", :string
t.column "model", :string
t.column "new_smell", :boolean
t.column "colors", :text
end
Notice I added the colors field with a type of :text. That’s because Rails will serialize my Ruby Array (or most any other object I specify) into YAML. And because it’s in the YAML format, it should be accessible from any other language that can read YAML. Ok, almost done. We just need to add a line to our model:
class Car < ActiveRecord::Base
serialize :colors, Array
end
is a class method that tells ActiveRecord to move the colors field back and forth between YAML and an Array. So in our example above, 1.) :colors tells it to use the colors field and 2.) Array (optional) tells it to check what I’m trying to store. So in our example if I try to pass a Hash to the colors field an exception is thrown.
Now I can use the Array on my model as normal:
Car.create( :make => "Yugo", :model => "Hatchback",
:colors => ['red','yellow','magenta'] )
c = Car.find_by_make("Yugo")
puts "Available colors:"
c.colors.each{ |color|
puts "#{color} Yugo"
}
And that’s it. Just two lines of code to add to your app! Check out the for more details.
Trackbacks
Unfortunately, due to spammers I've had to close both trackbacks and comments.