RubyProjectStructure

HomePage | RecentChanges | Preferences

Ruby Project Structure

The team I work with is [hiring] and I thought I'd attempt the code challenge they used for candidates.

The requirements include simulating a popular card game, and reporting statistics on the average number of hands and time it takes to complete a game.

As I pondered how to begin, I realized that I don't really know how a Ruby project is supposed to be structured. What is the equivalent of "mvn archetype:create ..." from Java and Maven? Where do you put your code and your tests? What else is typically in there?

A few ideas from searching...

I settled on creating a gem by executing...

$ bundle gem mygame
      create  mygame/Gemfile
      create  mygame/Rakefile
      create  mygame/LICENSE.txt
      create  mygame/README.md
      create  mygame/.gitignore
      create  mygame/mygame.gemspec
      create  mygame/lib/mygame.rb
      create  mygame/lib/mygame/version.rb
Initializing git repo in /Users/wsmoak/projects/mygame
$

Interesting! My next step was going to be to get this under version control, but it looks like that's already done.

$ cd mygame/
$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

	new file:   .gitignore
	new file:   Gemfile
	new file:   LICENSE.txt
	new file:   README.md
	new file:   Rakefile
	new file:   lib/mygame.rb
	new file:   lib/mygame/version.rb
	new file:   mygame.gemspec

$ 

The git repository has been initialized and the files have been added, all that remains is to commit:

$ git commit -m "Add initial project structure from 'bundle gem mygame'"
[master (root-commit) d9b1ec0] Add initial project structure from 'bundle gem mygame'
 8 files changed, 104 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 Gemfile
 create mode 100644 LICENSE.txt
 create mode 100644 README.md
 create mode 100644 Rakefile
 create mode 100644 lib/mygame.rb
 create mode 100644 lib/mygame/version.rb
 create mode 100644 mygame.gemspec
$ 

It just needs a little cleanup to capitalize MyGame? properly and fix the version number so that we do not build a 'real' version over and over locally. From [prerelease-gems] it looks like .pre is the convention, so we'll go with that. (This appears to be roughly the equivalent of the -SNAPSHOT suffix that Maven uses on version numbers in Java projects.)

So that gets me a project structure and a hint about where my project code should go (in the lib directory) but there's nothing here about tests.

I'm pretty sure I want to use RSpec, and a quick search turns up https://relishapp.com/rspec/rspec-core/v/3-2/docs/command-line and

$ rspec --init
  create   spec/spec_helper.rb
  create   .rspec
$

A bit more clicking around leads me to believe I need a spec/mygame_spec.rb file, so I'll add that, with the contents...

describe MyGame do

end

Now how to run it? Just running rspec complains

$ rspec 
/Users/wsmoak/projects/mygame/spec/mygame_spec.rb:1:in `<top (required)>': uninitialized constant MyGame (NameError)

That looks like it needs a requires statement somewhere...

This appears to have the best advice: http://stackoverflow.com/questions/4398262/setup-rspec-to-test-a-gem-not-rails

AND it looks like I could have used --test=rspec with the bundler gem mygame command.

I generated a new project with that switch and after some fussing around trying to compare them and add the missing bits to my original project, I elected to just delete everything and start over.

$ bundler gem --test=rspec mygame
      create  mygame/Gemfile
      create  mygame/Rakefile
      create  mygame/LICENSE.txt
      create  mygame/README.md
      create  mygame/.gitignore
      create  mygame/mygame.gemspec
      create  mygame/lib/mygame.rb
      create  mygame/lib/mygame/version.rb
      create  mygame/.rspec
      create  mygame/spec/spec_helper.rb
      create  mygame/spec/mygame_spec.rb
      create  mygame/.travis.yml
Initializing git repo in /Users/wsmoak/projects/mygame
$

And then do the initial commit, and repeat the fixes for the version number and capitalization and commit those.

Much better!

Now bundle exec rspec works as does bundle exec rake. The project skeleton comes complete with a failing test, so the output is:

$ bundle exec rspec

MyGame
  has a version number
  does something useful (FAILED - 1)

Failures:

  1) MyGame does something useful
     Failure/Error: expect(false).to eq(true)
       
       expected: true
            got: false
       
       (compared using ==)
     # ./spec/mygame_spec.rb:9:in `block (2 levels) in <top (required)>'

Finished in 0.00155 seconds (files took 0.09872 seconds to load)
2 examples, 1 failure

Failed examples:

rspec ./spec/mygame_spec.rb:8 # MyGame does something useful

Next up: writing a _real_ failing test and the first bit of code for the game.


HomePage | RecentChanges | Preferences
This page is read-only | View other revisions
Last edited February 22, 2015 2:53 pm by 198.98.93.120 (diff)
Search: