This is Part 2 in a multi-part series to detail the creation of a “simple” project combining Ruby, MongoDB, RSpec, Sinatra, and Capybara in preperation for a larger-scale side project set to begin January 2013. For more in this series, see the Pokephile category. Part 2 details refactoring code using the MongoDB Ruby driver to use Mongoid. The code for this side-project is located on Github.
What I’ve Done
In a previous post, I described creating a class that would populate a database with data scraped from the internet. I used the MongoDB Ruby driver to accomplish this. However, using the driver can be laborious and there are simpler ways. In this post, I’m going to refactor the Populater class to use Mongoid.
Mongoid
Mongoid (pronounced mann-goyd) is an Object-Document Wrapper for Ruby. Using mongoid abstracts some of the database operations that must be performed when using the MongoDB Ruby driver. It comes in handy when using models in an MVC application. To install the Mongoid gem:
1
|
|
Refactoring
In populater.rb, we only inserted one structure of document into our “pokemons” collection. That makes this a great opportunity to use Mongoid. We remember that there were four fields in our document: number (string), name (string), image link (string), and types (array). Knowing this, we can create a model for this data:
1 2 3 4 5 6 7 8 9 10 |
|
And that’s it for our model. Although we specified the types in this case, it’s not necessary if we want a looser definition of our model. Here’s how we change our implementation file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
|
That one’s easy. We deleted four lines and added 3. However, now you can see that the Populater does not have to deal with connecting to the database, it only has to know what model it wants to modify. So we’ve removed some complexity from this file by no longer requiring the database name on initialization. However, that means that someone else has to be in charge of setting up the initial connection. In the overlying project, we want that someone else to be a controller. In our tests, we want that someone else to be our test file. So let’s do it. We’re going to start by adding a config section in our before:all block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
In doing this, we’ve set up any of our document models to use the ‘test’ database. Now we go through each test and replace the Mongo Ruby Driver syntax with Mongoid syntax, which is similar to Ruby’s Array syntax.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
The ‘new’ tests are straightforward. We remove the usage of an input parameter to the Populater initializer. The only significant change we make is to the “empties pokemon collection” test. Here we replace the Mongo Ruby Driver syntax of inserting into a collection with Mongoid syntax of creating a Pokemon document. The ‘create’ method inserts a document into the collection with the given values, or defaults if none are given. We also see that we can remove the “find” syntax completely and just use a “count” method on the document type.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
The tests for adding 0, 1, and 2 documents to the collection are all very similar. The only change is to replace the Mongo Ruby Driver “find.count” syntax with the Mongoid “count.” The “adds pokemon with a ____” tests all undergo the same changes. I replace the “.find.first” statement with a simple “.first” to get the same meaning. So our Populater has been converted to use Mongoid instead of the Mongo Ruby Driver. Bully for us.
There’s one more change that would be nice to make before we hang up our hats. Configuring Mongoid using the .config syntax is okay, but it would be a lot nicer to keep all of our configuration in a file. We can create such a file called “mongoid.yml” and put some configuration information in it:
1 2 3 4 5 6 |
|
This syntax is valid in Mongoid 3.x. This is a very simply configuration for our test environment. Now we can go back into our test file and change the ‘before:all’ block:
1 2 3 4 5 6 7 8 9 10 |
|
The second parameter can be a string or a symbol. Now there’s only one file to modify the environment configurations, and we’re better off for it.