Tuesday, December 28, 2010

Things not to say to the customer

Yes, I know this is irreverent, but I'm a bit punch happy, so here are some ideas about things that one should not say to the customer. Especially one who has been pretty good about getting slow support.

  • After banging on this product for over a year, we’ve moved on emotionally, spiritually and strategically. The product is going to phased out soon and we’re really busily focused on doing things that generate a whomp-load more revenue right now. So, for right now, we’re just plugging our ears with coffee grinds and ignoring the problem
  • My apologies for the delay. My mom says I shouldn’t talk to you.
  • Thanks for following up on this. Unfortunately the work to dig into the product issues has temporarily been put on an indefinite hold.
  • My apologies but a traumatic brain injury has wiped out all my memories and knowledge of who you are and what you do. Could we start over?
Clearly, someone in Sales needs to pick up the phone. Hello, Sales? Um, Sales?

Ah. They're out, erm, networking.

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.