git, Braid and MacPorts 1
It is common to have others code lurking in the vendor directory of your project. Many have switched to using piston on the Subversion side of life, and braids fills the same gap over on the git side, but can be used to freeze either subversion or git repos.
Braids (like much of git) is still a little wet behind the ears in the usability department, so don’t expect it to hold your hand through the process just yet. An example from today, I got the this message:
2008-03-28 12:26 $ braid add http://async-observer.rubyforge.org/svn/async_observer --type svn vendor/plugins/async_observer
braid: Creating work branch 'braid/track'
braid: Checking out work branch 'braid/track'.
braid: Adding svn mirror from 'http://async-observer.rubyforge.org/svn/async_observer' into 'vendor/plugins/async_observer' using local branch 'braid/svn/vendor/plugins/async-observer'.
braid: Got remote svn revision: 19.
braid: Setting up remote branch and fetching data.
braid: Error occured:
braid: Resetting braid/track to d38137af1951a32f0d217a2c77f3d553890576ba.
braid: Checking out branch 'async'.
braid: An exception has occured: ()
Its those empty parentheses that are really informative ;-) It turned out that I installed git via Macports, then manually installed a newer version in /usr/local/bin. I then had changed my path to have /opt/local/bin behind /usr/local/bin. That worked just fine until last week when some other (not SCM) thing broke and I switched them back (forgetting why I’d switched in the first place). The bottom line is the error above is caused by not having subversion bindings installed right in git. Macports now has a better version to use, so I blew away the custom compiled one and just updated my Macports to be right. I found the comment about subversion bindings at the bottom of this excellent post
Gnu Screen is Awesome
I like to tweak my workflow all the time. I often change something for a week, try it out and then either change back or move on to something else. I got used to tabbed terminals in Linux and even had mrxvt working under cygwin, so when I came to the Mac not having tabs in the Terminal bugged me. I tried several solutions and settled on iTerm. Life was good for a while. I got tired of using nohup to run long emerges in the background on the servers, so I learned about gnu screen. That led me to wonder if you could get labels for the various windows, and sure enough the hardstatus line will happily act as a tab bar for you as long as your not fond of clicking to change tabs (in the terminal? You shouldn’t be). I had seen Visor and thought it was cool, so I tried it out for a while with Screen to give me tabs. There where some problems with Visor interacting weird with screen, so back to iTerm I went. When I updated to Leopard, I moved to Terminal.app, since it had tabs now. But it turns out I had grown to love the “Do what I’m typing in all tabs” feature. So I went back yet again. But iTerm didn’t work as well for me under Leopard as it did under Tiger. So I got over not having the do in all tabs feature and lived with Terminal.app. Recently I realized that I was spending a lot of time ‘setting up’ my work environment. The steps go like this:
- Go to tab 1
- Stop script server
- Change directory to new project
- Restart script/server
- Go to tab 2
- Stop autotest
- Change directory to new project
- Start autotest
- Go to tab 3
- Change directory to new project
- Run sake gitrdone
- does svn up or git pull (depending on .git file)
- does rake db:migrate
- rake db:test:clone
- rake spec:db:fixtures:load
- rake notes
- svn status | grep \? or git status
- mate .
So yeah, thats a lot. Way to much to do manually (even with the awesome sake script). So I started looking around the web to see what others had done. I found this OnRails article which seems to have met with some serious frustration, and the associated links. The outlook did not look good. So back to iTerm… again. That still wasn’t satisfying. Then I stumbled across something (I don’t remember what) that mentioned screens -X and its -X stuff command. The way it works is this. -X tells screen to do one of its internal commands from the outside, so screen -X next would change the focused window by one, either form inside the screen session or from outside of it. stuff ‘do this’ is the screen command that sends ‘do this’ to the current screen. That got me thinking… what if screen could be used to do all the magic that Apples sucky Applescript in Terminal.app can’t? So I started to fiddle and hack and read. Screen’s documentation is the suck, though I did find this source This led to the creation of the following script
#!/usr/bin/env ruby
def find_or_create_by_id(window_id)
File.delete('/tmp/current_screen') if File.exists?("/tmp/current_screen")
`screen -p #{window_id} -X hardcopy /tmp/current_screen`
sleep(0.1)
unless File.exists?("/tmp/current_screen") && File.size("/tmp/current_screen") > 0
`screen -X screen`
return find_or_create_by_id(window_id)
end
return window_id
end
i = 0
find_or_create_by_id(i)
`screen -p #{i} -X stuff ''`
`screen -p #{i} -X stuff 'cd #{ARGV[0]}; ruby script/server --debugger\n'`
i += 1
find_or_create_by_id(i)
`screen -p #{i} -X stuff ''`
`screen -p #{i} -X stuff ''`
`screen -p #{i} -X stuff 'cd #{ARGV[0]}; sake git_r_done; autotest\n'`
i += 1
find_or_create_by_id(i)
`screen -p #{i} -X stuff 'cd #{ARGV[0]}; mate .\n'`
I drop that into my bin dir under the title hack and now as long as screen is running I can do hack ~/work/project/trunk and off I go. It is worth noting that since it sends a kill to whatever is running in the first and second screen tabs, you have to run it from either outside screen or from some tab other than the first or second.
I also found this article that showed my some other features of scripting screen and allowed me to write a script I call all which takes whatever you type after it and sends it to all open tabs in a screen session.
I’ve coupled this with my .screenrc file and the new version of Visor lets me have simple drop down terminal with all the power I need.
One Chat to Rule Them All! 1
Well… almost ;-) I’ve been using the Google Talk in iChat or Adium (and then back to iChat) for some time now. Back in August I read this Lifehacker article and implemented it. I’m a total clepto when it comes to chat logs… I keep everything I can usually. When your done you have the ability to route all of your various IM accounts (AIM, Yahoo, MSN, Jabber) through one Google Talk account. I have my AIM and Yahoo buddies actually on again now. And whats really cool to me is all the logging takes place in gMail, so when I think: “what did SoAndSo say about the bananas again?” I just search for SoAndSo and bananas in gMail and I never have to think about whether it was an email conversation or a chat one. It makes me happy =-) Also there are lots of other cool Jabber services out there that this can be used with, so that is cool. I tried doing IRC over jabber for a while, which worked, but doesn’t have enough features for me once it goes through the limitations of the gTalk service (notice these are gTalk limits, not Jabber limits).
There are two major caveats to this approach. The first is that you can’t do direct connect, file transfer, voice or video with folk on other networks this way. The other is Skype doesn’t have any transports (to anything, the bastards). Given that iChat does pretty good audio, video and now desktop sharing and that most of my Skype people are also on either gTalk or AIM, you may be seeing me less and less on Skype.
Working Daze 1

I generally love this comic by John Zakour and Kyle Miller, and when I saw the one from Halloween I just knew it couldn’t be too hard for Anna to replace the y in Roy with a b. If anyone is upset about me putting this up (I make no claim that this work is mine) feel free to email me and I’ll take it down. In the mean time I hope it gives you as good a chuckle as it gave me. And thanks go to Anna for the Photoshop job.
Capistrano Talk
Here are the slides from the capistrano talk I gave as SDRuby.com. They are available in ODP and in PDF. The slides are licensed under a Creative Commons Attribution 3.0 United States License.

These are not Jordan’s talk from last night (2007-11-2), but mine from a few months prior. I’ll post a link to the podcast once that is up.
Sphinx and Ultrasphinx: And Eye on Search 5

Got into Sphinx this last week. It was cool to try the new Russian hotness of Rails search. The toughest part seems to be figuring out which of three Rails plugins to use. Your options are:
This plugin by Evan Weaver seems very complete. It has field weighting and faciting, field merging and aliasing (allows you to have columns in associated models joined in the index). It is compatible with will_paginate, which is cool and has spell checking (always a plus for me).
Because ActsAs is cool ;-) This plugin doesn’t generate the configuration files for Sphinx the way Ultra does, but if you decided you wanted to roll your own indexing config anyway it probably provides just enough with out being anywhere near as much code. Also it was this plugins main page that I used for installation instructions the first time. I’ll put some below, but if you use these beware that they link to version 0.9.7-rc2 of Sphinx, which is not the most current stable version (and won’t work with Ultrasphinx)
Sphincter This is Eric Hodel’s entry into the Sphinx party. I’m not sure exactly how this compares to Ultrasphinx, and may try and get a project running with it in the future, just to know. It does look like testing the search portion of your code has been well thought out though, which I really like to see. Ok, the name grabs attention, giggle giggle whatever. Does a name like this make waves? Sure. Does it keep some people (especially clients) from liking it? Sure. I don’t know if Eric thinks keeping the more PC people away is a feature or what, but to me picking a name just to be sensational isn’t really worth much. I love puns and all, but it takes a way from people talking about the merits of your work.
Getting started is pretty easy (for OS X or Linux):
curl -O http://sphinxsearch.com/downloads/sphinx-0.9.7.tar.gz
You could also grab the latest from the Sphinx site. Replace the version number below if you do.
tar zxfv sphinx-0.9.7.tar.gz
cd sphinx-0.9.7
The next step is the configure. This needs to know where the libraries and header files for mysql live. Below is the line I used for OS X running a MacPorts based install of Mysql. We had some problems on another Mac getting to install with a Mysql installer based version, we finally ended up making a symlink in the /usr/local/lib and /usr/local/includes directory to /usr/local/mysql. The bottom line is that you’ll need to change the two configure options to suite your install.
./configure --with-mysql-includes=/opt/local/include/mysql5/mysql --with-mysql-libs=/opt/local/lib/mysql5/mysql
make
sudo make install
Now we also need to install our chosen plugin into our Rails app. From your Rails root, using piston
piston import svn://rubyforge.org/var/svn/fauna/ultrasphinx/trunk vendor/plugins/ultrasphinx
cd vendor/plugins
ruby ultrasphinx/install.rb
Usage is also simple
All you have to do is open up your model and add an is_indexed line like this
is_indexed :fields => ['name', 'description']
A great thing about Ultrasphinx is that it is easy to get at multiple fields associated with a certain model. For instance this example has the relationships Bin has_many Services through BinsServices, Services has one Provider. We want the Bin name and description to be indexed, but we also want matches on Service name Service description and provider name to return the associated Bin. That ends up looking like this:
is_indexed :fields => ['name', 'description'],
:include => [{:class_name => "Service", :field => 'description', :as => 'service_description',
:association_sql => "JOIN (bins_services, services) ON (bins.id=bins_services.bin_id AND bins_services.service_id=services.id)"},
{:class_name => "Service", :field => 'name', :as => 'service_name', :association_sql => ""},
{:class_name => "Provider", :field => 'name', :as => 'provider_name',
:association_sql => "JOIN (providers) ON (services.provider_id=providers.id)"}]
Notice that the second field for Service has to have its own line, and that the association_sql must be declaired, but be empty string (otherwise we JOIN twice and get an error). Also notice that the Provider JOIN starts off where the Service JOIN left off, it doesn’t start at Bin, but goes from Service. It seems like this could be cleaned up a bit with some changes to the parser, but all in all it proved a workable solution for all the cases we had.
Next up we need to see what the search code looks like. We can just call Ultrasphinx::Search like so:
@search = Ultrasphinx::Search.new(:query => "My query string")
@search.run
@search.results
Now lets get the index run and the search daemon going. Note that these three commands can all be run at once with rake ultrasphinx:boot or its alias us:boot
rake ultrasphinx:configure
rake ultrasphinx:index
rake ultrasphinx:daemon:start
That about raps up our look at Ultrasphinx. One quick note, we ended up not using any of this code :-( The app in question is slated to run on Media Temple, and their grid structure precludes running background processes like this. We ended up moving everything to ActsAsSolr, a change that is worth looking at, but is the subject of another entry.
Test from mobile
Test of s60 blog client blogplanet
it works!
Nested Resource Check List
I want to get back to this and make a generator for it, but for now here is my checklist based mostly off of this post.
- Create resource scaffolding ruby script/generate scaffold_resource Nestee title:string body:text
- ruby script/generate scaffold_resource Nester body:text
- Setup relationships in models
- Modify Routes
- Modify controller of nested resource
- add before_filter to assign nestee
- include @nester = @nestee.nester.find(params[:id]) if params[:id]
- ammend the *_url calls with @parent
- remove all instances of Nester.find(params[:id])
- scope the nested class finder_all with the nestee
- add before_filter to assign nestee
- Modify the views of nested resource
- edit.rhtml - formfor, linkto ‘show’
- show.rhtml - link_to ‘edit’ (at bottom)
- index.rhtml - linkto ‘edit’ and linkto ‘destroy’
- Provide links to nested resource
Born and Bread to Develop 3
I often tell people that I was raised to be a developer. My dad is a Systems Engineer at NASA, and has worked there in either software or systems my whole life. People hear this and often misconstrue it to mean that Dad pushed me into computers at an early age. That is really not true. He was there to listen, and would answer questions when I asked, but he never said things like “When you grow up you’ll make a great programmer”.
A few of my friends have been after me lately, asking about how my dad passed on the art of programming to me. The answer is that he didn’t… At least not directly. We played games together instead.
When I was a toddler, I would play Star Command with my dad. He would control the star ship and I would press the buttons on the Atari 800 keyboard to bring up the map, change weapons etc. Sneaking up from a nap on Saturday afternoons and hoping Mom didn’t catch us is one of my earliest memories. When I got older (Junior high/ High school) we played RPGs like Ultima 7 together. One person would “drive” while the other worked on mapping, high level ‘whats next’ stuff and such. I learned logic and reasoning this way. I also learned how to draw a mean flow chart… after all that is all the maps from Zork really are.
It occurred to me this morning that this was truly “Pair Video Gaming” Not just two people laying against each other or even cooperative games like MMORPGs, but Pair gaming in the same vain as Pair Programming. The freedom of the non-driver to work ahead on the ‘big picture’ while the driver focuses on the detail, is exactly the benefits that XP teaches.
So playing games together taught logic and reasoning, taught pair programming, testing and other good techniques, but there is one more aspect of this learning method had over “Heres a programming book son, let me know when you’ve finished it”. We spent time together. That is huge, so I’ll say it again. Even as a teenager I spent a lot of time hanging out with my dad. I think like a computer programmer not just because I am one or because I was raised by one, but because I was mentored and befriended by one from a very early age. I tackle problems by picking them apart into little tasks and solving each task one by one, because I saw proof over and over again that it could be done that way.
When it came time for me to put in college apps, my dad, very proud that I had chosen Computer Science, sat me down. He wanted to be very certain that I knew, if CS didn’t make me happy, that I should find whatever vocation does and do that instead.
It wasn’t pressure or sneaking CS books on my book shelf or any of that kind of thing. It was being willing to help when I asked for it, to spend time with me. Sure, I’m probably one of the few people who at 25 has a well thumbed first addition Kernighan and Ritchie, but that was because I asked to borrow it and was told I could have it.
Older posts: 1 2
