The Blog

Posts from January 2009

Jan 12

Porting Legacy Applications to Modern Systems

By Jason LaPorte

(Or, an adventure in pain!)

Let me preface this little article by saying I did not write the app I am now porting to our new network. I know noting about its specific intricacies, and furthermore, I know nothing specifically about gettext, filecolumn, or attachmentfu. So, I dove into this project with a sort of wanton abandon that is fairly characteristic of much of the work I do. Any obviously stupid mistakes below thus really happened.

Let me also preface this with the fact that this Rails app is old. Version 1.2.3 old. So, as always, YMMV.

Finally, I really wish attachment_fu had proper documentation.

Installing GetText 1.10.0

We don’t really like GetText around here, but, at the time, it was the only option. Getting it running off of a local copy (so I wouldn’t have to pollute other projects with it) was less difficult than I expected. Go to your vendor/gems directory and issue: gem unpack gettext This assumes you have gettext 1.10.0 installed locally. I think adding a VERSION=1.10.0 will handle it if you have multiple gettext versions laying around. After that, I merely needed to add the following to config/environment.rb to make sure the gem loaded: GETTEXTGEMDIR = “#{File.expandpath(RAILSROOT)}/vendor/gems/gettext-1.10.0” $LOADPATH.reject { |path| path =~ /gettext/ } $LOADPATH << GETTEXTGEMDIR $LOADPATH << File.join(GETTEXTGEMDIR, ‘lib’) $LOADPATH << File.join(GETTEXTGEMDIR, ‘ext’, ‘gettext’) require File.join(GETTEXTGEMDIR, ‘lib’, ‘gettext.rb’) Ta-da!

Replacing FileColumn With AttachmentFu

After doing the above and booting up a test server, I get the following fun error: no such file to load – RMagick There is no way I am ever installing RMagick onto our nice, new, beautiful infrastructure. I want things done right, here. I also don’t want to have to be paranoid about memory leaks, especially for legacy applications. So, we have to get rid of it.

This problem is caused by our use of filecolumn, an old-but-effective way of easily adding file uploading support into a Rails app. The modern _de facto standard for this seems to be attachment_fu, which uses the much-better-designed ImageScience instead of RMagick.

So, let’s gut this fish.

Remove File_Column.

$ svn rm vendor/plugins/file_column

Install ImageScience.

$ sudo apt-get -y install libfreeimage3 libfreeimage-dev $ sudo gem install image_science

Install Attachment_Fu.

$ script/plugin install http://svn.techno-weenie.net/projects/plugins/attachmentfu/ After installing attachmentfu, I powered back up script/server to check the next fun error: undefined method `filecolumn' for Clan:Class This is expected: filecolumn is gone, so the app can’t possibly know what a file_column is. Now, we have to get into the nitty-gritty of tweaking the app.

Adapting the Application to Attachment_Fu.

Let’s start in app/models/clan.rb, to which I was directed by the aforementioned error: $ grep filecolumn app/models/clan.rb No output. The words filecolumn don’t appear in that class. Not what I expected.

In the time-honored tradition of killing a cockroach with a shotgun, I then turned my sights on the entire app directory: $ grep -R filecolumn app The only results that turn up happen to be in app/views, leaving me perplexed. A quick conversation with the project lead informs me that this application uses “skeletons”, or appableplugins, which was an absolutely horrible idea that we thankfully no longer use. In essence, it allows you to wrap pieces of functionality into a self-contained plugin, which is duck-punched onto your application when it starts. It is great from a code-reuse perspective, but horrible from a KISS and maintenance standpoint, which is why we no longer use it.

Except that every now and again, it comes back to bite you in the ass when you least expect it.

Anyway, checking the skeletons quickly turns up what I am looking for: $ grep -R filecolumn vendor/skeletons/clanskeleton vendor/skeletons/clanskeleton/app/models/clan.rb: filecolumn :avatar_image, :magick => { :size => “64x64!”} So, there is where I have to make the first incision. I changed it as follows:

filecolumn :avatarimage, :magick => { :size => “64x64!”}

# validatesfilesizeof :avatar_image, :in => 0..40.kilobytes

hasattachment :contenttype => :image, :storage => :filesystem, :maxsize => 40.kilobytes, :resize_to => ‘64x64!’

validatesasattachment Time to restart the server and try again. (I don’t honestly expect it to work: there are (at least!) a lot of views that use file_column methods. It is easiest to just hack at them one at a time until everything works, though!)

I spent the next couple hours digging through the innards of attachmentfu, only to discover that I had written :filesystem, above, instead of :filesystem (note the underscore). Make sure you spell things correctly, people, or you’ll be in for a world of self-induced hurt. (The above snippet shows things the correct way, so you, my beloved internet, won’t inadvertently copy-and-paste yourself into hell.)

Once I had properly spelled everything, though, I met with success: the front page of the site loaded! Clicking on just about anything yielded a failure, as anticipated: undefined method `urlforfilecolumn' for #<#Class:0x7f7d7f3006c0:0x7f7d7f300670> The views didn’t work, but the fix wasn’t horrible. Generally speaking, I simply searched and replaced the following: urlforfilecolumn(X, ‘avatarimage’) with: X.publicfilename Also, along with this, I modified the clan table’s SQL schema to accomodate attachmentfu: ALTER TABLE clans CHANGE avatarimage filename VARCHAR(255) DEFAULT NULL; ALTER TABLE clans ADD (contenttype VARCHAR(255) DEFAULT NULL, size INT DEFAULT NULL, width INT DEFAULT NULL, height INT DEFAULT NULL); Thankfully, this was pretty easy to do, since the clans table was very small for this particular title. If it were larger, I would create a separate table and do a SELECT * FROM clans INSERT INTO clanstemp sort of thing. (Yes, I know that it is very evil to hack the SQL directly instead of using migrations. This app is sufficiently old that I cannot guarantee that its migrations even work; I’m already spending a lot of time trying to port this app, I don’t want to spend much more trying to make it perfect. If it weren’t a legacy application, however, I would do things a bit more cleanly.)

At this point, virtually everything on the site worked. Avatars (once moved to the proper new directories) showed up just fine. The only remaining error came from trying to upload a new avatar image. Solving this essentially boiled down to a complex series of hacks to blend attachmentfu into the remainder of the existing codebase; none of which were particularly complex or interesting (generally involving changing the names a form parameters from the previous :avatarimage to the new :uploadeddata, like this:) <%#= filecolumnfield ‘clan’, ‘avatarimage’ %> <%= filefieldtag :uploadeddata %> Doing all this left me with one final application error, received when actually performing the file upload: Content type is not included in the list content type can’t be blank Validations are complaining. After tinkering with attachmentfu’s code for a while, I discover that there is a method that attachmentfu adds to your ActiveRecords (uploadeddata=), which sets content_type and other miscellaneous variables. And, clearly, this wasn’t getting called.

Turns out I was getting bitten by multipart forms. By tossing a quick puts params.inspect into the code, I quickly saw where my problem lay. Notice the following bit from our clans controller’s update method: @clan.updateattributes(params[:clan]) Unfortunately for me, the uploaded data is in params[:uploadeddata], and not in params[:clan][:uploadeddata]. While there’s a cleaner fix, the following hack suits our purposes fine and allows me to finish up this 20-hour hackfest: params[:clan][:uploaded_data] = params[:uploadeddata] So, after all of this code mangling, we finally had our app ready to move to a new, lighter-weight infrastructure, ultimately saving us money. A very frustrating few days, but they will pay for themselves. All that remains is integrating into a new infrastructure, and switching over the DNS.

Jan 5

The Misunderstood Art

By Christian Arca

Note: This editorial does not express the feelings of Agora Games as a company, and is solely the opinion of the author.

Art, by definition is the expression or application of human creative skill and imagination typically in a visual form. A video game by definition is a game played by electronically manipulating images produced by a computer program on a television screen or other display screen. By both definitions of each word, video games may be considered a form of art. The computer program which electronically manipulates images on a display screen must be created by a human. This human, must apply creative skill to create such images as well as the manipulation of images, images being a visual form. The definition of art clearly states that a the expression of human creativity is typically in a visual form, which video games by definition clearly do. Therefore, technically disregarding all personal opinions, culture, and other variable elements video games by definition are art. 

I strongly believe that video games are a form of art. Video games in fact include almost every single element of art there is. Let us analyze one of the most “accepted” forms of art in society which is included in video games, literature. Many video games these days staff writers to create a story for the particular game at hand. In fact, many game journalists include the quality of story within their review of a game. How much different is that then the New York Times reviewing a new novel? In fact, with games currently averaging about 20+ hours of gameplay it is safe to say that a well developed short story, or even a novel may be included within a video game. 

While one might argue that the quality of story is rather poor does this not also hold true to several novels? Sure one might say Gears of War had very poor dialogue and a rather poor story progression however, other titles provide players with a very well developed story and dialogue. An example of such a game in my opinion would be Mass Effect, in which a character Lorik Qui’in after you the player say, “I will let you go.” states the following, “Let me go? Do humans consider conversation a form of imprisonment? That would explain why so few of you are willing to sit down and talk…” This dialogue being directed at my character, therefore an extension of myself since I am controlling the character. The communication is not passive in nature, it is directed at myself and therefore directly impacts my thoughts and feelings on a personal level since it is I who am controlling this character, I who am a living breathing human being. The character being addressed is not print on a paper, it is my character, my choices which insinuated this response from Lorik. 

This method of immersion can not be achieved through a novel. Koster, touches on this subject by saying, “…games are very fundamental and powerful learning tools. It’s one thing to read in a book that “the map is not the territory” and another to have your armies rolled over by your opponent in a game. When the latter happens, you’re gonna get the point even if the actual armies aren’t marching into your suburban home.” Furthermore, video games are an accessible medium to any given audience. That is to say, while a certain skill is required to play a video game, both a novice gamer and an experience gamer will both be able to direct their in game experience into the subconscious, intuitive mind. However, in the art of literature, an experienced reader will gain a better experience into their subconscious, intuitive mind rather than a novice reader. 

Koster, in fact hits on this topic by comparing literature to games. “Consider the key differences between something like a book and different kinds of games. A book can do the logical conscious part of the brain pretty well. And really good readers have an ability to slurp that info directly into the subconscious, intuitive mind. But what a book will never be able to do is accelerate the grokking process to the degree that games do, because you cannot practice a pattern and run permutations on it with a book.” In essence, within a book you do not have the option to experience a scenario or event which you caused and observe the various outcomes of your actions. 

In addition to providing players with an immersive experience through literature, video games also provide creative visual elements which allow players to continue their immersion in a video game. Furthermore, combining both visual and literary elements provide the player with a unique experience which can not be simulated by any other form of art. Artists, art directors, and creative directors work in unison to give players a certain “feeling” or evoke a certain “emotion” while playing the game. 

The complexity and infancy of video games make the legitimacy of video games as a medium of art rather difficult to swallow. However, many other forms of art when first introduced went through the same life cycle. From the 1900s to the 1940s on screen films went from short black and white movies to full length hour long movies fully dressed with color and sound. As video games begin to mature and designers, programmers, artists, and musicians begin to become more experienced within this form of art I can only hope that the social stigma and media literacy problem evolves as well. One day I truly believe we will be walking through a museum watching interactive displays featuring some of the greatest forms of art, video games.