Barefoot Development

Automating Rails deployment without Capistrano

Certainly Capostrano is the most elegant way to deploy your Rails apps, but here's an easy way to automate Rails deployment using just rync and rake. And the best part is that it borrows from a previous blog entry.

This first step is optional, but boy will it make your life easier. Start by setting up public key authentication between your local development machine and your server. We've covered this ground before, so just make sure you're doing it for the account on your server that you'd normally use to FTP to your Rails application.

The second, and final, step: using rync with rake. To see full coverge of this topic (or how to do it if you're developing on a Windows machine, see the HOWTO.

Add the following block to the Rakefile in your local application directory:

desc "Deploy basic application directories"
task :deploy => :environment do
dirs = %w{ app lib test public config}
onserver = "login@remotehost:/home/rails-app-directory/"
dirs.each do | dir|
`rsync -avz -e ssh "#{RAILS_ROOT}/#{dir}" "#{onserver}" --exclude ".svn"`
end
end

You'll need to change the onserver line to use your actual username and hostname. Then at the command line, change to your Rails application directory and run:

$ rake deploy

That's it. Enoy your new found productivity.

Sean Brown, Partner, Technology at Barefoot

Labels: , ,

Concerning Media Components and Cue Points

On a recent Flash project (version 7) with talking characters, it became necessary to start and stop animations at specific points during the playback of a sound file. We decided that the most efficient way to manage the calls was via CuePoints which are available in MX 2004 Pro through the Media components.

I placed an instance of the MediaDisplay component on the stage and initialized it thusly:


var myMedia = _root.my_media_component;
myMedia.autoPlay = false;

// Load some sound into the component
// which has been preloaded
myMedia.setMedia("some.mp3", MP3);

// Add CuePoints to the component
myMedia.addCuePoint("start", 7);
myMedia.addCuePoint("stop", 19);

// Create a Cue Point Listener object
var cuePointListener:Object = new Object();

// Call this method when a CuePoint is "heard"
cuePointListener.cuePoint = function(eventObject):Void {
// call the function with the CuePoint's name
handleCuePoint(eventObject.target.mostRecentCuePointName);
}

// Call this method when the sound is complete
cuePointListener.complete = function(eventObject):Void {
trace("I'm all done.");
// do some stuff
}

// Associate/attach the listers to the component
myMedia.addEventListener("cuePoint",cuePointListener);
myMedia.addEventListener("complete", cuePointListener);

// Method to handle each CuePoint
// @param myCue: The name of the "heard" CuePoint
function handleCuePoint(myCue:String):Void {
switch (myCue) {
case "start" :
trace("Start me up.");
// start some stuff
break;
case "stop" :
trace("Stop it, now.");
// stop some stuff
break;
}
}

// Now that everything is ready to go, let's play!
myMedia.play();
trace("The beginning.");


Okay, that was pretty simple -- the sound is playing great and the CuePoints are called in time. But wait, what was that? The sound finished and my CuePoints just fired again. Let's take a look at the output:


The beginning
Start me up.
Stop it, now.
Start me up.
Stop it, now.
I'm all done.


So, something is amiss between the completion of the sound and our listener "hearing" the complete. If we trace myMedia.playheadTime in the complete function, it returns 0. The Media component is automatically rewinding the sound when it finishes but before triggering the complete listener. Blockbuster would be proud. This wouldn't be so bad, but the act of rewinding fires the CuePoints as the sound scrubs back to 0. Luckily, the solution is simple. After a CuePoint is heard, just remove it:


// Call this method when a CuePoint is "heard"
cuePointListener.cuePoint = function(eventObject):Void {
// call the function with the CuePoint's name
handleCuePoint(eventObject.target.mostRecentCuePointName);
// now that the function above has been called, remove the CuePoint
myMedia.removeCuePoint(mediaStreamer.getCuePoint(eventObject.target.mostRecentCuePointName));
}


Not much to it, but the behavior of the MediaDisplay component is so odd that I just had to share.

Bobby Uhlenbrock, Application Developer, Barefoot

Labels: ,