nyerm http://blog.nyerm.com Life goes by pretty fast Mon, 16 Nov 2009 10:41:50 +0000 http://wordpress.org/?v=2.7.1 en hourly 1 Making public key SSH connections in Cygwin http://blog.nyerm.com/2009/08/04/making-public-key-ssh-connections-in-cygwin/ http://blog.nyerm.com/2009/08/04/making-public-key-ssh-connections-in-cygwin/#comments Tue, 04 Aug 2009 19:45:33 +0000 lonnon http://blog.nyerm.com/2009/08/04/making-public-key-ssh-connections-in-cygwin/ Here’s a trick I had to relearn to get SSH to make a key-authenticated connection in a Cygwin environment. I have my Windows user directory (c:\Users\lonnon) set as my home directory via the HOME environment variable, but many Cygwin programs, like SSH, look for the home directory within Cygwin’s own bizarre little directory structure, at c:\cygwin\home\lonnon (/home/lonnon in Cygwin’s file space). Because my .ssh directory, which contains my key files, isn’t located where Cygwin wants it, I get a “Permission denied (publickey)” error when attempting to connect.

The solution was so simple, I forgot that I’d already done it on my older laptop. I removed the home directory provided by Cygwin and replaced it with a symbolic link to my “real” home directory.

  > cd /home
  > rm -rf lonnon
  > ln -s /cygdrive/c/Users/lonnon lonnon

Yay, presto, it works. Both ssh and scp can find my keys now.

]]>
http://blog.nyerm.com/2009/08/04/making-public-key-ssh-connections-in-cygwin/feed/
Running afoul of Windows NTFS stream security http://blog.nyerm.com/2009/08/04/running-afoul-of-windows-ntfs-stream-security/ http://blog.nyerm.com/2009/08/04/running-afoul-of-windows-ntfs-stream-security/#comments Tue, 04 Aug 2009 18:48:46 +0000 lonnon http://blog.nyerm.com/2009/08/04/running-afoul-of-windows-ntfs-stream-security/ This is the kind of stuff that drives me absolutely bonkers about Windows. I run Console as a command prompt replacement, and I just installed it on a brand new Vista machine. Unfortunately, every time I ran it, I’d get a security warning similar to this:

Unbeknownst to me, Windows helpfully attaches security information to files that you download, using an obscure NTFS streams mechanism about which I’d never heard. As long as this file was flagged as a potential risk, opening it would bring up the blasted nanny dialog, regardless of how many times I unchecked the box for “Always ask before opening this file.”

Popping open the properties for the console.exe file revealed a Security section that I’d never seen before, at the bottom of the dialog:

Unfortunately, clicking the Unblock button did nothing. And to add further insult, re-opening the properties revealed that Windows had silently undone my handiwork; the Unblock button was still there.

Much googling later revealed that I might be able to hack around this by copying the file to a non-NTFS partition, then copying it back. I did exactly that, copying it over to my Ubuntu server and back. The Unblock button was still there, but this time when I clicked it, it stayed gone. Problem solved.

The most annoying part of this morning’s jaunt into overprotective Windows security is that I can’t reproduce the problem. At all. I’ve re-downloaded Console in an attempt to recreate the error and get some screen shots for this blog post, but the newly downloaded executable behaves as if it’s always been on my hard drive. No security messages, no silly Unblock button, no evidence at all to support the last hour or so of frustrated clicking and searching. When I say that Windows makes me crazy, this is exactly what I’m talking about.

]]>
http://blog.nyerm.com/2009/08/04/running-afoul-of-windows-ntfs-stream-security/feed/
MySQL with Ruby under Cygwin http://blog.nyerm.com/2009/08/03/mysql-with-ruby-under-cygwin/ http://blog.nyerm.com/2009/08/03/mysql-with-ruby-under-cygwin/#comments Tue, 04 Aug 2009 00:54:35 +0000 lonnon http://blog.nyerm.com/2009/08/03/mysql-with-ruby-under-cygwin/ I have a brand spanking new laptop, and it needs a brand spanking new Ruby on Rails development environment. This being Windows, the only sane way to get a good pile of development tools and a usable shell is to install Cygwin. I’ve had it set up on the old laptop for a while now, and while it’s slow (mostly because that laptop is old, and therefore slow), it works well as a Rails environment.

Of course, every time I set this up there has to be a snag in the process, right? Rails hasn’t shipped with MySQL support for a few versions now, so it’s necessary to manually install a MySQL gem. Unfortunately, there aren’t any library files available for Rubygems to compile against, because the Windows version of MySQL doesn’t install any. If it did, they’d be somewhere Cygwin wouldn’t know about them, anyhow; the MySQL folks don’t officially support Cygwin.

So, to get the library, I downloaded the MySQL source, popped open the tarball, and ran through the usual configure, make, make install routine. The only difference is the addition of the --without-server flag for configure; there’s no need to build the whole server, because that’s already been installed using the Windows binary installer.

Unfortunately, it wasn’t that easy, because Cygwin doesn’t ship with the sys/ttydefaults.h header file. I’ve read forum conversations that imply you can get the file by installing the GNU readline package, but that didn’t fix the problem. Fortunately, you can snag the file from another unix (or grab the copy here), drop it into the /usr/include/sys directory (Windows path: c:\cygwin\usr\include\sys), and that makes the compiler happy.

  > ./configure --without-server
  > make
  > make install

After that all finishes (and it takes a while, even on the swanky new speed machine), I installed the Ruby mysql gem.

  > gem install mysql

Kind of anticlimactic, really. Even the “building native extensions” part of the gem installation is orders of magnitude shorter than compiling MySQL. And a whole hell of a lot quicker than tracking down why things won’t compile. It’s been a long day of watching a console spit reams of text at me.

]]>
http://blog.nyerm.com/2009/08/03/mysql-with-ruby-under-cygwin/feed/
Fixing git pre-commit hook woes http://blog.nyerm.com/2009/04/23/fixing-git-pre-commit-hook-woes/ http://blog.nyerm.com/2009/04/23/fixing-git-pre-commit-hook-woes/#comments Fri, 24 Apr 2009 02:02:43 +0000 lonnon http://blog.nyerm.com/?p=562 I’ve had something strange occur when attempting to commit changes to a Git repository located on a flash drive. A pre-commit hook, which is a script Git runs before the git commit command does its thing, prevents me from committing files until I’ve removed whitespace characters from the ends of all the lines in the files. Cleaning out such whitespace is good practice if you’re working on a project and you submit your changes as patches; the patch mechanism has a tendency to barf on lines that contain trailing whitespace.

My problem is that not only am I not working on a project where I submit patches, some of the Rails generators create files that contain trailing whitespace (I’m looking at you, RSpec). When I found that the rake db:migrate task adds trailing whitespace to the schema.rb file, I nearly went ballistic. I’d be okay with keeping the whitespace out of my own code, because I’m just OCD enough to enjoy the exercise, but having to fix code generated by automation tools just pisses me off.

To add to the aggravation, the pre-commit hook didn’t seem to run when I was committing to Git repositories on the hard drive of my Mac. I ran afoul of the hook only when committing to a repository on the flash drive or on my Windows laptop.

I got fed up with it enough today to do a bit of digging into the guts of Git. The pre-commit script is created when git init sets up a new repository, and the script is located in a project’s working directory under .git/hooks. The pre-commit script’s comments indicate that it’s designed to prevent trailing whitespace from getting into files destined for patches. The comments also mention the following:

To enable this hook, make this file executable.

Aha! Now we’re getting somewhere. I checked the file permissions, and sure enough, the file is executable in a repository created on the flash drive. However, it isn’t executable in a repository created on the Mac’s hard drive. Digging a bit deeper, I found that the original copy of pre-commit comes from /usr/local/share/git-core/templates/hooks, where the file is also not executable.

It looks like git init loses the file permissions when it copies everything from the Git templates directory over to the flash drive, thereby resulting in files that have full permissions enabled. This makes sense, given that the flash drive is FAT32-formatted; the filesystem doesn’t support Unix-style execution permissions. My Windows laptop has the same problem.

Finally knowing what causes the problem, I defused it by renaming pre-commit in the templates directory to pre-commit.patching. Now if it’s copied with full permissions, it won’t matter, because Git’s looking for a file named pre-commit. I may at some point need to re-enable the hook if I start submitting patches to someone else’s project, but in the meantime, for the majority of work that I do in my own one-man repositories, I’m no longer bothered by an over-protective pre-commit hook.

]]>
http://blog.nyerm.com/2009/04/23/fixing-git-pre-commit-hook-woes/feed/
Deploying a Sinatra app on Dreamhost http://blog.nyerm.com/2009/03/21/deploying-a-sinatra-app-on-dreamhost/ http://blog.nyerm.com/2009/03/21/deploying-a-sinatra-app-on-dreamhost/#comments Sat, 21 Mar 2009 18:32:50 +0000 lonnon http://blog.nyerm.com/?p=548 I’ve been down with the flu and confined to the couch for the last couple of days, so what better way to pass the time than learning a new web framework and deploying it to Dreamhost? Only a brain cooked by fever would think something like this might qualify as fun, but my grey matter is pretty close to hard-boiled by now, and I can only play so much WoW before wanting to shoot myself. So I fired up Google and a text editor and started hacking away.

Enter Sinatra

The most pleasant part of this whole experience was picking up Sinatra, a minimal Ruby web framework that hearkens back to the simpler days of shoving a bunch of Perl into a CGI script and calling it a day. Like the CGI script of yore, you can easily stuff a small app into a single file. Unlike that CGI script, Sinatra lends itself well to MVC separation, test- or spec-driven development, and other modern programming conveniences. It’s ideal for slapping a quick user interface on some Ruby code.

Sinatra’s readme is a great drink-from-the-fire-hose introduction to what the framework can do, but the minimal “hello world” application on Sinatra’s home page is a bit too minimal to be instructive. There are some great tutorials listed on the Sinatra site, though. In particular, I found Building an iPhone web app in under 50 lines with Sinatra and iUI to be just the ticket for quickly getting up to speed on what Sinatra does. As an added bonus, it’s got iPhone stuff in it, which is worth at least two squares in Buzzword Bingo.

Dreamhost, prepare to be boarded

The first step is to make a domain in the Dreamhost panel and configure it to run Passenger. From what I’ve been reading, Passenger isn’t really set up to run apps in a subdirectory (like example.com/myapp), so a new subdomain is the way to go here (like myapp.example.com). Dreamhost lets you define as many subdomains as you want, so this isn’t a problem; just click Add New Domain / Sub-Domain in the Domains > Manage Domains screen.

On the Fully Hosted page that appears, check the Ruby on Rails Passenger box. Then set up the web directory as you would for any other site, but add current/public to the end of the path. We’re using Capistrano to deploy the app, and Capistrano wants to deploy to a directory called current. Passenger expects the web directory to point to the app’s public folder. Combining those two makes a path ending in current/public.

Let Dreamhost do its thing and create the new domain. Depending on how flaky its systems are and the current phase of the moon, you may have a working subdomain in a few minutes or several hours. I failed my saving throw versus Broken Scripts and got the several hours version when I set up the domain yesterday, resulting in the dreaded bad_httpd_conf error. You can sometimes force Dreamhost to rebuild your messed up httpd configuration by going back to the Fully Hosted page and just clicking the Fully host this domain now button. No need to change any settings on the page; apparently, performing this little ritual will kick the scripts into gear, and with luck, you’ll have a working subdomain with Passenger running on it.

When Dreamhost’s scripts get around to creating the domain, they’ll also create its web directory. You’ll need to ssh over to your account and delete the current directory that’s there. Capistrano recreates current as a symbolic link pointing to the currently deployed version of the application.

  > cd ~/sites/sinatra-test.nyerm.com
  > rm -rf current

Vendoring Sinatra and Rack

Though it’s possible to get your own local gem repository working on Dreamhost (and for some gems, like RMagick, necessary), I find it simpler to unpack gems required by the app into a vendor folder and just deploy them with the rest of the application.

As I write this, Dreamhost doesn’t have Sinatra installed at all, and its copy of Rack is version 0.4.0, which is incompatible with the latest Sinatra (0.9.1.1). So, I unpacked both of these gems into a vendor folder. Run these commands from the root of your Sinatra project:

  > mkdir vendor
  > cd vendor
  > gem unpack rack
  > gem mv rack* rack
  > gem unpack sinatra
  > gem mv sinatra* sinatra

Be sure to change the require 'sinatra' line at the start of your application so it requires the vendor copy of Sinatra:

  require 'vendor/sinatra/lib/sinatra'

Capifying and racking

With Dreamhost ready to receive your application, it’s time to get Capistrano in on the action. First you’ll need to create a Capfile so Capistrano knows where your application’s source is and where it should be deployed.

  > capify .

Open Capfile in your favorite editor and replace the sparse default contents of the file with something more like this:

  load 'deploy' if respond_to?(:namespace)

  default_run_options[:pty] = true
  
  # be sure to change these
  set :user, 'username'
  set :domain, 'domain.com'
  set :application, 'myapp'
  
  # the rest should be good
  set :repository,
      "#{user}@#{domain}:git/#{application}.git"
  set :deploy_to,
      "/home/#{user}/#{application}.#{domain}"
  set :deploy_via, :remote_cache
  set :scm, 'git'
  set :branch, 'master'
  set :git_shallow_clone, 1
  set :scm_verbose, true
  set :use_sudo, false
  
  server domain, :app, :web
  
  namespace :deploy do
    task :restart do
      run "touch #{current_path}/tmp/restart.txt" 
    end
  end

I found a number of sites with reasonable instructions for deploying Sinatra to Dreamhost, and my favorite is John Nunemaker’s guide on RailsTips. The Capfile above is from his article, which is well worth a look.

The bits that you might need to change in the Capfile here, aside from the obvious :user, :domain, and :application fill-ins, are the :repository and :deploy_to paths. For example, I keep my personal Git repository in a directory that’s served out by Apache so I can browse the contents. Also, my file structure has an extra sites directory above the web roots, because I don’t like the mess that Dreamhost’s default paths make of my home directory. The appropriate portion of my Capfile looks like this:

  set :repository,
    "#{user}@#{domain}:sites/git.nyerm.com/#{application}.git"
  set :deploy_to,
    "/home/#{user}/sites/#{application}.#{domain}"

The last ingredient needed for deployment to Dreamhost is a rackup configuration file, config.ru. Pop open the text editor again and enter the following:

  require 'vendor/rack/lib/rack'
  require 'vendor/sinatra/lib/sinatra'
  
  set :run, false
  set :environment, :production
  set :views, "views"
  
  require 'hi.rb'
  run Sinatra::Application

Deploying to Dreamhost

Check all your files in and push to the remote Git repository, and you should be ready to deploy with the following commands:

  > cap deploy:setup
  > cap deploy

Assuming you don’t have any typos and Dreamhost is choosing to be merciful, you should now have a Sinatra app running on Dreamhost. On the other hand, if like me you’re not a divine being of pure logic, you might want to enable Rack’s logging middleware so you have some clue what’s not working. Stick the following in your config.ru, and you’ll get something more useful than you’ll find in the Apache logs:

  log = File.new("log/sinatra.log", "w")
  STDOUT.reopen(log)
  STDERR.reopen(log)

Credit where credit is due

I found the following articles helpful when trying to get all this working:

]]>
http://blog.nyerm.com/2009/03/21/deploying-a-sinatra-app-on-dreamhost/feed/
Helipad, now on GitHub http://blog.nyerm.com/2009/03/06/helipad-now-on-github/ http://blog.nyerm.com/2009/03/06/helipad-now-on-github/#comments Fri, 06 Mar 2009 11:38:03 +0000 lonnon http://blog.nyerm.com/?p=541 The Helipad Ruby interface is now available on GitHub in addition to its original home on RubyForge.

There’s no difference at all between the two, apart from the GitHub copy bearing my name, which is GitHub’s convention for preventing collision between identically-named gems. If you wish to install the gem from GitHub instead of RubyForge, you can do the following:

  > gem sources -a http://gems.github.com
  > sudo gem install lonnon-Helipad
]]>
http://blog.nyerm.com/2009/03/06/helipad-now-on-github/feed/
Improved dynamic human-readable RESTful routing http://blog.nyerm.com/2009/02/20/improved-dynamic-human-readable-restful-routing/ http://blog.nyerm.com/2009/02/20/improved-dynamic-human-readable-restful-routing/#comments Fri, 20 Feb 2009 08:58:31 +0000 lonnon http://blog.nyerm.com/?p=513 Earlier in the week I posted about making dynamic RESTful routes in Rails. At the end of the article, I mentioned that the method I was using might not work in a production environment, and after searching Agile Web Development with Rails for the word “restart,” I confirmed my suspicions. Generating routes on the fly from data runs afoul of caching, requiring the server to be restarted to pick up changes to the routing. That rules it out as a reliable way to generate pretty URLs.

To recap, I’ve already used map.resources to generate the usual http://example.com/sections/1 style of REST URL. I want to be able to route a URL like http://example.com/about to the show method of my Sections controller, as well, to improve human readability (and SEO) of the URL.

Fortunately, I’d already thought about how to do this. The solution is to capture the highly variable URL in a route and process it in the Sections controller to figure out where to send it. The following is now the very last route in my routes.rb file:

  map.section_dispatch ':section',
                       :controller => 'sections',
                       :action => 'show'

This route’s location at the very end of routes.rb is no accident. It’s extremely promiscuous, and it will latch onto any URL of the form http://example.com/foo. If it came earlier in the routing, it would prevent many other routes from being triggered, including the http://example.com/sections REST route that calls the index action to display a list of all the sections.

The route captures whatever comes after the domain part of the URL in the :section parameter and sends it along to the show action in the Sections controller, which is where the really interesting stuff happens:

  def show
    section = params[:section]
    if section.nil?
      section = 'home'
    end
    @section = Section.find_by_name(section)
    unless @section
      render :file => "/404.html",
             :status => :not_found
    end
  end

Remember I said the route is promiscuous? Here’s real proof: even a nil :section parameter gets picked up by the route, which means the root URL for the site (http://example.com) is sent to the show action. The check for section.nil? assigns the Home section as the desired target; Home is where I keep any bits of content that appear on the front page of the site.

The show action then looks for a Section in the database whose name matches whatever the route picked up from the URL, assigning the Section it finds to the instance variable @section for use by the Section view. However, if the name in the URL doesn’t match any Section names, a render call sends the browser a 404 Not Found error and renders an appropriate page so the site visitor knows she’s typed in a bad URL. Eventually, I’ll replace the static 404.html file with a new controller and view that can generate a more useful 404 page with a search box and helpful links, but that’s a project for another day.

]]>
http://blog.nyerm.com/2009/02/20/improved-dynamic-human-readable-restful-routing/feed/
Crashing InDesign with bookmarks and hyperlinks http://blog.nyerm.com/2009/02/18/crashing-indesign-with-bookmarks-and-hyperlinks/ http://blog.nyerm.com/2009/02/18/crashing-indesign-with-bookmarks-and-hyperlinks/#comments Thu, 19 Feb 2009 01:17:36 +0000 lonnon http://blog.nyerm.com/?p=506 After generating a table of contents for a multi-document InDesign book, I tried to export the book to PDF. Adobe InDesign CS3 fell right over, presenting me with the friendly “please tell our developers what the hell you were doing that crashed our fine software” dialog.

When generating the table of contents (Layout > Table of Contents), I selected the Create PDF Bookmarks option. If I omitted the bookmarks, InDesign was able to export a PDF without any trouble, but of course, the PDF was missing the bookmarks. Because the book is nearing 100 pages, having functional bookmarks in the sidebar of Adobe Reader, as well as working hyperlinks in the table of contents, is a necessity for navigating this beast.

After trying every combination I could think of in the Table of Contents dialog, I turned to the Export Adobe PDF dialog (Book panel menu > Export Book to PDF) and started flipping switches there. I discovered that the Bookmarks option in the Include section of the dialog didn’t make any difference; whether on or off, InDesign still crashed when producing a PDF.

I turned off the Hyperlinks checkbox, and lo and behold, InDesign continued chugging away and gave me a PDF. None of the bookmark sidebar links worked, nor any table of contents links, nor any other hyperlinks anywhere in the book, but at least InDesign decided to stay with me this time instead of unceremoniously quitting.

On the theory that a logical approach wasn’t working, I started poking at random settings. I got lucky with the first one I tried; turning off Create Tagged PDF not only prevented InDesign from crashing, it produced a fully functional PDF with working bookmarks and hyperlinks. Mission accomplished!

I’m a bit frustrated that InDesign refuses to make a tagged PDF with working hyperlinks. The whole point to tagged PDFs is that they define document structure, which makes them accessible to assistive reading technologies and lets mobile devices reflow the content to better fit tiny screens. This book isn’t likely to reach a huge audience to begin with, but it hurts to think that InDesign might be shrinking that audience even further. Given a bit of googling, it appears I’m not the only one to find problems with tagging in InDesign CS3.

]]>
http://blog.nyerm.com/2009/02/18/crashing-indesign-with-bookmarks-and-hyperlinks/feed/
Dynamic human-readable RESTful routing http://blog.nyerm.com/2009/02/16/dynamic-human-readable-restful-routing/ http://blog.nyerm.com/2009/02/16/dynamic-human-readable-restful-routing/#comments Tue, 17 Feb 2009 03:02:45 +0000 lonnon http://blog.nyerm.com/?p=483 I’m slowly becoming a convert to the RESTful routing model in recent versions of Rails, largely because it builds a pile of useful named routes with a tiny amount of code. If I put map.resources :sections in my routes.db file, I instantly get sections_path, edit_section_path, and all their friends. When coding a controller, it’s a lot nicer to write redirect_to section_path than redirect_to :controller => :section, :action => show.

The only difficulty I have with default routes created by map.resources is that, in some cases, they’re ugly and show too much of the application’s internal workings. For example, the application I’m working on now has a Section model, which describes a major section heading in the site (things like About, FAQ, and Help). Instead of having weird routes like /sections/1, I want human-readable URLs like /about. They look nicer, and they’re better for SEO.

To the rescue: dynamic named routes

To create the pretty section names, my routing dynamically creates a set of named routes based on the URL-friendly string stored in each Section’s name attribute. The appropriate part of routes.db looks like this:

  map.resources :sections
  Section.find(:all).each do |section|
    map.named_route("#{section.name}_section",
                    section.name,
                    :controller => 'sections',
                    :action => 'show',
                    :id => section.name,
                    :method => :get)
  end

The first thing this code does is create normal RESTful routes for the sections:

  map.resources :sections

Creating the usual RESTful routes allows administrative actions, like editing and deleting sections, to have all the benefits of regular REST routing. I can still edit a section at /sections/1/edit, or delete one by sending the DELETE HTTP method to /sections/1. I’m okay with most of these URLs showing off section ID numbers, because they’re all tucked away behind an admin interface that requires authentication to access. What I really need is to create new routes for each section’s show action, which is what the next part of the code does.

Next, the code iterates over the sections in the database, using the standard ActiveRecord find method:

  Section.find(:all).each do |section|

Within this each block, the map.named_route method is used to create a named route pointing to each section’s show method. Normally, Rails creates named routes using a little method_missing magic. This is great when you’re making a named route by hand; it lets you create named routes on the fly, instead of having to call a method on the map object (an instance of ActionController::Routing::RouteSet::Mapper). Unfortunately, this bit of syntactic sugar isn’t as nice to code that needs to create named routes.

Fortunately, the Mapper class contains an undocumented named_route method that creates named routes in a standard method call, rather than relying on method_missing to fill in the blanks. The named_route method takes three arguments: the name for the new route, the URL path that will trigger the route, and a hash full of options defining the properties of the route. In my case, the name for the route is composed of the Section object’s name attribute, with _section tacked onto the end. This results in helper methods like about_section_path and faq_section_url. The recognized path is the name of the section itself, meaning that /about will go straight to the section controller’s show method and display the About page.

Putting in the human-readable bit

One other sneaky thing I’m doing is on line 7 of the first code example, with :id => section.name. Because I’m using short, human-readable names in my section URLs, I’ve changed how the Section model generates URLs. By default, ActiveRecord returns the record’s id@ as a String, resulting in the familiar @/sections/1 style of URL. However, if you override the to_param method of an ActiveRecord model, you can change how it generates URLs. Over in my section.rb file, I have the following code:

  def to_param
    name
  end

This ensures that when the Section model is used to generate a URL, it returns the friendly, human-readable name attribute instead of its numeric @id@.

A drawback: rake gets wonky

There is a downside to this method of dynamically generating routes. Recent Rails versions (probably 2.1 and later) changed the rake tasks framework to load up the entire application’s environment before running any rake task. Unfortunately, this includes the routes.rb file. Because my routing queries the database, a normally innocuous invocation of rake db:create causes problems if the database is missing or empty, producing an error like the following:

  > rake db:create
  rake aborted!
  Unknown database 'project_development'

I can’t fathom why something like db:create would need access to the application’s entire environment, and it’s particularly silly in this case that in order to create the database, there must already be a database. I expect that purists would argue that having a database query in my routing breaks MVC separation, but this method makes it simple to make named routes based on changeable data. The workaround is to comment out the Section.find part of the routes.rb file before running things like db:create, but it’s a poor workaround, indeed.

In addition, I’m not positive that this setup works well under the Rails production environment. It’s been fine in development, but caching and other goodness introduced in a production application could mean that I can’t change the routing on the fly like this, instead requiring the application to restart to pick up any changes to the sections data. I recall earlier versions of Rails requiring a restart any time routing was changed, but I haven’t been able to track down if this applies to 2.2 in production.

A different approach?

Another possibility, which I may settle on eventually, would be to add a catch-all route at the bottom of routes.rb that pipes everything through a dispatch method in the sections controller. It might look something like this:

  map.parse_section ':section',
    :controller => 'sections',
    :action => 'parse'

It could perform the database lookup inside controller code and compare it to the string captured by the routing system, and it wouldn’t interfere with rake tasks. It’s important to note that this route should be at the very bottom of routes.db, else it will slurp up any single-component URL and attempt to process it with the section parse method.

]]>
http://blog.nyerm.com/2009/02/16/dynamic-human-readable-restful-routing/feed/
TextMate as a blogging tool http://blog.nyerm.com/2009/02/11/textmate-as-a-blogging-tool/ http://blog.nyerm.com/2009/02/11/textmate-as-a-blogging-tool/#comments Wed, 11 Feb 2009 22:48:30 +0000 lonnon http://blog.nyerm.com/?p=478 There’s something extraordinarily wrong about this. I just discovered, through Barry Hess’ blog, that TextMate has a blogging bundle. It hooks up to the ubiquitous XML-RPC interfaces sported by modern blogging software (Wordpress, Movable Type, Typo, what-have-you) and lets you use your text editor to create and edit weblog posts.

This is a far more comfortable interface for composing blog articles than any I’ve encountered, including the feature-rich web interface in Wordpress itself. I don’t use the embedded WYSIWIG editor widget in Wordpress, preferring to format my posts with Textile so I can just keep typing instead of trying to figure out what all the little buttons are supposed to do. TextMate does a great job with highlighting Textile, providing just enough coloring and styling to let you know that you’re doing the markup right without getting in the way of the writing.

On top of that, I’ve got the security of knowing that my prose isn’t going to disappear if the browser crashes or my network connection flakes out. Need more time to compose a lengthy article? Just save it locally, as a simple text file, and come back to it later. This is the very definition of “no muss, no fuss.”

Now to see if this bundle works as well in TextMate’s Windows cousin, e, so I can get the same great feature on my laptop that I have on the iMac at work.

UPDATE (2009-02-11 21:03): Yes, indeed, this same power exists in e. I am one happy camper.

]]>
http://blog.nyerm.com/2009/02/11/textmate-as-a-blogging-tool/feed/