Archive for the ‘rails’ Category

OFX for Ruby

Monday, July 16th, 2007

Okay, it’s official. I’ve put my money where my loud mouth is; my first open-source project. I know what you’re thinking: so?

Well, for me, this is an important step. I’m a leecher. I’ve been a leecher since I was Icarus on Capricious Alliance (I tried to find any reference to this Baton Rouge-based BBS system for href-ing purposes, but alas). Open-source challenges me to stop leeching, to give something back, to do more than lurk and hide.

I’ve been working on a home management system in Ruby for some time now. It’s my classic side-project/magnum opus, a toy in Ruby and Rails that’s growing into something that might be worth it. It’s far too early to tell, and definitely too early to release anything, or even put the code up for public perusal/contribution. It’s not that I’m unsure about my intentions; this project/system will definitely be open-sourced in the long run.

One of the major subsystems of the home management system is the finance package, which includes a full double-entry accounting package (inspired by Fowler’s Analysis Patterns (1997) — an incredible read with updates still coming on his website). The overriding principle of the home management system (I’m just calling it “Home” for now, but I’m sure that’s too broad of a name to trademark) is to bring enterprise-level systems to the home. I also grew interested in building an accounting package for Linux, for which the pickin’s are indeed slim (no offense, GnuCash, you guys have a great product, but there must be options!)

After going down the path of building a manual journal for entering transactions and a very rough QIF import utility, I knew I’d never use the thing myself (and would never recommend it to anyone else) unless it had online banking. In the US, this pretty much means OFX. So I needed a parser.

I didn’t know the first thing about parsers, so I scoured open-source land looking for any kind of OFX implementation that might get me started. I had the peculiar constraint of insisting on pure Ruby, so this left libofx and friends right out (although, trust me, I tried to sell myself on it). Other than that, I found the ofxrb project that was in it’s adolescence, run by Adam Williams. I touched base with Adam, but I think we had some different goals in mind. So I went it alone (for now), and developed OFX for Ruby.

Even now, it’s capable of exchanging nearly all of the read-only message sets with an OFX 1.0.2 financial institution (which was my first immediate need). I am explicitly going to have to steer clear of the destructive message sets (bill payments, transfers, etc.), because my fanatical need to write and run tests and my critical lack of a test server are fundamentally incompatible at the moment. (Open solicitation to any financial institution with a friendly attitude to open-source: give me access to a test server and you won’t regret it!)

Thanks to the administrators of RubyForge (Tom, I think it was) for the excellent turnaround on provisioning the project and just for having a great system in general.

First post (again)/Ruby (again)

Saturday, February 3rd, 2007

Got bit by the Typo bug, then got bit by Typo, so I changed to WordPress (I still love you, Rails). I’m starting this blog off with a little re-cap of my Ruby and Rails flails over the last few months.

I’m infected with Ruby/Rails. It’s a disease. Every conversation I have with someone about technology, programming, and the Web ends up coming back to Ruby and Rails. My friends are sick of me, seriously. It’s not my fault, I just have to tell people the Truth, and when I do, it ends up referring back to Ruby and Rails.

My friends in strong-typed land, please give me one chance to change your mind with a little story about Ruby. Ruby has an (okay) unit testing library called Test::Unit that is now part of the standard Ruby library. It has the features you’d expect of a unit testing library, like defining test suites, running test methods, making assertions and outputting little dots to the console as each test passes. I usually do all my testing from the console, whether I’m using nunit-console.exe or Test::Unit scripts in Rails. I find that I get much more rapid feedback about my tests and I have long ago let go of my need to literally see the red/green lights to iterate my red-green-refactor cycle.

One pet peeve of my (I have few) is when either my code or (worse) someone else’s code is writing out to the console during my unit tests and messing up my beautiful uninterrupted string of dots. So I’m working on some console-style scripts to augment a Rails application I’ve started recently (don’t worry, once they’re something to blog about, it will be here), and like a good tester bee, I want all of my features to be tested. So I whipped up some integration tests that would flex out my console tools, replete with OptionsParser testing to make sure all of my console options were covered. Looked great. So I ran my first tests, which just used the “backtick” method to invoke a console command from the Kernel. Which looks something like this in Ruby code:
`myscript --option-one -a=abc`
and will run that text verbatim at a new shell for your OS (bash for me). My tests passed and things were groovy. Then I checked my code coverage report from RCov (I’ll post later on how I use RCov in my Rails work), and found that my console tools weren’t getting covered by RCov. They’re forked off in new processes by the backtick method, and RCov isn’t going to instrument them there. D’oh!

At this point I hadn’t lost faith, so i decided to use the load method for my scripts:
load 'path/to/myscript.rb'
but I was lacking a way to pass my command-line arguments, and I ended up just making a hacky global variable for them. So I run my tests again and see to my horror that all of the console junk I was writing out in my console scripts was showing up in my test results (my beautiful linear dots!)

Now I’m getting serious. I’ve got coverage, but I’ve also got this mess. So I start thinking about Ruby and how it’s supposed to let you do anything you want. If I want to redirect the console output for the duration of a test method, I should be able to do that, right? Well, the answer I came up with might seem a little extreme, but it worked wonderfully, and I also have some code to share:

def execute_console_tool(consoleTool, arguments)
# redefine puts
Kernel::module_eval(< @@old_puts = method(:puts)

@@output = ''
def output
@@output
end

def puts(*args)
args.each do |arg|
@@output += arg.to_s + "\n"
end if (args != nil)
end
end_of_eval
)

# set the command-line arguments and run
$commandLineArguments = arguments
load consoleTool
Kernel::output

ensure
# make sure puts is always put back
Kernel::module_eval(< remove_method :output
remove_method :puts
define_method(:puts) { |*args|
@@old_puts.call(*args)
}
end_of_eval
)
end

I dropped this method into my Rails test_helper.rb class, and then I can call it from my unit tests:
execute_console_tool('path/to/myscript', ['--version', '-a=b'])

How sweet is that? Okay, I admit, this isn’t really “elegant” in the sense that most Ruby code is elegant. But what I want to illustrate here is that Ruby is truly dynamic and even the “built-in” features are malleable at run-time. This is impossible in a statically typed language (or at minimum would require an enormous array of hacks, much more than this code).