Category Archives: cool tools

A Java Developer’s Switch to Rails

As I read this account of transitioning from Java EE to Ruby on Rails,”Java Web Apps to Rails, A Developer’s Experience,” I thought the following:

Regarding the lack of a good Ruby/Rails IDE:

When it was time to look at the code, I was a bit disappointed.  TextMate looked like a popular choice but it fell short in many ways.  I struggled to navigate the code, link the methods across files and follow the code. Grep was my only savior.

I am surprised he did not find RubyMine. JetBrains makes awesome IDEs (IntelliJ IDEA for Java, too). I have to admit at being very impressed that the underlying model of the ruby code within the RubyMine IDE is amazingly capable of giving you the same sort of features that it can for a “compiled,” or more type-centric language like Java.

Ruby

Next he mentioned about learning the language…

My approach to learning Ruby was to start looking at code and figuring out pieces of syntax that did not make sense.  That turned out to be a bad idea. Constructs like “do |x| x+1” threw me off. … I found it very important to understand the motivation behind creating the new language.

There are some good books out there, and other resources…

Another comment rang true with me:

I found it very important to understand the motivation behind creating the new language.

More about the motivation behind Ruby… or at least, how I interpret things.

Ruby treats you like an adult. It doesn’t baby you, or hold your hand, or make you type all sorts of (obfuscating, in my opinion) fluff that a compiled language needs. Your code is more compact and obvious and “dense with meaning,” leading to less need for things like method return types and method parameter data types. Or semicolons.

However, I miss parameters list, curly braces, return statements, camel case naming conventions…

Be patient… soon you will grow weary of having to read all that extra stuff when you go back to Java. If you write well-formed classes, and very small, compact, and obvious methods, you don’t need the extra frills. You will run across the concept of “duck typing” which really means that classic C++/Java/C# style interfaces are not needed. If you create a method that expects a passed-in object to respond to a method call (e.g., “torque”), any object of any class will do — as long as it has that method call! And if you pass in an object that does not have that method, Rails will kindly throw an exception.

The concept of ‘open classes’ that allow developers to go in and change a base class sounds scary.

Go back to my opening statement. “Ruby treats you like an adult.” If you are naive, you can blow your code up and break stuff. If you do everything the Ruby way, you’ll be fine — because you will catch it with tests (right?). There are good rules of thumb for how and why and when you should consider adding to an existing class — or worse, monkey-patching. In Ruby you can actually alter the behavior of an existing method of an existing class. Do it poorly, and you will pay the price. And maybe not for a year or two. Mwahahahaha.

Ruby’s metaprogramming is incredibly powerful (even if the syntax takes a bit of getting used to).

Rails

Rails is incredibly opinionated about how the MVC code should look. It is basically a model-driven architecture approach. The framework expects the MVC stack to have a model, a view, and a controller for each domain concept. (As a long-time domain modeler, and UML guy, this is a real treat.) You can use the default rails generators (interesting when first starting, or for banging out a quick prototype), or write your own twist on a generator. Instead of focusing on the boring framework bits with repetitive, template-like code for each domain object, you can focus on quickly creating features that people want to use and pay for 🙂

Supporting Cast

Ruby on Rails has a great ecosystem of wonderfully talented folks providing 1000s of gems to do all sorts of useful things. For example:

The ecosystem of supporting tools is incredible. Some of my favorites:

These all make it so easy to “do the right thing” and write code with BDD/TDD to provide quality from the start.

Personally, my switch from J2EE to Rails (not to mention SQL to NoSQL/MongoDB) has been one of pure pleasure. The kinds of rich functionality and the ability to build stuff faster is imprerssive. I only wish I were better at writing kick-ass Ruby, Rails, CSS, Javascript, MongoDB…

Is it perfect? Of course not. There are other cool things to look at as well… Meteor, Node.js, MEAN, etc. So much to explore, so little time.

Back to my continuous learning!

 


Regex to Exclude Multiple Words

For Google Analytics, I wanted to create some chainable filters to deal with a set of subdomains that can occur on alpha, beta, and production, etc. So I needed to find a way to say “Give me all of the production subdomains, and none of the alpha/beta variants, or preprod.”

Here are the sample URLs that I want to filter out the alpha/beta/preprod from:

acme.domain.com
acme.beta123.domain.com
acme.alpha123.domain.com
wyle.alpha.domain.com
wyle.showme.domain.comcool_stuff.html
acme-two.domain.com
acme-two.preprod.domain.com

Here is the resultant regex:

^w+-*w*.(?!(?:alpha(123)*.|beta(123)*.|preprod.)domain.com).*$

And here is what Rubular looks like:
Rubular Multi Word Exclude URL Regex

Big shout out to Rubular.com, an awesome place to test out regex!

Looking at Gem Code is Easy with GemEdit

Ever want to pop into the source code of some gem that you are using?

Gem Edit is a nice and easy way to do this (if you aren’t using RubyMine, for example):

[sudo] gem install gemedit

In the terminal, simply type:

[develop*]$  jonsmac2-2:source jon$  gem edit -e mate mongo_mapper

And you will see:

Found gem for 'mongo_mapper' with version >= 0
Opening the following gems with mate:
  mongo_mapper-0.8.6 /Library/Ruby/Gems/1.8/gems/mongo_mapper-0.8.6
Running `mate "/Library/Ruby/Gems/1.8/gems/mongo_mapper-0.8.6"`

and Voila, Mongo Mapper appears in TextMate:

Mongo Mapper

Mongo Mapper Source Code

In an IDE, you can often get to the source code for a single method, but not as “completely” as with gemedit and TextMate, IMHO.

 

Mongo Mapper from IDE

Mongo Mapper from IDE

 

@martinstreicher gave me a good tip when using bundler (which I use on my Rails 3 apps):

export EDITOR=mate;bundle open <gem>

Factory Girl and MongoMapper

You were probably hoping for some Rosey the Riveter poster…

Factory Folder

Factory Folder

Instead, I am going to extend my small MongoMapper example to include Factory Girl. The steps are pretty simple:

  1. Go here to install…
  2. Create your factories
  3. Use the factories in Cucumber/RSpec

Factory Construction

I created a new “factories” folder under the spec folder:

The factories for User and Event are quite simple:

Factory.define :user do |u|
  u.name ('a'..'z').to_a.shuffle[0..7].join.capitalize
end

and

require 'factory_girl'
def dummy_word(len=6)
  ('a'..'z').to_a.shuffle[0..len].join.capitalize
end

def dummy_date
  secs_in_day = 24*60*60
  Time.now + (rand(60)*secs_in_day - 30)
end

Factory.define :event do |e|
  e.title "#{dummy_word} #{dummy_word 3} #{dummy_word 10}"
  e.date  dummy_date
end

Refactor Original Setup

Instead of using this style of test data creation:

@event = Event.create(:title => "Code Retreat Timbuktoo", :user => @fred)

We will use the new factory as follows:

@event = Factory(:event, :title => "Code Retreat Timbuktoo", :user => @fred)

Refactor Cucumber

The given went from this:

Given /^A set of events$/ do
  fred = User.find_or_create_by_name("fred")
  (1..10).each do
    Event.create(:title=>"#{dummy_word} #{dummy_word 3} #{dummy_word 10}",
                 :date => dummy_date,
                 :user => fred)
  end
  harry = User.find_or_create_by_name("harry")
  (1..10).each do
    Event.create(:title=>"#{dummy_word} #{dummy_word 3} #{dummy_word 10}",
                 :date => dummy_date,
                 :user => harry)
  end
  Event.count.should == 20
end

to this – including refactoring out dummy_title, and reducing it to one loop:

Given /^A set of events$/ do
  fred = User.find_or_create_by_name("fred")
  harry = User.find_or_create_by_name("harry")
  (1..10).each do
    evt = Factory(:event, :title => dummy_title,
                          :date  => dummy_date,
                          :user  => fred)
    evt = Factory(:event, :title => dummy_title,
                          :date  => dummy_date,
                          :user  => harry)
  end
  Event.count.should == 20
end

Subtle Details

The beauty of having tests is that I could easily mess around with getting some of the Factory Girl configuration stuff in the right place. Try something, run the test, adjust as needed until all are back to green.

The file features/support/env.rb got some additions so that Cucumber could find the factories:

$LOAD_PATH << File.expand_path('../../../app/model' , __FILE__)
require 'user'
require 'event'
require 'spec/factories/events.rb'
require 'spec/factories/users.rb'
load 'config/mongo_db.rb'

All the tests still pass!

More Complicated Example

For a project I work on, my factories look like this, with auto-creation of random IDs:

def random_months(months)
  day_in_secs = (24*60*60)
  (1+rand(months))*30*day_in_secs
end

# ----------- GROUP -----------
Factory.sequence :group_num do |n|
  "99#{n}#{rand(n)}"
end

Factory.define :group do |g|
    g.group_num {Factory.next(:group_num)}
    g.name "Greatest Group"
end
# ----------- ACCOUNT -----------
Factory.sequence :doctor_num do |n|
  "999992#{n}#{rand(200+n)}"
end

Factory.sequence :login do |n|
  "AB#{rand(n*68)}bx#{rand(200+n)}"
end

Factory.sequence :msid do |n|
  "CQ987Z12#{n}#{rand(n)}"
end

Factory.define :account do |a|
  pw = 'password'
  a.msid { Factory.next(:msid) }
  a.doctor_num { Factory.next(:doctor_num) }
  a.first_name "James"
  a.last_name "Jones"
  a.role 'user'
  a.password pw
  a.password_confirmation pw
  a.email Setting.get("AutoEmail")
  a.login { Factory.next(:login) }
end

# ----------- PATIENT -----------
Factory.sequence :patient_num do |n|
  "#{n}#{rand(300+n)}"
end

Factory.define :patient do |pt|
#  pt.patient_num "10000009"
  pt.patient_num {Factory.next(:patient_num)}
  pt.emr_num "1853286"
  pt.first_name "John"
  pt.last_name "Johnson"
  pt.dob {(Time.now - random_months(36))}
  pt.count_public_encounters 1
  pt.count_public_events 2
end

 

Cucumber, RSpec, MongoMapper, Git, Oh My!

Nick left a question on my many-to-many associations post. He wanted to know more about sorting by date and querying…

So I decided to (over achieve and) show how I would approach that as if I were adding a new feature:

  • Adding a “date” key field and an index
  • Using Cucumber to drive the new feature from the desired behavior à la BDD.
  • Querying with a date sort tacked on…

You can follow my progress from the earlier version to this one by examining the commit history:

Commit History

Commit History for Adding Dates to the Event Class

Looking at the “added initial event date functionality” commit, you can see how I added some new files to allow for Cucumber and MongoMapper:

Commits for Event Dates

Commits for Event Dates

For Cucumber, I added the “/features” stuff.

And since I wanted to start testing the code, I had to make the database functional, so I added “mongo_db.rb” – and I assume you have MongoDB installed and running locally.

##### MONGODB SETTINGS #####
MongoMapper.connection = Mongo::Connection.new('localhost', 27017, :pool_size => 5)
MongoMapper.database = "event-development"

I am never quite sure if there is a “perfect” way to wire up small, non-Rails apps like this one to use MongoDB. But what I have done works good enough to allow for a simple example to run.

BDD Cycle

So I began the BDD cycle by creating a “feature branch” and switching to a new branch from the current master branch:

git checkout -b event_dates master

Next I wrote the feature for the new behavior:

Scenario: Sort Events by Date
  Given A set of events
  When I display the events
  Then I should see them sorted by latest date first

When you run Cucumber, you will get the default code for steps – all pending of course.  Naturally, I did one step at a time, to take each one from “pending” to green. Working on the Given, then the When, and finally the Then, I came up with these steps:

Given

Here I wanted to generate a set of data so that we could see if the list was sorted properly. You can check out the code on github for the randomness baked into the “dummy_*” helper methods. And I wanted to create the events for two users.

Given /^A set of events$/ do
  fred = User.find_or_create_by_name("fred")
  (1..10).each do
    Event.create(:title=>"#{dummy_word} #{dummy_word 3} #{dummy_word 10}",
                 :date => dummy_date,
                 :user => fred)
  end
  harry = User.find_or_create_by_name("harry")
  (1..10).each do
    Event.create(:title=>"#{dummy_word} #{dummy_word 3} #{dummy_word 10}",
                 :date => dummy_date,
                 :user => harry)
  end
  Event.count.should == 20
end

When

Sort of playing along as if this is a web request, I coded this step to return a “response” that is generated by the “list all events” class method. In true BDD fashion, this is the code I wish I had 🙂

When /^I display the events$/ do
  @response = Event.list_all
end

Then

The proof is in scanning the resultant “response” object to ensure date order is correct:

Then /^I should see them sorted by latest date first$/ do
  first = Date.parse(@response.third[0..10])
  last = Date.parse(@response.last[0..10])
  first.should > last
end

Outside – In

As soon as I ran the “When” I got a failure due to Event.list_all not existing. So off to the RSpec-land we go, to write the expectations for list_all. This is known as the “Outside-In” approach. (I learned this term from the excellent RSpec book, and it looks like you can watch a video about it here.)

The behavior expressed above (in Cucumber) can be thought of as more of an “outer,” acceptance/integration style of test. Typically it would be the User Interface (UI) – but I have been known to blur that line, since not all code is about UI and since Cucumber is so darn fun to use. Working at this outer level often leads to expressing what is expected of our actual code; in this case, that Event have a class-level method that returns a list of it’s instances (a.k.a., documents). Since we are talking about the behavior of a class, that is more of the “inside” of the application. Not something that an external user might care so much about directly, but rather something that supports the end behavior in an indirect fashion. For the “inside” we turn to RSpec (basically a better-than-unit-test, unit test tool).

  • Outside ≈ Feature ≈ Cucumber
  • Inside ≈ unit test ≈ RSpec
  describe "#list_all" do
    it "should show each event, ordered by date" do
      response = Event.list_all
      response.should_not be_empty
      response.class.should == Array
      response.size.should == Event.count + 2 #for title and column header
      # Yes, you should not output stuff as part of your tests, but this *is* our UI :-)
      puts response
    end
  end

Many times, my initial pass at a new method is to simply return what is expected. Then write another test to make that fail. Sort of “sneak up on the answer.” But here it was easy enough to simply output some real text from the get-go:

  def self.list_all
    response = []
    response << "%s %s %s" % ["*"*10, "LIST OF EVENTS", "*"*10]
    response << "%6s %15s               %s" % ["Date", "TITLE", "Attendees/Interested/Likes"]
    events = Event.all(:order => 'date desc')
    events.each {|e| response << e.to_summary}
    response
  end

Oops. LOL (:-D) While writing this post, I found a mistake when testing my code a bit further than my initial commit.

I decided to remove the order part of the query, which revealed that the Cucumber feature still passed. Crap! So, it wasn’t so easy after all! Dope.

    events = Event.all

Second Attempt

My initial way of generating records resulted in the documents magically being in the right date order by default. Tests passed, but the test was wrong – not vigorous enough testing!

Note to self:
no matter how trivial things seem, write failing tests
that contradict each other – so to speak.

So, I tweaked the document generator to better randomize the list of events such that we won’t accidentally have them all in proper order by default:

  ...
  fred = User.find_or_create_by_name("fred")
  (1..10).each do
    Event.create(:title=>"#{dummy_word} #{dummy_word 3} #{dummy_word 10}",
                 :date => Time.now + (rand(60)*secs_in_day - 30),
                 :user => fred)
  end
  ...

And, instead of just spot-checking the order, here is a new RSpec test to ensure each event is in proper order, date-wise:

    it "should show each event, ordered by date" do
      response = Event.list_all
      response.should_not be_empty
      response.class.should == Array
      response.size.should == Event.count + 2 #for title and column header
      r_prior_date = Date.parse(response[2][0..10])
      response[3..response.size].each do |r|
        date = Date.parse(r[0..10])
        date.should < r_prior_date
        r_prior_date = date
      end
      # Yes, you should not output stuff as part of your tests, but this *is* our UI :-)
      puts response
    end

Now we’re talking! A failed test:

'Event#list_all should show each event, ordered by date' FAILED
expected: < Wed, 20 Apr 2011,
     got:   Wed, 20 Apr 2011

And similarly, I re-wrote the Cucumber test. Funny thing, further testing revealed that the error above was not actually a legitimate fail as it turns out! I discovered I needed “<=” instead of just “<“– sometimes the simplest things aren’t so simple after all. Especially when it comes to setting up sample data.

Then /^I should see them sorted by latest date first$/ do
  last_date = Date.parse(@response.third[0..10])
  @response[3..@response.size].each do |r|
    date = Date.parse(r[0..10])
    date.should <= last_date
    last_date = date
  end
end

And I got the above test to fail by “stepping back” and removing the “order by” clause to get me back to an original, non-sorted listing. Good! Now we can step forward again and try to get the functionality that we are looking for to work.

Cucumber Failing Tests

Cucumber Failing Tests

I re-enabled the order clause to see if the tests would now pass:

events = Event.all(:order => 'date desc')

And, fortunately, the tests are indeed passing:

Cucumber Passing Tests

Cucumber Passing Tests

Commit on Green

Once you get the bits of functionality working, commit (even if you still have pendings). Committing locally has no downside 🙂 Here I will commit and push to the repo (the “$” is my prompt (well, not really), and the #comments are not part of the command line!):

$git status #You can see your changes
$git commit -a -m "added initial event date functionality"  #commit your changes
$git checkout master #switch to the master branch
$git merge --no-ff event_dates #merge all of your local feature branch commits, preserving each
$git push origin master #Pump it up to the repo
$git branch -d event_dates #Get rid of the feature branch

This rhythm gets to be very familiar.

More on Querying

You may have noticed some of the queries above, and this was one of Nick’s questions…

With MongoMapper, you can chain Plucky queries as follows:

  def self.list_all(a_user=nil)
    response = []
    response << "%s %s %s" % ["*"*10, "LIST OF EVENTS", "*"*10]
    response << "%6s %15s               %s" % ["Date", "TITLE", "Attendees/Interested/Likes"]      events = nil     if a_user.nil?       events = Event.all(:order => 'date desc')
    else
      events = Event.where(:user => a_user).all.sort(:date.desc)
    end
    events.each {|e| response << e.to_summary}
    response
  end

I added a new feature that shows off the above query, quickly ran through the entire process again, from git checkout to git push, with Cucumber and RSpec and code in between. You can find it all in the source code.

Cucumber Show Events For User

Cucumber Show Events For User

Git is really an amazing revision control tool… I can’t imagine using anything else now. Here is an example of looking at the “Network Graph” of my little project:

github network graph

Github Network Graph

Pow — A Great Server for your Mac Bat Cave

Somehow I stumbled across this great little tool  — oh yeah, John Nunemaker mentioned “powder,” which was “Syntactic sugar for http://pow.cx/

Huh? Syntactic what? For “pow” what? John hasn’t steered me wrong yet, so I decided I needed to look at what Pow was. In 37Signals own words:

Pow: Zero-configuration Rack Server for Mac OS X

In other words:

You can run a bunch of your rails apps all at once, with ease.

This is worth the effort to try and get running to see if it will help ease how you work with multiple Rails apps.

Since my experience was a bit off from the awesome-looking Screencast teaser, I figured I would share it in case others might benefit from the troubleshooting.

Once I solved the Pow-not-working-like-magic-from-the-start problems, it worked right out of the box with a Rails3 App. Not so much with my Rails2 apps. So, you can either try to do it the Rails3 way from the start (see below for instructions), or barge ahead and see how far you get (knowing now what I do for Rails2, barging is probably a pretty safe bet).

Yes, I am repeating what is in the main website… but then aggregating common troubleshooting experiences ad fixes below, to save you (and my colleagues) time.

Install Pow:

$ curl get.pow.cx | sh

Be certain you see “*** Installed” or it is not! (See Troubleshooting section below if need be.)

jonsmac2-2:.pow jon$ curl get.pow.cx | sh
% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
Dload  Upload   Total   Spent    Left  Speed
100  2722  100  2722    0     0  17322      0 --:--:-- --:--:-- --:--:-- 34455
*** Installing Pow 0.2.2...
*** Installing local configuration files...
*** Starting the Pow server...
*** Installed

If you get upset, just uninstall:

$ curl get.pow.cx/uninstall.sh | sh
Symbolic Link to Rails3 App

Symbolic Link to Rails3 App

Configure:

$ cd ~/.pow
$ ln -s /path/to/myapp

To the right is an example. Name the link if you do not want to use the default folder name. For example:

ln -s ~/railsprojects/first_app jkfirstapp

This allows you to then enter the following into the browser, using the symbolic link name (or the default folder name):

http://jkfirstapp.dev

If that didn’t work, continue onward, your journey will be short (I hope).

Troubleshooting

I was disappointed when the magic didn’t happen right away. Boy does the Ruby community spoil us! So a hunting I will go…

Create a Rails3 App

If you are only doing Rails2, see below for the config.ru fix. Otherwise, creating a vanilla Rails3 app is a good way to test that Pow is properly configured. Here is a simple Rails3 app (from Michael Hartl’s Ruby on Rails3 Tutorial):

mkdir ~/railsprojects
rails new first_app

edit the Gemfile:

gem 'rails', '3.0.1'
gem 'sqlite3-ruby', '1.2.5', :require => 'sqlite3'

Then execute:

bundle install
rails server

It should be running with the default server page.

I got Nothing!

If pow did not install, or you get seemingly NOTHING when going to the browser webpage, look no further than here. The following worked for me (and others). Seems that the permissions are not quite right sometimes:

before:

-rw-rw-r--   1 jon  staff   518B Apr 18 13:42 cx.pow.powd.plist

So I ran this:

jonsmac2-2:.pow jon$ launchctl load -Fw ~/Library/LaunchAgents/cx.pow.powd.plist
jonsmac2-2:.pow jon$ chmod 644 ~/Library/LaunchAgents/cx.pow.powd.plist
jonsmac2-2:.pow jon$ curl get.pow.cx | sh

And, after the re-install, the perms ended up as you might expect:

-rw-r--r--   1 jon  staff   518B Apr 18 13:42 cx.pow.powd.plist

Checking It’s Running

This is admittedly odd output for a “working” install, but it gives you at least one data point to compare what you get versus this. Do the following:

cd ~/Library/Application Support/Pow/Current/bin
jonsmac2-2:bin jon$ ./pow

On my Mac it results in:

node.js:134
    throw e; // process.nextTick error, or 'error' event on first tick
    ^
Error: EADDRINUSE, Address already in use
at HttpServer._doListen (net.js:1089:5)
at net.js:1060:14
at Object.lookup (dns.js:159:5)
at HttpServer.listen (net.js:1054:20)
at Array.<anonymous> (/Users/jon/Library/Application Support/Pow/Versions/0.2.2/lib/daemon.js:34:27)
at EventEmitter._tickCallback (node.js:126:26)

Domain Isn’t Setup

If you see this:

No such app

No such application can be found!

Then you know you have screwed up the symbolic link.

Try again, and be careful and exact.

Trouble Accessing Dev domains

Some folks needed this simple fix:

touch /etc/resolver/dev

Rails2: Cannot GET /? –> config.ru is Missing!

That’s right, you see: Cannot GET / in the browser. Bet you never saw that before!

This means that you are missing the Rackup config.ru file in your application’s root. Try adding this file (you can see it in the folder screenshot above):

# This file is used by Rack-based servers to start the application.
require "./config/environment"
use Rails::Rack::LogTailer
use Rails::Rack::Static
run ActionController::Dispatcher.new

Pow Can’t Start Your App

This is most likely, genuinely, truly your error… Sorry to say!

The error below is because the config.ru was completely wrong (I was trying the Rails3 project file (duh — it invokes a class in a module named after the app itself)):

Pow can’t start your application.

/Users/jon/railsprojects/track_my_league/tml raised an exception during boot.
NameError: uninitialized constant FirstApp
/Users/jon/.gem/ruby/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:443:in `load_missing_constant'
/Users/jon/.gem/ruby/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:80:in `const_missing'
/Users/jon/.gem/ruby/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:92:in `const_missing'
/Users/jon/railsprojects/track_my_league/tml/config.ru:4
/Users/jon/Library/Application Support/Pow/Versions/0.2.2/node_modules/nack/lib/nack/builder.rb:4:in `instance_eval'
/Users/jon/Library/Application Support/Pow/Versions/0.2.2/node_modules/nack/lib/nack/builder.rb:4:in `initialize'
/Users/jon/railsprojects/track_my_league/tml/config.ru:1:in `new'
/Users/jon/railsprojects/track_my_league/tml/config.ru:1

Here the error is that I do not have the gem environment set up properly with RVM (using .rvmrc). Easily diagnosed because I can’t even start the app manually!

SystemExit: exit
./config/boot.rb:66:in `exit'
./config/boot.rb:66:in `load_rails_gem'
./config/boot.rb:54:in `load_initializer'
./config/boot.rb:38:in `run'
./config/boot.rb:11:in `boot!'
./config/boot.rb:110
./config/environment.rb:7:in `require'
./config/environment.rb:7
/Users/jon/railsprojects/tml/TML/config.ru:3:in `require'
/Users/jon/railsprojects/tml/TML/config.ru:3
/Users/jon/Library/Application Support/Pow/Versions/0.2.2/node_modules/nack/lib/nack/builder.rb:4:in `instance_eval'
/Users/jon/Library/Application Support/Pow/Versions/0.2.2/node_modules/nack/lib/nack/builder.rb:4:in `initialize'
/Users/jon/railsprojects/tml/TML/config.ru:1:in `new'
/Users/jon/railsprojects/tml/TML/config.ru:1

Hope this helps!

RVM Install Troubleshooting

All I wanted to do was sit down with Mike Hartl’s “Ruby on Rails 3 Tutorial” yesterday. Hours later, with nothing to show other than a zillion open terminals, I punted and watched the Flyers beat the Sabres despite playing like girls (I know, unfair to girls!). Then I went to bed.

So I must have had a dorked up installation of RVM or something, because when I tried to install Ruby 1.9.2 and Rails 3 and upgrade RVM I ran into <ahem> “issues.” I was getting weird errors like:

error installing rails i18n requires rubygems version 1.3.5
gem_runner.rb:85:in `<top (required)>': undefined method `load_plugins'

After exploring all sorts of similar woes that other people had and not really getting that magic googullet (Google Bullet), I decided to go all nuclear (apologies to Japanese readers). I was able to run:

rvm implode

Which made “rvm -v” fail to find rvm — a good thing. It meant I had uninstalled RVM. (Or so I thought!)

I also deleted the RVM stuff from the bash_profile file(s). Just to attempt to eliminate voodoo dolls.

But I still ran into stupid errors (stupid voodoo dolls!):

error installing RVM fatal: Not a git repository (or any of the parent directories): .git

After much pain and suffering (well, only in a wimpy software relative sense), my guess is that I installed rvm as sudo at one point or installed the gem, or somehow had things “cross-eyed.” I don’t know…

I guess I should be more diligent, because in general you get spoiled by Ruby and gems and Rails and the general euphoria of how easy things are. Until they aren’t.

Today, I ended up fixing my system by looking for “rvm” on my system, and cleaning up leftovers. The crumbs from my sloppy eating at the trough of Ruby, I suppose.

I saw some directories holding rvm docs. I whacked them.

I saw some directories with rvm source, archives… Gone.

I uninstalled the rvm gem. (Oops. Who put that there?)

Finally, I retried the install:

jonsmac$ bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)

And added this to ~/.bash_profile And I restarted terminal because I always forget how to do that source ~/.bash_profile thing…

jonsmac2-2:~ jon$ rvm -v
rvm 1.6.2 by Wayne E. Seguin (wayneeseguin@gmail.com) [https://rvm.beginrescueend.com/]

Shazam! No errors. Thanks Wayne!

Now I can get past page 15 in Mike’s tutorial book!

Ideas for a Distributed Team

In response to a posting on Agile Project Management…

I am starting up a ‘Distributed’ Agile Project and looking at tools to assist the distributed team communicate the status of work undertaken, stories, estimates and burn down/up charts as well as general collaboration (forums, document sharing etc).
There are tools such as Agile Wall, Mingle, Trac (with plugins etc).
I am ideally looking for an externally hosted solution (something that we will not be setting up in-house).
I have a core team of 15 people and with an additional 10 people that would want access. I am looking for any ideas or suggestions on online tools that you may have.
Thanks in Advance.
Regards
Neal

I’ve been doing this sort of thing since 2000, so it is very easy and very possible to be extremely effective as a distributed team.

Here is a very simple approach using Basecamp (and you can get an add-on for burndowns if you like that sort of thing). I’ve been doing this on a small project since March or so.

Then I set up other simple collaboration tools (looked like this on many projects, though you might have to march around that hodgepodge of a site to find more tool ideas):

  • Wiki: Project stuff that is not issues or code needs a home; a.k.a.,
    (you can use basecamp, though not as extensive as something like confluence)
  • Chat Room for being the virtual cubicle farm and water cooler. Skype or IRC works great. You can establish key words that call out for attention, like “@ALL I’m going to kick the TEST server.” You can even have textual scrums if voice is not always possible. For a while, we had a bot that recorded the chats and logged them to the wiki 🙂
  • Issues/Bugs: You need a place to store your lists of things to get done. Some call that an issue tracker; others, simply a To-Do list. I have used Jira for a l-o-n-g time for both features and bugs. I have also used Lighthouse — which is just fine too.

Atlassian Studio is worth a look. You can add in continuous integration and code reviews and what not.

My suggestion: start really small and humble with the tiniest process.

That really simple Basecamp process I blogged about? We actually got to PRODUCTION with much less ceremony. There were none of the “To be QAd” or “To Be Released” because we did it more in iteration chunks, so we knew the overall state of a given iteration (in dev, qa, or released).

The slightly greater ceremony of QA and Release buckets allowed me to answer the need from the stakeholders and other non-developers to know the state of the project at a glance. It’s easy to see what is in the backlog, or what is in progress, or waiting QA, etc. Now we’re doing Kanban. I crank issues and (rare 🙂 bugs through one at a time usually.

Anyway, have fun!

Using Basecamp in an Agile Manner

Software Development Life Cycle

In software development, we want to make our process as visible as possible to all participants and stakeholders. To that end, behold a simple process that uses a handful of Basecamp To-Do Lists as markers for how a feature or bug is working its way through this process.

At any point in time, you can look at the “To-Do” list page for a status on your favorite new feature, task, or bug. And, if you have a chunk of features piled up in an “Iteration 1” list, you can see the number of items being worked through to completion. (There are even third-party apps that allow you to do burndown charts if they appeal to you.)

Using Basecamp's To-Do List in a simple manner

Requirements/Bugs

The business has a desired priority for features as expressed by the order of items in the “staging” lists, and especially the On-Deck list (to borrow a baseball metaphor for “What’s next”). For major new features, the business and the developers will work out a rough Release Plan. But for simple enhancements and bugs, the business can simply add desired items to the lists.

Development

The Developer will pick a new task off of the top of the On-Deck list. There will usually be a conversation around the issue to ensure proper understanding (unless it is self-explanatory). Ideally, we get the business/testers helping to write User Acceptance Tests in the BDD form of Given… When… Then… The Developer moves this feature into the “In Progress” list. If desired/possible, the user could add a date estimate for the task.

The Developer will create tests, be they Cucumber, RSpec, or UnitTest, or all 3 types. If possible, the Testers can help write the up-front acceptance tests, so that they are intimate with the feature/bug. The Developer writes code until the tests pass.

Once the issue is complete, and the tests are passing (and you didn’t break any other tests), the Developer: commits the code, updates the TEST server, and does a smoke test to ensure things still work as expected. The Developer then moves the task to the “To Be QA’d” list, where the Testers will now verify the issue is indeed complete and correct on TEST. Close collaboration between Tester and Developer is warranted here, as the nature of the fix and any developer tests can be explained so that testing can be as effective as possible. Plus we want to maximize use of automated tests, and minimize any unnecessary manual tests (as they are time consuming and expensive) given the nature of the code changes.

Testing

If the QA passes, the Tester moves the task to the “To Be Released” list. Depending on the nature of the feature, the Business can also help to “test” and ensure things work as expected. If the test fails, then the task is moved back to the On-Deck list and the details added to the issue as comments (if simple) and image uploads (add image link to the comments), or to the issue tracker if it is more complex (even though it is technically not an issue against the released product).

Release

The Developer will schedule the move for “To Be Released” tasks to the PRODuction box. This may require coordination with the client’s IT team if they have internal controls. Following release, the application is smoke tested to be sure the basics are still functioning. If any problems arise, the server can be rolled back, or fixed ASAP, based on the nature of the error.

Once the items are released to PROD, you can indicate that they are “complete.” If the issues came from a list that you want to keep for posterity, simply drag the completed task to the original list (“Iteration 1” for example). Now you can see the items in that list that have been released (i.e., completed).

Summary

I’ve used Jira and much more elaborate SDLC schemes in the past. But a recent Rails project with just a few folks on the team, found us trying out Basecamp. By creating various lists, we can mimic the Kanban-style wall board that Greenhooper provides within Jira. Because the lists allow simple ordering to show priority, and you can drag-and-drop between lists, and you can track your time, I think we have a very lightweight, winning combination.

This process is equally at home doing one feature all the way through, or an entire iteration’s worth of features in a bigger chunk. (Basically dependent on the cost of testing and the appetite of the end-user for changes.)

SDLC process[/caption]