Showing posts with label ruby on rails. Show all posts
Showing posts with label ruby on rails. Show all posts

Tuesday, October 16, 2012

ActiveRecord, JSON & hashes

While testing a new script for some data loading, I found myself on our testing platform and stymied because the foundation things I needed were not part of that database.  I needed certain license records and Forge records.  While the staging system has a more or less complete copy of our production system, the testing system has a much more constrained data set.  This is a one of my bugaboos: making sure there is sufficient data for testing. And, once again, I questioned the decision to NOT use TDD for the script development.  That way, I could have mocked all the scenarios I needed and probably would have completed the script in less time to a greater level of quality.  But I digress.

I was in the console of the testing environment (not the "test" environment) and needed to have a particular license as part of the testing dataset.  I wanted to use the tools I had, not have to write a migration, start up PSQL, or any of those pathways.  I wanted to be lazy and get the record from the staging environment and copy it into the testing environment.

So, I found the license in the staging environment and converted it to json with license.to_json. That was wicked easy.  The next step was to parse the JSON, which will convert it to a hash, then extract the license value. That looks like this:

license_hash = JSON.parse(json)['license']

The result was a pretty little hash with all the necessary data that could be copied from one console to the next and then pasted into place.  In no time at all, I had the needed record in the testing database.

Tuesday, August 28, 2012

Ruby & Rails Tools: Pry, Guard, Spork, RubyFiddle, Null Object Pattern

Here are some Ruby and Rails things that have caught my attention.  In the interest of sharing and documentation, in no particular order:

Pry is a powerful alternative to the standard IRB shell for Ruby.  I learned about it at CodeSchool, on one of the Code-TV videos.  Pry provides source code and documentation browsing, the ability to live edit defined methods, syntax highlighting, command shell integration and other things of goodness.

Also recommended is the CodeSchool Code-TV episode on Guard and Spork, which look like a great 1-2 punch for driving TDD.

From a recent Ruby MeetUp at the Punchbowl  place in Framingham (thanks for the hospitality, pizza and beer!), I picked up these two tidbits:

RubyFiddle is a website that lets you try out Ruby code in the browser and save snippets as gists.  It lines up nicely with my personal philosophy that to be a great ROR engineer, one needs to be a great Ruby engineer. RubyFiddle has easily selectable key bindings for none, vim or emacs, which I find rather considerate and helpful.

I also learned about the Null Object Pattern, which has some compelling features and deserves to be in the toolbox of the enlightened engineer.

Thursday, May 20, 2010

Rails alias_method_chain explained with pictures!

I've been meaning to do this for a while because I keep coming across alias_method and alias_method_chain in Rails code. I understood what was going on, but felt that I never grokked it. So, I finally mapped out what happens, drew some pictures, and, voila! Enlightenment!

Since I firmly believe that the best way to learn something is to teach it, I thought I would document what I learned in the hopes that it will be beneficial to someone else and firmly cement my understanding. So without further ado:

It is important to keep in mind that a method name is essentially a constant symbol and points to a block of code. "alias_method" is a Ruby class Module method with the signature:

alias_method(new_name, old_name)

And, "alias_method_chain" looks like this:

alias_method_chain :method_name, :feature

That's the easy part.

For the purpose of this example, I'm examining the behavior of:

alias_method_chain :render, :feature

The alias_method method makes a copy of the method block and assigns the new_name constant to point to the copy of the method block. So, it looks something like this:

Here's the method render and its method block:


After we call alias_method :render_without_feature, :render we have the following:
At this point, if we wanted to, we could redefine the render method, which would replace the original {render} block with new functionality. And, as it is often explained, the original functionality is still available at the render_without_feature method.

However, as it is often explained, what is desired in Rails library code is to redefine an existing method while saving the original functionality under a new name. Therefore, what we see in Rails code was often:

alias_method :render_without_feature, :render
alias_method :render, :render_with_feature


We already looked at the first line. Let's look at the second line.

The second line is assigning the constant "render" to a copy of the "render_with_feature" functionality. It looks like this:
Now, render will call the code block with the new feature and render_without_feature will call the original render block.

This is the key to the entire Rails helper, alias_method_chain, which takes the name of the original method and the name of the feature and does this mapping for us.

Therefore, the two alias_method calls above can be replaced with the following:

alias_method_chain :render, :feature

You, the fine engineer, will define a method render_with_feature and the render symbol will point to it. And, after the alias_method_chain call, you will have a new render_without_feature method created for you.

I find all of this rather elegant and hope this has been helpful

Sunday, January 17, 2010

Spike: Analyzing Rails Development Logs

As venerable as 'tail -f log/development.log' is to a Rails developer (and as undeniably useful as well), I've been using another tool that has been tremendously helpful in weeding through all the noise. Spike, written by Matt Mower with help from the Rails community, parses your development log and presents, in two windows, summary information and a detailed view.

Spike lets me see the flow of the application by filtering out records that aren't pertinent to what I'm looking for. For example, the 5 second refresh event coming in from EVERY browser -- ZAP and they're gone! I can filter by request, IP, session ID and so on. The detail viewer shows me all the parameters, the renders and all the activity in the log that is part of the request.

This has been a very helpful tool; my thanks to Matt and everyone who worked on Spike!

Saturday, January 16, 2010

Lesson that I keep learning

While writing specs I keep learning this lesson over and over. After calling methods on your data model and saving it to the database, call the reload method to refresh your model. Otherwise, subsequent operations will be performed on stale data.

Do this in your engines and other business logic components that change & persist data. When calling myObject.do_something, which changes and saves internal state and you need to continue using myObject in the rest of your method, first call myObject.reload.

There. I've gotten it off my chest and I feel better.

Friday, January 15, 2010

VICTORY: FactoryGirl and Database Rollbacks that Failed

Draw near my children and listen to a terrible tale of trial, tribulation, twisting torment, teething, temper-tantrums, truculence, and truancy. Except the teething part. And there may have been truffles.

Seriously, I was ready to walk away from FactoryGirl. Perhaps you have heard of FactoryGirl, yes? Perhaps you have encountered records left in the database after the test completes. Perhaps you Google for all sorts of phrases like "FactoryGirl records left database" or "FactoryGirl rollback". Perhaps you scoured Google groups, the rdocs and all of that stuff. Yah, me too.

Yes, "use_transactional_fixtures" was true and "use_instantiated_fixtures" was false. I searched the entire code base. So did you.

But, I'm using rspec, so there is no test_helper. Spec_helper has slightly different syntax from test_helper, so "self.use_transactional_fixtures" won't work. You're using FactoryGirl, so you don't have any fixtures. I deleted mine; get that cruft out of the way. Heck, I deleted my entire test directory!

But I finally got it. And it seems so easy now. Like childs play, just like in Spock's Brain, when McCoy had to re-attach Spock's brain. And, hopefully this will help you too.

Make sure you have a fixtures directory. Mine is in RAILS_ROOT/spec, so I added the following line to my spec_helper.rb:

config.fixture_path = RAILS_ROOT + '/spec/fixtures/'

Then I told Spec::Runner that I had fixtures, even though the directory is empty! There is a fixture entry for every table that was not getting reset. For example, the users table was not getting reset, so I set:

config.global_fixtures = :users

And, when I needed the players table cleared, I added the following:

config.global_fixtures = :users, :players

That's it! All better. Rspec now clears up those tables just as purty as you please and the tests are passing -- big bars o' green! Yippee!

Monday, January 11, 2010

Good Ruby on Rails Tools

I'm looking at the following tools to add to my Ruby on Rails tool chain:

Continuous Integration

RunCodeRun at runcoderun.com
CruiseControl by Thoughtworks

Scalability

I'm excited by the products talked about at the NewRelic scalability blog. I saw the first episode and am very psyched about bullet by Richard Huang.

Metrics & Monitoring

Can't wait to try out Caliper for Ruby metrics and NewRelic for monitoring

I'm using SVN on a few projects, but I have been in the promised land and can't wait to get back to git, so let's add GitHub to the list.

Friday, November 13, 2009

Event callbacks in AASM

Having written about AASM in the past, first on Chaining state transitions with Acts As State Machine (aasm), and then again in Conditional state transitions with AASM, I thought I had AASM down rather pat.

However, when I tried adding a callback to the aasm_event, I ran into trouble. Quite simply, the callback never worked. Here's the first code:

Notice that the callback registration is in the aasm_event code block. It seemed reasonable that this would be part of the transition. When I determined that this was not working, I had a colleague review the code and we ended up both scratching our heads.

So, I cracked open the library and poked around. I saw the successful aasm_state call displaying the callback registration in the options portion of the method, but the options of the aasm_event were blank. Hmm!

Here are the method definitions for your edification:
aasm_state(name, options={})
aasm_event(name, options = {}, &block)

Well, it was pretty clear how to fix the problem; move the callback registration after the name argument and before the block. Here's the corrected code:
That's it! Have fun.

Friday, October 30, 2009

Fast Online Documentation - GotAPI.com

When I'm coding and have an API question, I have one and only one demand from my documentation source -- speed. I want to be able to quickly find the information I seek. "Now. I want it now."

I use PDF versions of my favorite books and the generated Ruby 2.3.4 API documentation locally, which is all good, but I found something that may be even better. GotAPI has a clean interface, is wicked fast and utterly intuitive. It even holds your recent searches.

In addition to lightning fast Ruby and Ruby on Rails look ups, it has tabs for HTML, Javascript DOM and CSS; all the things I need during RoR development!

I've added it to my browser bar so I can get to it quickly and it's rapidly becoming my reference tool of choice. Highly recommended.

Saturday, October 10, 2009

Chaining state transitions with Acts As State Machine (aasm)

Have you ever had state transition requirements that required automatic chaining of transition changes? I've got a system that transitions to a "to_reviewer" state after it has been created.

In the "to_reviewer" state, a group of reviewers are presented the assignment and they may accept the assignment, or a project manager may assign the assignment to a reviewer: in either case, as soon as there is a reviewer assigned, the assignment transitions to the "reviewer" state.

However, if the system already has a reviewer assigned at the "created" event, then it should cascade the state transition change and go directly to "reviewer" without staying in "to_reviewer"

Having selected the Rubyist AASM gem to implement my state machine in this Ruby on Rails project, I expected that I would be able to use the :after options of the aasm_state statement. I got that idea from the README.rdoc for version 2.1.1, which lists "event:after" in the callback chain.

However, the :after callback is called on an event (aasm_event) and I can't find documentation on how to hook into that callback. Digging into the the code, I found the following syntax works correctly in my Assignment object (derived from ActiveRecord). The solution is to use the :after_event option in the aasm_state definition statement.

This first part defines the states:
aasm_initial_state :task_created
aasm_state :task_created

aasm_state :to_reviewer, :after_enter => :check_reviewer
aasm_state :reviewer

This next part defines the events:
aasm_event :created do
transitions :to => :to_reviewer, :from => [:task_created]
end

aasm_event :task_review do
transitions :to => :reviewer, :from => [:to_reviewer]
end

This last part is the definition of the :after_enter method:
def check_task_reviewer
task_review unless reviewer_id.blank?
end


Now, when the object is created, the aasm_current_state is "task_created". If the object receives the "created" event, it transitions to the "to_reviewer" state. However, after the object enters the "to_reviewer" state, the "check_task_reviewer" method advances the state again if a reviewer as been assigned (indicated by the presence of the reviewer_id).

Checking the code in the console, we get:

>> a = Assignment.new
=> (Assignment object information)
>> a.reviewer_id = 5
=> 5
>> a.save
=> true
>> a.created!
=> true
>> a.aasm_current_state
=> :reviewer

And we can see that the object transitioned through the "to_reviewer" state an on into the "reviewer"state.

Thursday, October 08, 2009

The Ruby Toolbox

I've had the good fortune to stumble across The Ruby Toolbox.

This delightful site is filled with collections of helpful, nifty plugins and gems that help make the life of any Ruby and/or Rails developer much more pleasant. There are some 75+ different categories that deal with ActiveRecord, Backups, Code Metrics, CSS Frameworks, E-Commerce, Game Libraries, Gem Creation, and on, and on.

Not only are projects, gems & plugins listed, but they are rated in terms of how much attention the project is receiving. The most popular projects are listed at the top with an attractive scale along side to the right to help you compare the popularity of different options.

If you're doing Ruby and/or Rails development and haven't visited this site, then you really deserve to do yourself a favor. I'm headed there now!

Sunday, September 06, 2009

Installing Spree eCommerce

I'm looking to update a website that was written in a decent, but not great website creator application. I want to write it in Rails (yea!) because I had such great fun creating the Zepatter.com website. I mean, that took less than 12 hours from sitting down with the GIMP to getting the application installed on the hosting environment. And a huge chunk of that 12 hours was figuring out how to get the hosting environment configured correctly. hehe.

So, I'm looking for an eCommerce engine for Rails. Yes, I could create the whole shopping cart and payment gateway on my own because there are tons of tutorials and general advice. However, I suspect that if I could find a full-featured engine, then someone else will have thought of -- and solved -- problems that will take me time to recognize and address.

So I came across Spree eCommerce.

However, I haven't updated Rails on my system in a while and Spree requires Rails 2.3.2. So I start by doing a

sudo gem update rails


which gets me to Rails 2.3.4. However, Spree wants 2.3.2 ONLY. So I remove Rails 2.3.4 and install 2.3.2. Then I install Spree according to the instructions. Then I try to create my first Spree application with:
spree mystore
Unfortunately, I got this error:
/usr/local/lib/ruby/site_ruby/1.8/rubygems.rb:578:in `report_activate_error': RubyGem version error: hoe(1.5.3 not >= 1.8.0) (Gem::LoadError)

OK. No problem. Need to update hoe
~/src:sudo gem update hoe
Updating installed gems
Updating hoe
ERROR: While executing gem ... (Gem::InstallError)
hoe requires RubyGems version >= 1.3.1

OK. No problem. Need to update gem. After all,
~/src:gem --version
1.2.0
So I do the following:
~/src:sudo gem update --system
Updating RubyGems
Nothing to update
OK, this may be a problem. Referring to the rubygems documentation, one needs to do the following:
gem install rubygems-update
update_rubygems
However, this failed with:
~/src:sudo update_rubygems
/usr/local/lib/ruby/site_ruby/1.8/rubygems.rb:578:in `report_activate_error': Could not find RubyGem session (>= 0) (Gem::LoadError)
from /usr/local/lib/ruby/site_ruby/1.8/rubygems.rb:134:in `activate'
from /usr/local/lib/ruby/site_ruby/1.8/rubygems.rb:158:in `activate'
from /usr/local/lib/ruby/site_ruby/1.8/rubygems.rb:157:in `each'
from /usr/local/lib/ruby/site_ruby/1.8/rubygems.rb:157:in `activate'
from /usr/local/lib/ruby/site_ruby/1.8/rubygems.rb:49:in `gem'
from /usr/local/bin/update_rubygems:18
Mark Howe has a helpful blog on the matter.

In the end, the trick was to uninstall the partly installed rubygems 1.3.5, install rubygems 1.3.4, then do the
update_rubygems
And all was well. I was able to update hoe and then successfully run
spree mystore

Tuesday, June 09, 2009

Supressing Object#id deprecation warnings

I picked up some Ruby on Rails code up which I was working a few months ago to complete the project. While adding and running my rspec tests, I started getting the following warning during test execution:

"Object#id will be deprecated; use Object#object_id"

The warning was coming from the super_inplace_controls plug in that I was using. I really like these controls, and wanted to clean up the warning.

So, I popped open vendor/plugins/super_inplace_controls/lib/super_inplace_controls.rb and checked out line 234, from which one of the warning was eminating.

Sure enough, there was, in the method id_string_for, the line:

"#{object_name}_#{method_name}_#{object.id}"

No problems, I'll just change "object.id" to "object.object_id". I did this here and on line 260 in the form_for_inplace_display method.

Of course, this broke the code and the in-place object no longer received its updates after changing a value. The ID part was necessary to retrieve the updated record and display the correct value after update. So I backed out my changes.

Some more searching and I came across a way to suppress warnings around a small block of code, which is exactly what I wanted. I didn't want to suppress all warnings, but I knew that the object.id had to be there (truth be told, I should have tried using just "object"); I just didn't want to hear about it.

To suppress the warning, I wrapped the offending line in Kernel::silence_warnings() {}. So the id_string_for method become:

def id_string_for(object_name, method_name, object)
     Kernel::silence_warnings {
        "#{object_name}_#{method_name}_#{object.id}"
    {
end

I tried the same thing for the form_for_inplace_display method and ended up putting the whole method into the silence_warnings block due to the scoping problems the block introduced.

The danger to this whole method is that, should this code base advance into a new version of Ruby or Rails where the object.id call causes an error, code that seems to work will suddenly break. On the plus side, this won't be a complex logic bomb to solve, but should come up right away in a standard testing cycle.

Friday, May 29, 2009

How to Get Real in Corporate Development, Part VI

This is the sixth part of a series of essays on how to leverage the concepts of Agile software product development from Getting Real from 37signals in a corporate development organization. Part I introduces the concepts of Getting Real, part II looks at the idea of building less, part III is on focusing on one idea, part IV is on getting something functional out quickly and part V talks about focusing on how your users will use the application.

Now it's time to look at:

Focus on fulfilling business stories, not big specification documents.

In my 20+ years of technology experience, I have seen this as being the biggest and most pervasive problem. And I understand that it comes from a very valid perspective from the engineering community.

Engineers can not easily manage huge amounts of change to requirements. Imagine building a bridge if the length of the span changes weekly, the material under the footings shift regularly and the sponsor wants the bridge in steel; no, titanium; no, wood; no, aluminum; no, steel -- you get the point. Therefore, engineers seek to define the requirements and get agreement and sign-off on those documents so they can build something once. Plus, we all know that change gets more expensive as a project progresses, especially if you have a waterfall or spiral approach. All that inflexible foundation work is very expensive to change. (Another reason to stay light and agile!)

Because of the cost of constant change, engineers push to define requirements up front so that they know what to build and where to start. They require definitions, use cases, scenarios, storyboards, and so forth. From this collected material, they define the grand scheme, break it down into delivery phases and get agreement and sign-off. Again, they want to build something once.

The flaw with this approach is that the requirements cannot be entirely known in advance. Therefore, just as soon as the project starts, the huge requirements specification is out of date. I once worked on a project with over one thousand distinct requirements. Because we were inventing new science and technology while producing a commercial product, the requirements churn was huge. We touched every single requirement dozens of times; the requirements churn topped 1000%!! That's like writing over 10,000 requirements! It was nuts!

Here is the fix: Focus on business stories. Start with the most important story. It works like this.

The business problem is, "We have to generate an inventory spreadsheet daily by running a report in our inventory management software (IMS), copying the date and transforming it into Excel, then cleaning up the data by re-arranging the columns and saving it as a semi-colon delimited file so it can be emailed to the web services group so they can update the inventory counts on the website. Errors and delays in the process can mean displaying products as in-stock when they are currently back-ordered, which annoys customers."

The business story becomes, "We want to automate the daily inventory reporting from our IMS to our web server to increase accuracy, decrease information turn around time, and free business resources for other work."

I can immediately see a number of ways to do this, from using whatever automation exists within the IMS to generate and send that report, or accessing the IMS database directly with a custom report, or using the IMS database programmatic API to write an automated application to pull the data and update the web database, or to make the web database read its data from the IMS database live, or on a daily batch bases, or exposing a web service so the data can be pushed into the web database. I bet you have a few more options.

The take away is that solving the technical problem isn't usually the problem. The problem is solving the correct business problem. Getting bogged down with a huge requirements document doesn't make solving today's problem go any faster and doesn't produce a solution to today's problem any faster.

So, how would I apply this advice to that huge 1000% churn project? Well, the biggest constraint was that we had to produce a commercially shippable product. A goal was to create a single architecture that could be leveraged along the future product line. However, since we were creating new technology and a new command and control system, we set the bar too high.

The immediate business story was to operate the machine and provide a sufficiently flexible control system that would allow for the scientific invention to continue without requiring huge software re-writes. Today, I would drop the goal that we create an architecture that could handle future demands. The project was already very challenging without that goal and we ended up pulling out all the infrastructure that was built to handle that goal anyway, just to get the first product to ship.

We made the classic mistake of solving tomorrow's problem before solving today's problem. You can avoid that mistake by focusing on the business stories that you have today and not creating that huge, over-arching requirements document that will doubtlessly saddle you to a very sizable ball and chain.

Thursday, April 23, 2009

Using Getting Real Concepts in the Corporate Office

The talented and intelligent folks at 37signals have created some great applications. As major contributors to Ruby on Rails, they also have been fundamental in building and leading a revolution in rapidly developed, high quality web applications. 37signals is successful because they think creatively about the problem that they are trying to solve. Fortunately for all of us, part of that thinking is that they should be open and transparent with many aspects of their process and business. Therefore, they often preach about the practices that have helped them attain success.

Anyone can read their preachings online. For free! It's a great concept, and one that is often encouraged by industry leaders -- think Seth Godin for one.

You can also purchase a high-quality bound copy of their book “Getting Real” from Lulu.com. I have because I like being able to read when not in front of the computer. It’s all laid out in their book (the exact same copy in the web pages, downloadable PDF or book) – their philosophical approach to clients, development, hiring, customer service, and so on.

When I became aware of 37signals , I was developing Ruby on Rails web applications. Because I was creating web apps, which is clearly the focus of the book and philosophy, I found myself agreeing with just about everything they were saying. And hey, I’m a software development veteran.

I’ve done this for years and years and have focused extensively on managing complex projects to successful deliveries. I’ve been through waterfall, spiral, iterative, agile, ad hoc, chaotic, random and panic-driven development models. I agreed with what they were saying because it makes sense and I was able to make it work successfully on my projects without any pain or difficult transitions. There aren’t many “new” development philosophies about which that can be said! For light, flexibile web apps, “Getting Real” made total sense and, more importantly, it worked.

But what about corporate environments with ongoing development efforts? These shops have a different set of starting points and different base assumptions. What if you aren’t developing a web app? What if you aren’t focused on revenue generation with your app? What if your users are waiting for their application and have expectations about how it will help them?

Can your corporate development efforts also Get Real? Yes, I believe that they can. let's look at the components of Getting Real that will help your corporate development teams use the principles from Getting Real to improve productivity and stakeholder satisfaction levels.

Let’s start with some of the key concepts of Getting Real that are directly beneficial for all development efforts. (Links are to the essays on those concepts)


  1. Build less. Build smaller applications with only the most important features and deliver it quickly.
  2. Focus on one idea. Start with the big problem, build the large scale functionality and don’t sweat the details.
  3. Get something functional and useable deployed quickly. Plan on your next release right away. Make a choice and go with it.
  4. Start with the UI design and focus on how your users will use your application.
  5. Focus on fulfilling business stories, not big specification documents.
  6. Keep your developers on the front line of support
  7. Be willing to radically change the application to make it better. Resist the urge to make one monolithic tool to solve everyone’s problems at once.

Notice that these nuggets are completely environment, tool, and technology agnostic. There are some radical ideas that will doubtlessly shake up the “way things are done”, but these are the right ideas to grab onto and the right changes to make.

Fortunately, there are some components of Getting Real that an internal corporate development group can safely ignore right off the bat. For example, you’re probably not looking to generate revenue with something like an internal workflow enhancement tool. Not that you can ignore development costs or the value proposition of the development effort, but at least your users won’t be facing the prospect of paying a monthly fee. (Although, there may be something here….)

You can safely ignore the need to market and promote your application extensively. Please note the qualifier. The new whiz-bang tool you’ve developed for Operations is straight sunk costs if end users aren’t using it. Therefore, they do need to know about it and they should be excited about its arrival and feature set. But that should come from good communications and interactive product development and not from promotional marketing campaigns. Trumpeting successes is always allowed, however, so some allowance is made, but we’re not talking at all about the same degree of importance of marketing discussed in the book.

Most importantly, as you – the development lead, manager, director, VP, CTO, Whatever – read Getting Real, you can insert your favorite technology du jour whenever the book talks about web applications. The thrust of web apps in Getting Real is their rapid deployment and instant accessibility to customers. No CD burning, no distribution efforts, no retail operations, etc.

But let’s face it, how long does it really take to deploy a new version of an internally developed application in your shop whether it was written in C++, Java, Lotus Domino, C#, .NET or Ruby on Rails? If you’re thinking “weeks”, then you’ve got another problem, don’t you? You can quickly push out new applications through automated corporate update mechanisms, internal web sites and internal installers with the exact same degree of responsiveness that is the base assumption in the book So don’t sweat it that you’re not making a web app. The underlying philosophies in “Getting Real” remain pertinent, applicable and valid to you and can revolutionize your development centers.

The next essay will look at those seven take-away concepts in greater detail and will focus on how you can leverage these concepts to make high quality software faster.

Monday, December 08, 2008

Replacing ActiveRecord with DataMapper in Ruby on Rails

This is for the technically minded as it deals with replacing ORMs in a Ruby on Rails application.

I recently had an opportunity to do a little presentation and I chose to talk about replacing the ActiveRecord ORM (Object Relational Mapper) with DataMapper in a Ruby on Rails application. DataMapper was incredibly fast at returning records. For a single table look up, it took 0.0150% of the time that ActiveRecord took to return all 10,000 records. Holy Toledo!

Here, check this out. This is a series of benchmark runs between two nearly identical applications. They both have the exact structure, number of pages, etc. and same number of pages. But, one application is using ActiveRecord and the other is using DataMapper.

10,000 Records recalled with ActiveRecord









usersystemtotalreal
#1 1.050000 0.040000 1.090000 ( 1.227590)
#1 1.050000 0.020000 1.070000 ( 1.222924)
#1 1.080000 0.020000 1.100000 ( 1.250905)
#1 1.100000 0.030000 1.130000 ( 1.288719)
#1 0.860000 0.020000 0.880000 ( 1.724392)

Average: 1.342906

10,000 Records recalled with DataMapper









usersystemtotalreal
#1 0.000000 0.000000 0.000000 ( 0.000198)
#1 0.000000 0.000000 0.000000 ( 0.000196)
#1 0.000000 0.000000 0.000000 ( 0.000204)
#1 0.000000 0.000000 0.000000 ( 0.000205)
#1 0.000000 0.000000 0.000000 ( 0.000202)

Average: 0.000201

Datamapper requires 0.0150% as much time as ActiveRecord

One cool thing about doing this presentation is that when I started encountering problems with working on Rails in XP (although I know it is possible for the most part), I decided to create a Linux installation. My first thought was to repartion my hard drive and install Linux there. But, I'm using an older machine and was afraid of data loss (fortunately, I use an online backup solution for recoverability, but there is still all that work to do). Therefore, I ended up creating a persistable Ubuntu 8.10 installation on a 2 GB Flash Drive. That will have to be a topic for another post.

The presentation is available on SlideShare for your viewing pleasure. I walk through the steps in the presentation after a very quick overview of ActiveRecord and DataMapper. The source is available on github.

Please use the SlideShare posting and the github source for your resources. I used the DataMapper web site, of course, as a primary reference. I also used
François Beausoleil's blog, How to Use DataMapper From Rails, Including Migrations and Tests, to get started.