« January 2006 | Main | March 2006 »
February 20, 2006
Quite the Weekend
I don't normally talk about personal things on this blog, but it's been a landmark couple of days around here, so I thought I'd set them down. On Friday, I gave my notice at Pix, where I've worked for more than two and a half years. This coming Friday night will be my last shift. If you're free and in Portland, I encourage you to come down for a visit -- especially those of you who've been in before during my shifts or even made it a habit. I'll miss the place and the people, but it's definitely past time for me to be doing something else.
Speaking of which, a couple of my Less Distracted cohorts and I have put up our Ruby on Rails contract development and consultancy shingle (that's a bit of a misnomer for what we did, since the enterprise has neither a name nor a home, but anyway, we're open for business) and over the weekend we landed our first client. I guess that (combined with the quitting) officially makes me a professional Rails developer which somehow manages to sound even stranger when I say it aloud than it feels -- which is saying something.
Plus, by the time you read this, we'll probably have locked final mixes on the new At Dusk album, a moment about eighteen months in the making. Now, there's still some stuff left before the record's finished (we have to give it a name, settle on art, and send the mixes off to mastering), but this is a giant step.
Anyway, all of this good stuff snuck up on me and then all struck at once. And I'm 26. I feel like I need to have a second Bar Mitzvah or something. . .
Tagged: pix, patisserie, portland, oregon, rails, ruby, less, distracted, at, dusk, music, personalPosted by Greg at 1:22 AM | Comments (2)
February 15, 2006
learns_to use acts_as_versioned
Lately, I've been learning Ruby on Rails. In layman's terms, Ruby on Rails is a system for making dynamic websites like Flickr, Friendster, and yes, Music For Dozens. To drastically oversimplify, some of the smart people have gone ahead and handled all of the common tasks like logging on, handling user input from forms, remembering data and displaying it when appropriate, etc. The idea is to make it easier to create a dynamic website by letting you focus just on the unique thing that you want your site to do and not all the boring and difficult infrastructure all such sites need.
Chris and I are writing a super-secret exciting new MFDZ project in Rails and, eventually, we'll be rewriting MFDZ itself in it. In the process, I've come across some opportunities to actually get paid for working on other people's Rails projects, so I've been devoting some semi-serious time to improving my skills. Predictably, I've encountered a few beginner-type problems to which I couldn't find great solutions online. Some of these I've been able to work through with the online help of some of the many strong Rails programmers in Portland and a few others I managed to solve with just my own wits. I figured it would be the neighborly thing to do to write down some of what I've learned here for the sake of the next poor soul who would otherwise Google-up empty on the same problem.
Thus, I introduce learns_to, a new category of post here at IDFDZ where I'll try to document a little bit of what I've learned about Rails as clearly and concretely as I can. If you're one of the people who emails me about my blog becoming too boring and "technical" or, more specifically, you're just not interested in Rails, I urge you to move on now. But, if you're me from earlier this week -- wondering how you'll ever get acts_as_versioned to work with your project when you barely know the difference between a plugin and a gem -- then hopefully you've come to just the right place.
What it is
Acts_as_versioned is a chunk of Rails code meant to help you keep track of, well, progressive versions of whatever it is your application keeps track of. The quintessential example is the way a wiki keeps track of edits made to a page's information. In fact, acts_as_versioned is great for giving wiki-like revisible user-edited content to any part of your Rails app.
Where to get it
As I alluded to in the introduction, there are two different ways to get your hands on acts_as_versioned: as a plugin or as a gem. RubyGems is Ruby's built-in packaging system. It has a number of conveniences including easy command line installation and updating. These characteristics make it definitely the best way to get Rails itself and to keep your local copy fresh. However, in the context of an add-on like acts_as_versioned, I would recommend using plugins whenever you have the opportunity. Plugins have the great advantage that they are automatically included by Rails itself when you start the server. You don't have to write any fancy setup code. That means not having to venture into environment.rb, or any other exotic places that can be scary for Rails newbies like me.So, go ahead and download acts_as_versioned now (that link is to a .tgz, just what you'll need on the mac). Unzip it and move it into the /vendor/plugins folder in your Rails app and we'll get started using it.
Database setup
Before we get too far into the workings here, I should point out the documentation. It is not especially human readable, but it is a definitive reference for this stuff (most of what I'm about to say, I figured out by staring at the documentation for the Class Methods for a long time).
Anyway, the first thing we've got to do is get our system setup to use acts_as_versioned. This means database setup and some small changes to our models. Let's say we're doing a music app. We've got artists and we're representing them in an 'artists' table and a corresponding Artist class. Our artists have names and bios and, of course, ids. That means that our migration for creating our table looks like this (pre-versioning):
create_table :artists do |t|
t.column :name, :string
t.column :bio, :text
end
(If you're not familiar with migrations, they're the system Rails provides for representing your database structure and, especially, changes you make to it in code. They are super convenient. The Understanding Migrations tutorial on the Rails wiki is a great place to get started with them and, if you have any further questions, the Rails migration documentation is comprehensive. The sooner you start using migrations, the sooner you'll fall in love with Rails. Note: When you use migrations to set up your database, Rails adds ids automatically wherever they belong, which is why I didn't specify one here.)
Now, acts_as_versioned is going to mirror our artist data into a parallel table called 'artist_versions'. Each row of that table will represent a subsequent state, or version, of each of our artists. So we need to create the artist_versions table with a version column, a foreign key to tell it which artist its keeping track of (in this case we'll call that one 'artist_id'), and a column for each bit of data we want to version from our original model; for now, let's just do bio. All this adds up to a migration that looks like this:
Artist.create_versioned_table do |t|
t.column :version, :integer
t.column :artist_id, :integer
t.column :bio, :text
end
So the obvious thing to point out here is that we're using a new method "create_versioned_table" and that it's a method on the Artist model itself. In order for this to work, then, we're going to have to tell our Artist model that something's going on with versions. It's super easy; just one line: 'acts_as_versioned' within the Artist class. I like to keep it up near the relation declarations at the top so I don't lose track of it. Once we add that, the plugin does the rest of the work, adding a whole boatload of methods to our model including this migration method, create_versioned_table (and the converse we'll use in the down part of our migration: "Artist.drop_versioned_table"). Again, if you're doing this by hand, remember that our migration automatically adds an id to our table.
Assuming we've combined these two bits together into a migration and run it, we'll now have our database properly in place and we can start using all the methods the acts_as_versioned plugin has added to our Artist model.
Using the methods provided by acts_as_versioned
As you'll soon learn if you spend some time with the documentation, acts_as_versioned provides methods to do most things you can think of with it. I'm only going to go into detail here on the two that I think are most useful: revert_to, for rolling back to previous versions of your model and find_versions which is great for displaying old states of your data.
Let's start with find_versions. If @artist is an instance variable containing a particular artist then in our view we can do something like:
<% for version in @artist.find_versions.reverse %>
Version <%= version.version %> <br />
<%= link_to '(revert to this version)',
:action => 'revert_to_version',
:version_id => version.id,
:artist_id => @artist %>
<% end %>
This view code iterates over all the saved versions of our artist (starting with the most recent and heading backwards) displaying the version number and then providing a link to revert to that version. Other similar methods will let you find specific versions that meet given criteria or to get at just the particular attributes that you're keeping versioned.
Now, let's look closer at that link_to call. It's calling a custom controller action called 'revert_to_version', passing in the id of the version we want to revert to and the id of our artist. We want this link to revert the artist we've got stored in @artist to the version whose id we're passing in. The controller code necessary to do this will use the revert_to method provided by acts_as_versioned, like so:
def revert_to_version
@artist = Artist.find( params[:artist_id] )
@artist.revert_to! params[:version_id]
redirect_to :action => 'show', :id => @artist
end
All we're doing here grabbing ahold of our artist instance using the normal class 'find' method. Then we just call revert_to! (we use the conventional exclamation mark syntax to save as well as reverting) with the version_id as an argument and the old version of the artist's bio will now be saved in the right place in the artists table. One nice thing about using acts_as_versioned in this way is that it is non-destructive; all the more recent versions since the one to which we just reverted are still saved in our artist_versions table and we can always un-revert to them (if that's not too confusing).
And that is pretty much an introduction to acts_as_versioned. I've just scratched the surface of the subtle things you can do with it, especially when it comes on setting conditions for saving new versions. I've said it twice before, but a third time couldn't hurt: read the documentation. There's lots to learn.
Many thanks to Rick Olson, the author of acts_as_versioned, both for his great plugin and his rapid, clear, and helpful support when I was first trying to use it myself.
Tagged: rails, ruby, acts_as_versioned, wiki, plugin, gem, tutorialPosted by Greg at 12:36 AM | Comments (16)
February 1, 2006
Secret Structured Google Music Search
I do a lot of Google-searching for lyrics. I mean, a lot. I spend part of my day hand-screening suspicious looking new MFDZ uploads for piracy (for example, I don't think that cutegirl457 really made the song "50 Cent - In Da Club"). I've found that the best way to suss out more subtle pirated uploads (ones that don't provide the name of the actual artist or the song themselves) is to compose a Google search that includes the word "lyrics" and some of the words that you can pick out from the song (one big obstacle to this strategy is that you've got to find lyrics that aren't such a horribly common cliche as to be useless, which can be a challenge with some of the terribly cheesy music that gets uploaded). These kinds of searches usually return a page full of links to lyrics or fan sites and I can usually hunt down the song from there.
I do this so regularly that I was totally shocked last night when I idly searched for "M83" and the top hit took me off to a whole Google music universe that I never knew existed.
For each artist, they've got links to a list of their tracks, to their homepage, to the results of a Google image search about them, and to a Google group for discussing their work. The goodness goes all the way down to with album pages with track listings, links to reviews, and album art as well as track pages with links to various different download purchase options. (I wonder if Google is an iTunes affiliate and gets paid when people click on these links. If that's true it might make the universe explode.) Their catalog of who shows up seems to be pretty robust, too, insofar as my five seconds of test searches can show: Broken Social Scene was the only thing I tried that didn't work, Madonna, Metallica, The Arcade Fire, The Strokes, Philip Glass, Animal Collective, Juan Martin, and Madvillain were all in the system.
This seems like an incredibly helpful service and kind of an excellent model for ways of aggregating raw search data into meaningfully arranged structured data. Way better than the artificial user-entered system of Google Base. I mean this is all user-created data itself, after all. Just in this model people are able to create the data wherever they want all over the web and then Google can subtly combine it together into a useful service rather than forcing people to come to them to play.
I wonder if they do this for any other types of information. Books? Movies? Government transcripts? It kind of seems like they should. . .
Tagged: google, music, searchPosted by Greg at 4:59 PM | Comments (0)
A Note from the Content Usage Department
Another episode in the ongoing saga of CafePress's censorship of my Anti-Ketchup Shirt (previously discussed here and here): Today I called them up and after a rather long wait, I was finally transfered to their "Content Usage Department". The guy there told me that my design was in violation of Heinz Ketchup's "trade dress rights" which could include any similarity to the color, shape, or design of their packaging in my image. I tried to get more specific details -- was it the red color? the shape of the bottle? -- but the Cafe Press operator insisted that they "can't give legal advice". After much prodding, he finally suggested that I should try to change the chevron and oval shapes of the bottle's decals. I'm going to do that in the next day or so. I'll let you know if it sticks. . .
Note: after receiving a very nice email from Anthony Volodkin from Hype Machine, I agreed to take down access to my actual Hype Machine download script. He was worried that the script, if it caught on, could expose him to litigation from artists and cause his service technical problems. I've left my post on the subject up in a slightly altered form but now including (with his permission) some of Volodkin's comments on the subject. I think the whole thing makes for a relatively illuminating episode about the climate of confusion and fear in which anyone trying to do anything creative with online music distribution must operate.
Tagged: cafepress, censorshipPosted by Greg at 2:45 AM | Comments (1)


