Category: Work
svn:externals and the Versions svn Client

Update 2008-06-16: The latest beta of Versions (1.0b2 (31)) now allows you to set a different program for comparisons. I set mine to Changes, which I find a bit easier to work with than FileMerge.
I recently stumbled upon Matthew Weier O’Phinney’s explanation of svn:externals and how you can use it to mix stuff from multiple repositories in one project. This helped me when I was setting up a new project at work, since we keep a lot of core code in a centralized repository, but of course each project gets its own separate location. Matthew’s explanation should be included in the svn documentation, which (as he points out) lacks a simple example of how to use svn:externals.
The gist is to navigate to the folder into which you want to check out the external library, and then execute:
svn propedit svn:externals .
Within the editor session you need to add one line for every external library. The order goes: name of local folder, path to external library, like so:
extlib http://www.foo.com/path/to/external/libary
After you save and exit, an svn update on the directory will pull the external library into the folder you named in the property declaration.
I ran into one small issue — the propedit command requires that the environment variable SVN_EDITOR is set, otherwise it’ll bail. I added a line to my bash profile (export SVN_EDITOR=/usr/bin/vi) to point it to vi.
So Flash, the Registered TM Symbol, and a URLRequest walk into a bar…
At work we ran into a little issue on how to pass the registered trademark symbol ® from flash to the user's mail client via a mailto: call. We originally tried jamming it into the string like so:
-
var tmessage:String = "%26%23174%3B";
-
var _req:URLRequest = new URLRequest("mailto:?subject=hello&body=" + tmessage);
-
navigateToURL(_req);
We had hoped that the email client would receive the string and decode it properly, but instead it simply rendered it as ®. Searching the web for help was complicated because "register" and "registration" appear so often in forms and unrelated content.
In the end, some experimentation and reading of the documentation for the URLRequest class led us to this solution:
-
package
-
{
-
import flash.net.URLRequest;
-
import flash.net.*;
-
import flash.display.Sprite;
-
-
public class SendToFriend extends Sprite
-
{
-
-
private const MESSAGE:String = "This message is from dirtystylus®";
-
-
public function SendToFriend(): void
-
{
-
send();
-
}
-
-
private function send():void
-
{
-
var _req:URLRequest = new URLRequest("mailto:");
-
var variables:URLVariables = new URLVariables();
-
variables.subject = "hello";
-
variables.body = MESSAGE;
-
_req.data = variables;
-
_req.method = URLRequestMethod.GET;
-
navigateToURL(_req);
-
}
-
}
-
}
The URLRequest class has a data property, to which one can assign a URLVariables object containing stuff that we were trying to jam into the string as name/value url-encoded values. Assigning the variables to the data property also automatically urlencodes them before the URLRequest is sent, so in the final solution we just plugged the "®" symbol directly into the string, and it was urlencoded properly and emerged in the email body intact.
AllstateGarage.com

AllStateGarage.com is today's Site of the Day from The FWA. This is a project I've been working on for the last 7-8 months (on and off), so it's nice to see it pick up some accolades. The project was a lot of fun from the programming standpoint — we got to use RubyAMF to hook into the Rails backend, so there was a lot of digging into new technology.
The Squid and the Stallion has more on the project.
RubyAMF and AS2 (follow-up to AS3 + SSR, RubyAMF, and RESTful Rails)
A quick follow-up post to my tutorial on Flash and RubyAMF — RubyAMF can of course be used with AS2. Here's a short AS block showing a call to the index method of the PeopleController:
-
// remoting
-
import mx.remoting.Service;
-
import mx.remoting.PendingCall;
-
import mx.rpc.RelayResponder;
-
import mx.rpc.ResultEvent;
-
import mx.rpc.FaultEvent;
-
-
var peopleService:Service = new Service("http://localhost:3000/rubyamf/gateway", null, "PeopleController", null, null);
-
var peopleCall:PendingCall = peopleService.index();
-
peopleCall.responder = new RelayResponder(this, "onList", "onFault");
-
-
-
function onList(re: ResultEvent): Void
-
{
-
var people:Object = re.result;
-
for (var i = 0; i <people.length; i++) {
-
for (var j in people[i])
-
{
-
trace(j + ": " + people[i][j]);
-
}
-
}
-
}
-
-
function onFault(fault:FaultEvent): Void
-
{
-
trace("PeopleRest::onFault: " + fault);
-
}
AS3 + SSR, RubyAMF, and RESTful Rails
Update 2008-05-02: This example was written using SSR v1 and RubyAMF 1.3.4, and does not currrently match what you get with the latest versions. I'll be updating it shortly to reflect the changes against both SSR and RubyAMF.
Update 2007-10-25: A quick AS2 example using the Rails controller detailed below can be found here.
The RubyAMF blog recently linked to a good tutorial on using Flex, RubyAMF, and RESTful Rails. At Domani we've been using RubyAMF for a few projects recently, but without Flex. So here's a quick tutorial on using Flash, SSR (Super Simple Remoting), and RubyAMF with RESTful Rails in a local development environment. This assumes the usage of OS X, Locomotive, and MAMP — for some notes on setting that up I wrote a quick post on setting that up here. As always, many thanks to Aaron and the crew behind RubyAMF for their work and quick responses to questions.
Set Up Your Database
Create a new database called people_development. I used the phpMyAdmin interface running on the MAMP instance to do this.
Next, create a new rails app in Locomotive (Applications > Create New). I called the app people. The first thing I usually do is bring up the info screen for the newly-created app and change the port from the default set by Locomotive. I've noticed that the listing in the main Locomotive window will still display the default port even after you change it; to avoid this hit tab from the port field while you're in the info screen and it should refresh the display in the main window.
Modify the database config file (config > database.yml) to add two things:
port: 8889
socket: /Applications/MAMP/tmp/mysql/mysql.sock
Also set the password to "root", which is the default for databases served by MAMP.
Select the Rails app in the main Locomotive listing, and hit Command+T to fire up a terminal session in the context of the app you created. From the terminal session run this command (one line):
ruby script/generate scaffold_resource person first_name:string last_name:string
Among other things, this will create a migration that we can run to create a table for our app in the database. From the terminal run:
rake db:migrate
At this point you should have people table in the people_development database.
Install RubyAMF
From your terminal session run (one line):
ruby script/plugin install http://rubyamf.googlecode.com/svn/trunk/rubyamf
After RubyAMF finishes the install, start the people app in Locomotive. Verify that the RubyAMF gateway is live by pointing your browser to http://localhost:3000/rubyamf/gateway.
Next, verify that the app is live by pointing your browser to http://localhost:3000/people. Create a few people to populate the database with some entries.
Add AMF format response
Add a line for the amf format response in the people controller file (app > controllers> people_controller.rb)
format.amf { render :amf => @people }
The index method should read:
-
def index
-
@people = Person.find(:all)
-
-
respond_to do |format|
-
format.html # index.rhtml
-
format.xml { render :xml => @people.to_xml }
-
format.amf { render :amf => @people }
-
end
-
end
Set Up Your Flash App
Create a new FLA called people_rest.fla. Drag a DataGrid component onto the stage so that the library contains the DataGrid symbol and the DataGrid classes can be. You can delete the DataGrid off the stage after this.
Download SSR from here. Unzip the folder, and move the org folder to the same location as your FLA.
Create a document class called PeopleRest.as, and link it to your FLA as the Document class via the Properties panel. PeopleRest.as will establish a connection to the Rails app via the RubyAMF gateway and make a call to the index method.
PeopleRest.as:
-
package {
-
import flash.net.Responder;
-
import flash.display.MovieClip;
-
import fl.controls.DataGrid;
-
import fl.data.DataProvider;
-
import flash.events.Event;
-
-
import org.rubyamf.remoting.ssr.*;
-
-
public class PeopleRest extends MovieClip
-
{
-
private var rs:RemotingService;
-
private var peopleGrid:DataGrid;
-
-
public function PeopleRest()
-
{
-
init();
-
}
-
-
private function init(): void
-
{
-
peopleGrid = new DataGrid();
-
peopleGrid.x = 50;
-
peopleGrid.y = 180;
-
peopleGrid.width = 400;
-
addChild(peopleGrid);
-
-
rs = new RemotingService("http://localhost:3000/rubyamf/gateway", "PeopleController");
-
rs.addEventListener(FaultEvent.CONNECTION_ERROR, onConnectFault);
-
rs.addHeader('recordset_format',false,'fl9');
-
rs.index([], onList, onFault);
-
}
-
-
private function onList(re:ResultEvent=null):void {
-
var people:Object = re.result;
-
var dp:DataProvider = new DataProvider(re.result);
-
peopleGrid.dataProvider = dp;
-
}
-
-
private function onFault(fault:FaultEvent):void
-
{
-
trace("PeopleRest::onFault: " + fault.fault.faultString);
-
}
-
-
private function onConnectFault(fe:FaultEvent):void
-
{
-
trace("PeopleRest::onConnectFault() " + fe);
-
}
-
-
};
-
-
}
Compile the movie. You should see the person entries in your database in the data grid component on stage.
Adding Create/Update/Destroy Functionality
At this point you can add functionality to PeopleRest.as by adding input fields and buttons for triggering calls to the create, update, and destroy methods in the controller. Below are the edits to the Rails controller that are needed to support AMF responses:
Create:
-
def create
-
if @is_amf
-
@person = Person.new();
-
@person.first_name = params[:first_name]
-
@person.last_name = params[:last_name]
-
else
-
@person = Person.new(params[:person])
-
end
-
-
respond_to do |format|
-
if @person.save
-
flash[:notice] = 'Person was successfully created.'
-
format.html { redirect_to person_url(@person) }
-
format.xml { head :created, :location => person_url(@person) }
-
format.amf { render :amf => @person }
-
else
-
format.html { render :action => "new" }
-
format.xml { render :xml => @person.errors.to_xml }
-
end
-
end
-
end
Update:
-
def update
-
@person = Person.find(params[:id])
-
-
if @is_amf
-
@person=Person.find(params[:id])
-
@person.first_name=params[:first_name]
-
@person.last_name=params[:last_name]
-
else
-
@event = Person.new(params[:person])
-
end
-
-
respond_to do |format|
-
if @person.update_attributes(params[:person])
-
flash[:notice] = 'Person was successfully updated.'
-
format.html { redirect_to person_url(@person) }
-
format.xml { head :ok }
-
format.amf { render :amf => @person }
-
else
-
format.html { render :action => "edit" }
-
format.xml { render :xml => @person.errors.to_xml }
-
end
-
end
-
end
Destroy:
-
def destroy
-
@person = Person.find(params[:id])
-
@person.destroy
-
-
respond_to do |format|
-
format.html { redirect_to people_url }
-
format.xml { head :ok }
-
format.amf { render :amf => 'deleted' }
-
end
-
end
The final FLA, Actionscript3 document class, and rails controller file are here: people_rest.zip.







