EverSave - The Missing Autosave for OS X Apps
November 10th, 2008
I hate to admit it, but I have lost documents while working on my mac. You know how it happens – typing a long document in Pages, with 35 tabs open in Safari, checking Mail, downloading attachments, then open Photoshop and… Boom. It crashes. And I forgot to save.
Strangely, there is no auto-save feature in Apple Pages or Keynote, nor any number of other OS X apps. TextMate has this feature, and I rely heavily on it. Every time I make a change to a file, I switch to the browser to check it out, and TextMate automatically saves my file. I barely even think about it, until it’s not there.
Today I discovered EverSave, a free app that auto-saves your documents for you.
EverSave is a clever tool which allows you to save all of your documents – if possible – in a specific time interval or by changing the frontmost application. This means no more data loss if applications crash.
This should definitely be built into all new OS X apps.
Download it here
Spike
October 31st, 2008
Wow! Donor Tools peaked at almost 2000 visitors yesterday thanks to linkage from Best Web Gallery and CSS Mania

Parenting Theory
October 31st, 2008
As our children are developing into ever more sophisticated and rational human beings, we are degenerating – devolving into shadowy cave-people, with heightened reflexes but incapable of forming a complete sentence or retaining a memory for more than 15 seconds. No. Complete. Sentence. Ungh! But! We can catch a glass jar tipped by a toddler as it hurtles its way to the ground. Me kung-fu cave dad.
Track Referrals in Your Rails App
October 30th, 2008
Here’s a quick and easy way to track exactly where your signups are coming from, and who referred any given customer, without having to cross-reference your analytics program.
1 2 3 4 5 |
before_filter: set_referer def set_referer cookies[:referer] = request.env['HTTP_REFERER'] if cookies[:referer].nil? end |
The set_referer method sets up a session variable that keeps the original referrer with your customer, no matter how many pages they click through before signing up.
You can email this variable to yourself when they sign up, or store it in the database to keep track of who came from where.
Wildcard (*) Searches With Thinking Sphinx
October 24th, 2008
Ryan Bates has a helpful screencast about the using the excellent Thinking Sphinx Rails plugin for the Sphinx search engine.
There seems to be a bit of confusion over how to enable wildcard (star) searches with Thinking Sphinx. Wildcard searches would let you search for partial words, so “thin*” would match “Thinking Sphinx” and “Thinner”. This is pretty useful, and for Donor Tools it is essential.
Turns out it’s really easy to turn on wildcard search. There is no need to make any changes to your Sphinx setup or add a config/sphinx.yml file. In your define_index block, simply add enable_star and min_prefix_len like so:
1 2 3 4 5 |
define_index do ... set_property :enable_star => true set_property :min_prefix_len => 3 end |
enable_star simply turns on wildcard searching. However, this won’t do much good unless you also enable prefix indexing using min_prefix_len.
min_prefix_len sets the minimum number of letters that Sphinx will index. From the Sphinx docs:
...indexing a keyword “example” with min_prefix_len=3 will result in indexing “exa”, “exam”, “examp”, “exampl” prefixes along with the word itself.
You can also set min_infix_len, which does the same thing as min_prefix_len, except it does it on the middle of the word.
Infix indexing allows to implement wildcard searching by ‘start*’, ’*end’, and ’*middle*’ wildcards.
Caution: Infix indexing can cause your index to grow, and may slow down searching.
Now, re-run rake thinking_sphinx:configure, re-index (rake ts:in), and restart the Sphinx daemon (rake ts:run), and it should work.
Chuck Baldwin for President
October 20th, 2008
I love change. I love hope. And I love choices. But something about the way our electoral process works really rubs me the wrong way. Sure, it’s great that we get to vote for our President. But someone out there – someone with power – has picked my two choices for me, and for the past year has been hammering it into my head that if I don’t choose one of these two prescribed choices, then I’m throwing my vote away. You know what I realized? Aside from minor policy differences, like what percent of a tax cut the middle class will get, and whether we should invade this country or that country, there really is very little difference between the two mainstream candidates. Both Senators Obama and McCain voted in support of FISA, the Patriot Act, and the Bailout Bill, three of the most odious and nefarious acts of legislation that have done incredible damage to the American way. Neither of these two candidates provide any real solutions, and when put to the test, we see that in the end, a vote for McCain is the same as a vote for Obama; and neither will bring about any real change or mitigate or destroy the corruption that now gnaws away at the character of our government, nor will they stop the cancerous expansion of government powers that make our current government look and act more and more like the government of King George, from whom we won our Independence.
So if there is no real difference between the two, and I’m only voting for one or the other because I want to be on the winning side, or because I want to vote for one so the other won’t win, then I am truly wasting my vote.
What’s a patriot to do?
Well, did you know that there are actually six noteworthy candidates (plus a few others) for president this election? “But”, you say, “none of these candidates can win. Why bother voting at all?” You’re right, we might as well just give up. No sense in playing if we can’t be on the winning team, right? Look, the whole country is saying that. Everybody is just rolling over and letting the political establishment have its way with them. If we all just comply then we’re going to get exactly what people with power want to give us. That’s what the American Revolution was about folks! In a way, the American Revolution continues to this day. The fight against tyranny and oppression will go on as long as there are good and evil (and I don’t mean the “axis of evil” – I mean real evil, and people who would use power to harm other people). As long as we’re here on this earth we each have a responsibility to fight to maintain our freedom and our individual rights and to preserve and protect our Constitution against all enemies, foreign and domestic. The Constitution (read it, it’s good) limits the government’s power, and it grants the government power only by the consent of the governed. Our responsibility as citizens is to give that consent, to withhold our consent to tyranny, and to keep the government accountable by electing officials that respect the people and their position as representatives of the people.
One of the most obvious ways that we fulfill this responsibility is by choosing our executive, our President. If we believe in the Constitution, then we ought to elect a president who shares our reverence of liberty, freedom, and the Constitution, and who has demonstrated an understanding of these tenets, and who will do the most to uphold these precious things.
That is why I have decided to support Chuck Baldwin for President of the United States.
Baldwin does not have as much political experience as Obama or McCain, but in this case I think that might be a good thing. He certainly is not part of the political establishment. Based on his writings, his history, and his character recommendations, I believe that Chuck Baldwin is the candidate best suited to execute the office of President of the United States.
- Ryan Heneise
Haiti Hurricane Update
October 15th, 2008
Haiti Hurricane Update
We’ve been collecting money for Haiti hurricane victims for several weeks now, and although we haven’t received quite the response that I had hoped for, we did raise $45. Since this isn’t really enough to make a dent in providing clean water, we’ve decided to donate the entire amount that we raised, plus our matching funds, to Yéle Haiti, the aid organization founded by musician Wyclef Jean. The money will be donated to their Haiti Storm Relief Fund.
Check out the powerful videos on the homepage of www.yele.org. I also have some pictures of the aftermath on my Flickr account.
“I’ve seen extreme poverty before, but I’ve never seen it coupled with a natural disaster.” – Matt Damon, speaking on the video on Yéle Haiti.
Those of you who know me know that I share a special connection with Haiti. My parents were missionaries there, and I spent many years there growing up.
PassiveRecord
October 2nd, 2008
Ever need to use structured data that doesn’t need its own database model? Ryan Bates shows you how in a recent Railscast: Non Active Record Model.
If you have more than one non ActiveRecord model, you’ll find yourself starting to duplicate a lot of code. I did recently, so I extracted a bunch of functionality into a plugin called PassiveRecord.
There's more! Read the rest of this entry
Google Code Search
September 30th, 2008
Any programmer who’s ever googled for code snippets, particularly non-alpha snippets like ”<=>” will appreciate this…
Did you know Google has a code search tool? Go to http://www.google.com/codesearch and try a search like "def <=>" lang:ruby
Bliss!
New Donor Tools Feature: Online Donations
September 16th, 2008
We just rolled out a new feature that we’re really proud of: Online Donations! Now your donors can donate to your organization easily using Donor Tools’ new Online Donations feature!
The great thing about online donations is that funds are transferred immediately via PayPal, and the donation shows up instantly in your Donor Tools account.
As an added bonus, if you do a little legwork and track down your PayPal Payment Data Transfer token (we’ll show you how), Donor Tools will automatically record any fees that PayPal deducts (Donor Tools doesn’t deduct any fees for online donations).
Take a look at our Haiti Aid example site, at haitiaid.donortools.com. It’s a real fundraising project that we set up to help raise money to buy water purification supplies for victims of the recent hurricanes in Haiti.
Donor Login
Online Donations comes with another nice feature also – Donor Login. Now your donors can sign in to Donor Tools to track their giving history, print donation receipts and reports, and of course, donate online.
Water for Haiti Hurricane Victims
September 3rd, 2008
We just sent 45 boxes of Katadyn Micropur Purification Tablets to Haiti to help provide potable drinking water for hurricane flood victims.
Much of Haiti has been inundated by recent hurricanes, causing contamination of many water supplies. A major concern right now is the outbreak of water-borne diseases like giardia and typhus. These water purification supplies will most certainly save lives by providing clean drinking water.
Our first shipment will go down on Friday, Sept 5. We’re sending enough to purify about 1350 liters (357 gallons) of water. We’d like to send more!
So let’s do it! We will match every dollar donated to buy more purification tablets. If we raise $1000, then we’ll match it for a total of $2000. That’s enough to purify about 4633 liters (1224 gallons). That’s enough to provide one week of clean drinking water for 350 people!
Why Haiti? Both Ryan and Bethany have spent significant time there – Ryan as a missionary kid and Bethany as a nurse. We still have family in Haiti. Despite the poverty, the land is very dear to us.
Thanks for donating!
Update: Now you can donate through our new Donor Tools page! https://haitiaid.donortools.com/
Update 2: Also check out the Haiti Aid Blog
Underscores in URLs Considered Harmful
September 2nd, 2008
Did you know that the ”_” (underscore) character is prohibited in URLs host names? I didn’t, until just a few minutes ago.
The problem began when a Donor Tools customer signed up for a new account with a subdomain like “demo_organization”. So their web address would have been http://demo_organization.donortools.com. It worked fine for me, but they could not sign in no matter what they tried. We went back and forth with support emails trying to figure out what was going on – I could access their web address and every other web address on the system with no problem. But as soon as they tried to sign in on their end: boom, error. (Customer was using Internet Explorer)
I quickly traced the difficulty down to a cookie error. Using a little creative cookie sniffing, I set up an error message on the signin form, so if you go to https://demo.donortools.com/admin with cookies turned off (or with a restrictive privacy policy), you’ll be warned to turn on your cookies. So I instructed the customer how to turn on their cookies, loosen their privacy settings, etc. All to no avail – they could still not sign in.
Finally it hit me: this was the only account we had that used an underscore in their web address. Could that be it? A quick google got me this page: http://support.microsoft.com/kb/909264, which references RFC 1123:
In DNS computer names, use only the characters that are listed in RFC 1123. These characters include A–Z, a–z, 0–9, and the hyphen (-). In Windows Server 2003, DNS allows most UTF-8 characters in names. However, do not use extended ASCII or UTF-8 characters unless all the DNS servers in your environment support them.
Internet Explorer was choking on the underscore character! It would access the web address like normal, but for whatever reason, it was blocking cookies from that address. Voila! A quick change of the web address from ”_” to ”-” solved the problem.
So, for future reference, if your site requires Cookies, default to the least common denominator, Internet Explorer, and constrain web addresses to [a-z0-9-]*.
Post Git Commit Messages to Backpack Journal
August 13th, 2008
We switched to Git this year, and we now use Git almost exclusively at Art of Mission. We’ve even moved over most of our old svn repositories.
One thing we wanted to do recently was to post commit messages into our Backpack journal. Turns out it is very easy with Git and a little bit of Ruby code.
This would go in .git/hooks/post-commit (make sure to make the that file executable):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
#!/usr/bin/env ruby require 'rexml/document' require 'net/http' # Customize these values: # Your backpack account: ACCOUNT = "yourbackpacksubdomain" # Your backpack user id: USER_ID = 123456 # Your token (you might want to put this in a shell variable): TOKEN = '1234567890987654321234567890987654321' PROJECT = "my-project" GIT = `which git`.strip def build_commit_message text = `#{GIT} log --all -n 1` lines = text.split("\n\ncommit ") revision = text[/([a-f0-9]{32})/] commit_author = `#{GIT} show --pretty=format:"%an" #{revision} | sed q`.chomp commit_log = `#{GIT} show --pretty=format:"%s" #{revision} | sed q`.chomp # Additional useful data... # commit_date = `#{GIT} show --pretty=format:"%aD" #{revision} | sed q`.chomp # commit_changed = `#{GIT}-diff-tree --name-status #{revision} | sed -n '$p'` "[#{PROJECT}] #{commit_log}" end # Build the Backpack xml snippet: def build_request(message) doc = REXML::Document.new request = doc.add_element 'request' request.add_element('token').add_text TOKEN journal_entry = request.add_element('journal-entry') journal_entry.add_element('body').add_text(message) return doc end # Post the request to Backpack: def send_to_journal(message) doc = build_request(message) http = Net::HTTP.new("#{ACCOUNT}.backpackit.com") response = http.post("/users/#{USER_ID}/journal_entries.xml", doc.to_s, {'Content-Type' => 'application/xml'}) end # Do it: send_to_journal(build_commit_message) |
Beautiful Printable Pages with CSS
August 4th, 2008
Beautiful Printable Pages with CSS
In Donor Tools every page is a report. Adopting this simple philosophy has allowed us to almost completely eliminate the need to build dedicated reporting features. And it was almost effortless to implement – it took maybe a couple of hours.
CSS aficionados should recognize this trick already: it’s called print style sheets. Basically you have one set of stylesheet for screen display, and a separate set of styles for printing. This works in just about every modern browser, even the inferior ones. And the great thing about print styles is that we often don’t need to worry about complicated positioning or page flow – just provide some basic style instructions, hide non-printable controls and headers, and it looks beautiful on paper.
This has, of course, been discussed elsewhere, but I’m going to show you how we put it to work for Donor Tools.
I like to use CSS Edit, which in my opinion is the cream of the crop of CSS editors.
The first thing I do when I’m ready to start working on the print style sheet is to think about what I want to show up on paper, and what should be hidden. Opening up my page in CSS Edit, I use the X-ray tool to examine the blocks and divs that construct the page. Good HTML construction at this point is crucial to being able to target specific areas of the page.

Next, I turn off all the screen styles and switch the print stylesheet to display on the screen. Donor Tools is built in Rails, so a quick edit to the application.html.erb file is all that’s needed:

Flipping over to CSS Edit, now I can edit my print.css stylesheet with instant feedback.

I’ve turned off a lot of divs by targeting the names of the elements, and then applying display:none;. I also made a generic style called .noprint that I can apply to any random elements that should not print.

That’s it! Now, when someone uses their browser’s print function, they’ll get a beautiful, well-styled printout of what they’re looking at on the screen with no extra effort.
I talked about another approach in Easy Printable Pages with Rails
Subscribe
Network
Archives
- November 2008 (1)
- October 2008 (7)
- September 2008 (4)
- August 2008 (4)
- June 2008 (2)
- April 2008 (1)
- March 2008 (1)
- February 2008 (5)
- January 2008 (1)
- December 2007 (1)
- November 2007 (4)
- October 2007 (1)
- September 2007 (1)
- August 2007 (3)
- July 2007 (2)
- June 2007 (5)
- May 2007 (6)
- April 2007 (3)
- March 2007 (4)
- February 2007 (5)
- January 2007 (5)
- December 2006 (6)
- November 2006 (1)
- October 2006 (8)
- September 2006 (12)
- August 2006 (7)
- July 2006 (6)
- June 2006 (6)
- May 2006 (2)
- April 2006 (17)
- March 2006 (15)
- February 2006 (7)
- January 2006 (12)
- December 2005 (25)
- November 2005 (11)
- October 2005 (3)
- September 2005 (2)
- August 2005 (4)
- July 2005 (5)
- June 2005 (1)



