Politics, Programming and Possibilities
27 Apr
Note: Please see the updated ColumnComments v.1.2 post for the latest with bug fixes.
Here’s a small plugin that may be useful for documenting your database. Based on Dave Thomas’s AnnotateModels plugin, this plugin goes one step further and allows you to store comments on each column in the database (MySQL only).
Since the Rails philosophy uses the database as the “authoritative source” for the data model, it’s been troublesome to know where to store helpful developer comments. If you write them in the model files (where it would make sense to do it), you repeat a lot of work because the models don’t store column information.
Dave Thomas solved part of this problem by introducing the AnnotateModels plugin–with it you can take the basic information about each table and auto-generate a comment-header inside each model file. But still, where would you put comments? If you edit the auto-generated header then you run the risk of accidentally (or by necessity) overwriting your own comments when you re-generate the headers.
The ColumnComments plugin makes the necessary modifications to ActiveRecord to allow for an optional :comment in your table migrations. In addition, it includes the same feature provided by the AnnotateModels plugin (rake annotate_models), but also includes the database-stored comments in the auto-generated header.
Here’s an example of the output:
# Schema as of Thu Apr 27 12:07:32 MDT 2006 (schema version 10)
#
# id integer(11) not null
# login string(255)
# A user-generated login name.
#
# salted_password string(40) default(), not null
# Encrypted using SHA1 and the "salt" column
#
# email string(60) default(), not null
# Mandatory email address for each user
There are two times when you might want to add comments to your columns: while you create a new table or after a table already exists.
While You Create a New Table
def self.up
create_table "users" do |t|
t.column "first_name", :string, :comment => "The member's given name."
t.column "last_name", :string, :comment => "The member's family name."
end
end
After a Table Already Exists
def self.up
column_comment "tags", "id", "The unique ID of any tag in the system."
end
Or, if you want to mass-assign comments (for example, just after you install the plugin on an already-built app):
def self.up
column_comments({
:users => {:first_name => "User's given name", :last_name => "Family name"},
:tags => {:id => "Tag IDentifier"}})
end
syncPEOPLE maintains an open source subversion repository for plugins and other useful code that we’ve open-sourced. ColumnComments is released under the MIT license and can be installed from:
svn://syncid.textdriven.com/svn/opensource/column_comments/trunk
26 Apr
I was witness to this gem on the freenode.net #textmate channel:
quellhorst: textmate is expensive
rhacer: textmate isn’t expensive at all.
quellhorst: it is when you have to buy a mac first
canadaduane: lol
quellhorst: which i did this week
Apple, you should be paying attention right now.
26 Apr
I’ve decided to put up a page for my personal Textmate Bundle for others to use. So far, it’s star (and only!) feature is the MASC work I’ve been doing.
As I develop other features, I’ll upload newer versions. This is an “as-is” bundle–I’m just putting it out there in case you want to use / modify / steal / learn from its code.
UPDATE: I just re-made the screencast, this time in under 2 MB. Check it out on the bundle page.
25 Apr
Here’s a method that will allow you to call to_xml on an ActiveRecord::Errors object. We’re using this to pass errors between web apps via a web service api.
class ActiveRecord::Errors
def to_xml(options = {})
options[:indent] ||= 2
options.reverse_merge!({ :builder =>
Builder::XmlMarkup.new(:indent =>
options[:indent]), :root => “errors” })
options[:builder].instruct! unless options.delete(:skip_instruct)
options[:builder].__send__(options[:root].to_s.dasherize) do |xml|
@errors.each do |key, value|
xml.__send__(key.to_s.dasherize) do |xm|
for message in value
xm.message(message)
end
end
end
end
end
end
25 Apr
So here’s an idea I’ve been tossing around on the Textmate IRC channel and mailing list: What if Textmate supported multiple arbitrary simultaneous carets (MASC)? Allan Odgaard didn’t like the idea on first inspection, because it involves using the mouse–something that he is philosophically opposed to (for obvious reasons–it’s a text editor, after all). But I think there’d be many people who would receive this feature with eager arms and an appropriate amount of salivation.
So what is the idea? Here’s my original mailing list post:
What if you could add multiple carets to the current document by command-clicking? I imagine this to work in a way almost identical to that of the current snippet mechanism. For example: choose three caret locations, start typing, and in each location your text will show up. Press tab and the caret will focus in on the second of the two locations, highlighting the newly typed text (if any). Tab again and it moves to the third.
It would also be ideal to be able to highlight multiple selections in the same way–kind of like a powerful replace mechanism. Command-click and select three words in the document, then type one new word, and incrementally, all three words change to the new one.
Here is a screencast of MASC in action (Quicktime, 27 MB):
Update: The bundle is available as a disk image here. Key bindings and the “ß” marker character are subject to change. Use alt-s to mark and alt-f to convert markers to a snippet.
Update #2: No longer uses the beta marker. Uses special angle brackets instead.
Update #3: There is now a page for My Textmate Bundle that has updated information and a new (shorter) screencast.
24 Apr
It seems that the TextMate Footnotes Plugin has been hiding a bug for a while–the clickable line numbers have occasionally had the RAILS_ROOT part of the path included twice, causing the links to fail.
Here’s a screenshot of the type of link that’s been failing (note the “#1″):

It seems to be working now. Get the latest from “svn://syncid.textdriven.com/svn/opensource/textmate_footnotes/trunk”.
21 Apr
Thanks go out to a new Mac user, Jed Hurt, for this correspondence:
You know, I was using TextMate for migrations last night. I realized that when making a new table is was typing ‘mcc[tab]‘ over and over again. Would there be any way to DRY this up? Maybe make it so that if you are currently on an mcc line (after it has already been expanded and you’ve given the column a name and type) and you press a key combo, it makes another mcc on the following line, and places your cursor in the ‘name’ field of the new mcc declaration?
From his suggestion, we now have the “mccc” or “Migration Create Column Continue” snippet, which is a snippet that creates a snippet. Watch the screencast here:

This feature is available in the Textmate Bundle Subversion Repository. Or, you can wait until the next beta release of Textmate.
Update: The screencast is working now.
17 Apr
This one got me today:
feed_bridge_is_valid = !state[:feed] or (state[:feed] and @feed_bridge.valid?)
It turns out that the “=” assignment has a higher precedence than the “or” operator, so if (in the example above) !state[:feed] turns out to be false then feed_bridge_is_valid will be assigned a false value, and the entire expression will return the value of (state[:feed] and @feed_bridge.valid?).
Here’s one solution:
feed_bridge_is_valid = (!state[:feed] or (state[:feed] and @feed_bridge.valid?))
And I think you can also solve the problem by using the “||” version of the “or” operator too.
15 Apr
This plugin saves you time when moving between your browser and Textmate. It adds clickable links to the Rails backtrace when an error occurs, and clickable “footnotes” to the bottom of each page (in development mode only). When clicked, these links open the correct file in Textmate and move your cursor to the precise line of interest.
In your plugins directory, install with:
svn export \\
svn://syncid.textdriven.com/svn/opensource/textmate_footnotes/trunk \\
textmate_footnotes
This plugin was also featured in the syncPEOPLE on Rails bundle for Textmate.
13 Apr
Here’s a way to validate a url if you really want to make sure it’s real (i.e. this goes above and beyond merely checking that a regexp says it’s ok–instead, it goes out and pings the server.)
Create a file, validates_uri_existence_of.rb in your app’s lib folder:
require 'open-uri'
class ActiveRecord::Base
def self.validates_uri_existence_of(*attr_names)
configuration = { :message => "is not a valid web address" }
configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
validates_each attr_names do |m, a, v|
begin
# Try to open the URI
open v
rescue
# Report the error if it throws an exception
m.errors.add(a, configuration[:message])
end
end
end
end
Add ” require ‘validates_uri_existence_of’ ” to your environment.rb. Then in your model:
class Repository < ActiveRecord::Base
validates_uri_existence_of :url
end