InquiryLabs

Politics, Programming and Possibilities

Archive for the ‘Software Engineering’ Category

The old blog just got a new face and a new name. I don’t write much about Ruby on Rails specifically any more (although there will likely be further posts on the subject), and my leanings lately have been toward politics.

The change in focus seemed to merit a fresh visual arrangement, so welcome to the new look, and officially the “InquiryLabs” blog.

Note: Comments are working again. My hosting company had a server crash about a month ago that somehow disabled the spam filter. The net effect was that I ignored all 1800 unflitered comments until today. I deleted all but 6 (nearly all of the comments were spam) and restored the Spam Karma plugin that seemed to do a pretty good job of filtering input. Let me know by email if you notice anything set up incorrectly (such as your comments not getting through, for example). Thanks!

Getting in to TeX

I’ve been learning a lot about the typesetting engine, TeX, lately. It’s really an amazing piece of software from the 1980s—not just because it still works 25 years later, but because of what it allows people to do. Perhaps with its powerful scripting capabilities it will be a long time yet before it becomes obsolete.

A few things I’ve learned:

  1. “TeX” is an engine and command-line tool at the base of several tools.
  2. There are modified TeX engines such as:
    • XeTeX — lets Mac OS users typeset using AAT or TTF fonts from the system
    • eTeX — an enhanced TeX engine
  3. There are distributions of TeX, either built for you or packaged in some way:
    • AMS-TeX — used by mathematicians and scientists
    • teTex — the basic distribution most others are built from
    • TeXLive — a Mac OS distribution that puts all the engines and macro packages together.
  4. And then there are macro packages which are like libraries of functions that enhance TeX (the macro packages generally work with any TeX distribution):
    • LaTeX — the oldest and largest macro package (advantages: well-documented and feature-rich; disadvantages: big, bloated, sometimes confusing)
    • conTeXt — a more recent macro package that binds things together at several different levels.

What I’ve been trying to do is build something like Jonathan Fine has at MathTran—a TeX daemon process that can render files (math equations in the case of MathTran) into PNG or JPG format at lightning speeds. I’d also like robust font support, such as is provided by XeTeX, but unfortunately it seems very slow. My testing showed that rendering a 100 page document using the standard TeX fonts with the standard TeX engine took about 1.5 seconds, while rendering the same document using a TrueType font and XeTeX took about 30 seconds. The bottom line is, that’s not fast enough for real-time document creation on the web.

An excellent “plain TeX” (i.e. TeX without any macro packages) introduction is available from professor Michael Doob at the University of Manitoba, A Gentle Introduction to TeX.

Since typesetting is the function of TeX, it stands to reason that the most complicated aspect of this engine is the way fonts are stored, used and rendered. I found a great summary at the University of Utah on font tools for TeX. Also, the TeX User Group website has some good information as well. And here are some free fonts I found. If you know of any other good font resources, I’d like to know. The fontinst utility also looks quite useful.

More soon.

Aman Gupta recently wrote the Sequel mailing list with a nice, compact solution to a question posed: is it possible to write an ActiveRecord-like “serialize” class method for Sequel::Model classes?

Aman answers, yes.

Magic Scaffold for Merb

I’ve been playing with an idea lately that makes scaffolding a Merb app more pragmatic than the traditional generator method. I call it “Magic Scaffold for Merb”.

One of the problems I’ve always had with code generators is that they create several files with code all over the place that I’m not familiar with. Ideally, I’d like to start with one file that I can then change over time or cut/paste into separate files as desired. In addition, because I change my models around a lot near the beginning of an app (the time when generating code is most useful) I would like the generated code to be updated almost constantly to reflect my experiments with the data model.

Magic Scaffold for Merb accomplishes these tasks by doing a little bit of clever work for you. First, rather than being a command-line code generator, Magic Scaffold is a method. You put it in a Merb controller and it gets called when the class itself is loaded. Second, it requires a Ruby block in curly braces. This is a little trick that takes advantage of the fact that in Ruby, blocks can be inspected to return the filename and line number at which they were declared. At this point, the Magic Scaffold code parses the ruby file where it was declared and inserts the scaffolding code wrapped inside a Ruby module. Finally, it reloads the ruby file so that the scaffolding code gets included, and then mixes the module into the controller. Presto, your controller is scaffolded.

The really nice part is that you can cut and paste any method from the scaffolded code (’index’, ’show’, ‘edit’, etc.) into the controller class (it must be above the magic_scaffold_here declaration) and the Magic Scaffold code will know not to try scaffolding that method any longer. As a result, you get the benefit of constantly re-scaffolded code with the flexibility of changing all or part of it as necessary.

Take a look at the Jing Demo and tell me what you think. The code is available in the lib folder of Marble’s code (part of the Merb repository).

Another Major Change to Merb Routes

I updated the routing system to Merb again yesterday. I’ve added plenty of specs and examples now to illustrate its flexibility and usefulness. What I used to call “late-bound routes” is now “deferred routes” which makes more sense.

Take a look at the new specs for a run-through.

TextMate Footnotes Has Moved

TextMate’s Ruby on Rails bundle has changed directories, and along with it, the Footnotes plugin. People are reporting that “script/plugin install” results in “Plugin not found: http://macromates.com/svn/Bundles/trunk/Bundles/Rails.tmbundle/Support/plugins/footnotes”. Indeed, it can now be found at:

http://macromates.com/svn/Bundles/trunk/Bundles
/Ruby on Rails.tmbundle/Support/plugins/footnotes

(no spaces or newlines)

To switch from the old address to the new, just use “svn switch [new-url]” at the command line.

Also, for those of you on edge rails, you can point your scripts / svn clients at:

http://macromates.com/svn/Bundles/trunk/Bundles
/Ruby on Rails.tmbundle/Support/plugins/footnotes-edge

Enhancing the ‘irb’ Experience

I use the ‘irb’ command at the terminal every day. In case you program in Ruby and haven’t used it yet, you’re missing out. But as it turns out, so was I. The irb program can be configured to do almost anything, and specifically, people have already done stuff like this:

  • Autocompletion… wow. Just press tab on any partially-complete method name and irb will complete the rest for you.
  • Save and restore the commands you type between sessions (use the “up” cursor key to cycle through past commands, like normal)
  • Use the “ri” command right inside of irb. You won’t need to have two terminals open to reference the core or standard library documentation any more.

I’ve uploaded my .irbrc file here for anyone to use and/or modify. Just create a “.irbrc” file in your home directory (on a unix-based machine) and paste it in there. Yum!

Getting to Know Merb

Merb is in its incubation phase—small, changing quickly, and growing fast. As I’ve mentioned in previous posts, it’s a light-weight framework similar to Rails. Here is a list of resources on the web I’ve found useful as I’ve been introduced to this mini-framework:

If you have a half hour, I highly recommend Ezra’s hoedown presentation listed first above. He talks about his design philosophy (small, fast, less magic) and the features now available as well as upcoming.

New Router in Merb

Note: The API has significantly changed since this posting. Best to check out this post for details.

With Ezra’s approval, I committed some significant changes to the Merb routing system last night. If you’ve ever been limited by Rails’ routing system, you might want to check out some of the features now in Merb. Here’s a run-down of some ways you can use the new system:

Construct Params from Matched Portions of the URL

Merb::Router.prepare do |r|
  # There is now a named_route method which is
  # basically a simple_route plus a URL generator
  r.named_route :test,
    "/:controller/:action/:id/:prefix",
    :action => ':prefix_:action'
end

# In a controller or view, we can use its generator:
url :test,
  :controller => "users",
  :action => "show",
  :id => 1,
  :prefix => "alternate"

# => "/users/show/1/alternate

# Example controller class that would respond properly:
class Users < Application
  def simple_show
    #
  end
  def alternate_show
    #
  end
end

Use Any Request / Environment Variable

Merb::Router.prepare do |r|
  # Send all SSL / HTTPS traffic to the Secure class, 'index' action
  r.route :protocol => /https/,
    :controller => "secure",
    :action => "index"

  # Use the 'admin' subdomain to route to the admin module
  r.route :domain => /^admin\\./,
    :path => %r[/~~/~~/~~],
    :controller => “admin/:path[1]“,
    :action => “:path[2]“,
    :id => “:path[3]”
end

Note in the above example that some of the keys in the hash are environment variables (:domain, :path) and some are outputs to the params hash (:controller, :action, :id). This may change in the future, but for now it just means you have to know that the environment variables are “reserved words”, used specifically for matching against the incoming URL request.

Also, you may wonder at the “~~” and “:path[1]” notation. The “~~” in the path is a special string sequence that gets replaced with a parenthetical regular expression that will match a normal URL segment (e.g. it will match characters such as a-z but not ‘/’ or ‘?’). Next, the “:path[1]” notation is used to tell the router how to reconstruct the params from the matched portions of the request / environment variables. So, in the above example, the :controller is going to be “admin/” plus whatever gets matched in the first “~~”. Here’s an example match. Let’s use the URL, “http://admin.mysite.com/books/show/1″:

# Routes to the controller Admin::Books, and the "show" action
module Admin
  class Books < Application
    def show
      params[:controller] # => “admin/books”
      params[:action] # => “show”
      params[:id] # => “1″
    end
  end
end

A full list of request / environment variables that you can use is available in the lib/merb/router.rb class, but here is a sampling:

  • protocol
  • domain
  • port
  • path
  • method (e.g. ‘put’, ‘post’, ‘get’)
  • query_string
  • accept
  • remote_ip
  • user_agent
  • referer

This flexibility could, for example, let you essentially create two different sets of views for Mozilla vs. Internet Explorer browsers (routes would distinguish between browsers using the “user_agent” variable). Or you could ban certain IP addresses. Or allow certain routes from third party sites using the “referer”. Lots of possibilities.

Late-bound Route Decisions

Merb::Router.prepare do |r|
  # Query the database for an object type, and then route
  # to the appropriate controller based on type
  r.route do |request|
    if request.path.match(%r{/([a-z0-9\-] )})
      guid = $1
      if obj = AppObject.find_by_guid(guid)
        {:controller => obj.type, :action => ’show’, :id => guid}
      end
    end
  end
end

Some things may continue to change as I get feedback and also optimize the system, but the above examples should stand as a doorway for solutions to your own development needs. Let me know if you have any special requests and I’ll try to post more later.

Changes to Merb in the Last Week

I’ve been busy working on FamilyLearn projects and haven’t had time until now to pay attention to the many changes that Ezra and Jon have been making to Merb. Here’s a summary of some noteworthy changes over the past week:

  • There is no longer a “dist” folder. The Merb directory structure is now even closer to Rails’ directory structure.
  • Created a “mixins” directory and removed “merb_” prefixes from Merb’s inner workings.
  • An interesting ticket was submitted which documents how to progressively stream HTTP output in Merb/Mongrel. (Thanks to b.candler and ry)
  • You can now “throw” content and “catch” it again from any partial or view.