Safeguarding Your API Keys

I don’t like to put any API keys in version control. It is easy to do when your newrelic.yml already has the api key in it and the docs for carrierwave say to just put your keys in the config initializer. I see this as a security concern as anyone who gets access to your repo immediately has all the tokens for everything.

Services like Heroku lean towards putting keys in your environment config. I really like this approach, but it makes things a little bit more complicated in development. I certainly don’t want to have to set up these keys in my zshrc.

One approach we’ve been trying out is to put all the application’s keys in a gitignore’d config/development.yml and load it when the application starts. We also put a development.example.yml next to it with all the keys that are expected but without the values so future developers know what they need to set up.

The setup is very easy. You start by editing your config/environment.rb and putting this code in to load the development.yml if it exists.

config.before_initialize do
  dev = File.join(Rails.root, 'config', 'development.yml')
  YAML.load(File.open(dev)).each do |key, value|
    ENV[key.to_s] = value
  end if File.exists?(dev)
end

Then you can create your config/development.yml and fill it with all the keys you want to store in your server’s environment.

BRAINTREE_PUBLIC_KEY: big long key
HOPTOAD_API_KEY: another big long key
NEWRELIC_API_KEY: YABLK

Now comes a really important part. Be sure to add the development.yml to your .gitignore file. If you forget that, then all of this was for nothing.

config/development.yml

We changed an initializer so be sure to bounce your server at this point.

OK, now you can go ahead and start using those environment variable in your yml’s and initializers. For example, you can update your config/newrelic.yml with the key from the environment.

license_key: <%= ENV['NEWRELIC_API_KEY'] %>

And you can update your hoptoad configuration like so.

HoptoadNotifier.configure do |config|
  config.api_key = ENV['HOPTOAD_API_KEY']
end

Another added benefit is that you can very easily have different keys per environment, as opposed to hard-coding them and checking for the environment in the initializer.

Easy Uptime Monitoring with Rails 3

A number of services are available to monitor your website’s uptime. The ones I have seen are all very easy to set up on their end. All you need to do is tell it what URL to hit in your system.

Your first reaction might be to just point to the root url of your app. If you have database resources or other services that you access on the server side along with that page request, then you will be hitting those every time the uptime monitor checks your site. You are also cluttering up your logs with noise. I typically configure it for once per minute, so you are looking at 1440 extra requests per day.

It is really easy to make a lightweight endpoint for services like this in Rails 3 though. You can just setup a custom route to a proc right in your routes file.

match 'heartbeat', to: proc { [200, {}, ''.chars] }

That will just return a successful status and empty body, which is all those services need. Now you can point your monitoring service to http://yourdomain.com/heartbeat and save yourself a little bit of processing!

Proper Use of Fabricators (or Factories)

Writing Fabrication has given me a lot of insight into the world of object generation. It has forced me to reflect a lot on how we are doing it and how we can do it better. The reason I wrote Fabrication to begin with was to try out the idea of lazy generation of associations, meaning that a defined association wouldn’t actually be generated unless it was actually referenced. That would allow you to specify the entire object graph in a single set of fabricators but not worry about generating them all every time.

After implementing that and working extensively with the library, I have settled on what I consider to be a few best practices for defining fabricators. Whether you are using Factory Girl, Machinist, Object Daddy, Fabrication, or some other library, these principals all still apply.

In the spirit of the upcoming bike week, let’s say we have the following class, representing a motorcycle model.

class Model < ActiveRecord::Base
  belongs_to :manufacturer
  has_many :motorcycles
  validates :name, presence: true, uniqueness: true
end

The primary fabricator should only have the fields necessary to create a valid object.

In many cases, a table has quite a few fields on it. Most of them are not necessary for the object to be valid in the database and so don’t need to be generated every time you create an object.

This particular class probably has a whole lot of fields on it specifying the engine displacement, drive type, tire sizes, etc. Our system may not care about any of those fields the majority of the time though. The only thing the model actually validates is the presence of the name.

The primary fabricator should always create belongs_to associations, but never has_many.

A good object model will typically require objects going up the tree to exist, but never objects going down. Any time there is an id field on your model, as in the case of a belongs to, then that other object is very likely necessary for your object to exist. In the case of our Model, it has_many motorcycles but you don’t actually need to make a production run for the model to exist. The manufacturer does need to exist for the model to make sense, so we should be creating that every time.

Use a sequence when uniqueness is required.

Our Model has a uniqueness validation on name. There are a number of ways to ensure that, but the easiest one is to use a sequence.

Let’s put it all together.

Now that we have the basics down our fabricator should look like this.

Fabricator(:model) do
  manufacturer!
  name { Fabricate.sequence(:model_name) { |i| "Model #{i}" } }
end

We skipped all the fields we didn’t absolutely need, didn’t mention the has_many relationship, forced the manufacturer, and used a sequence for the name. It is lean and clean, but flexible enough for the vast majority of your specs.

Integration Testing Setup with RSpec 2 and Capybara

NOTE: This is an update to a post I made a while back on using Capybara with RSpec 1 for integration testing. This post is specifically for using Capybara with RSpec 2! The setup information is different but the example is the same.


RSpec 2 has introduced a ton of great new features to make our spec suite better. Writing integration specs in RSpec is easier now, too. Well, maybe not easier, but definitely prettier.

If you already have RSpec integration specs in your project and are upgrading from RSpec 1, then you will want to start by removing any requires or includes from your spec_helper.rb or support/capybara.rb files. Those inclusions are still necessary, but have a new home now.

Next up, put the necessary requires in your Gemfile.

Run a quick bundle install and you should be good to go from a gem perspective.

Run rails generate rspec:install to generate the basic rspec setup for the new version. Note that the spec_helper.rb has changed, so make sure you merge any changes you had into the new file.

Now we need to add the piece that ties RSpec and Capybara together for your integration tests. Paste this file into spec/support/integration_example_group.rb. All the Capybara requires and includes happen here, so you no longer need to do it in your spec_helper.rb or support/capybara.rb.

Just to make sure all this is working properly, go ahead and run rake. If this doesn’t work, you need to fix whatever the problem is before moving on.

Now on to Capybara! By default it uses the rack-test driver, which is similar to webrat in that it is headless and does not run javascript. Unless you have a very javascript intensive app, the rack-test driver should handle the majority of your test cases. The really cool thing about Capybara is that you can use another driver like selenium when you need javascript and rack-test when you don’t.

Now let’s test a simple sign in process. Create a file called spec/integration/guest_signs_in_spec.rb and fill it in like so. Be sure to change the field, button, and link labels to match your actual screens.

That is a trivial example and you would typically want to make more numerous and comprehensive asserts than that, but it should get you going with your first test.

Now that you have a modern integration test setup, I expect to see the quality of your app improve dramatically! Happy TDD’ing!

Fabrication

Github Repo: http://www.github.com/paulelliott/fabrication

One of my takeaways from RailsConf this year was inspiration to write a new gem. I was sitting at a fast testing round table discussion and people kept bringing up the use of build versus create in factories.

That gave me the idea to lazily generate activerecord associations. Doing that allows you to define your entire object graph in your Fabricators and only generate the pieces you need for the spec you are running. When the association is first accessed, the Fabricators will generate the defined objects, persist them to the database, and return the set as if they were there to begin with. While I was at it, I figured it would be handy to be able to generate regular old ruby objects and Mongoid documents, so I baked in support for doing that as well!

Let’s say we have a Person object that is just a regular old class in Ruby. We can define a Fabricator with static or evaluated attribute values as seen below. You can then Fabricate as many as you want and override specific fields as you go.


class Person; attr_accessor :first_name, :last_name, :age, :friends end

Fabricator(:person) do
  first_name “Joe”
  last_name { Faker::Name.last_name }
  age { rand(100) }
  friends(:count => 10) { |index| Fabricate(:person) }
end

person = Fabricate(:person, :last_name => “Schmoe”)

Notice that you don’t need to pass a parameter to the block. I figured that would just be extra and unnecessary syntax.

Also note the :count parameter. When generating a collection, this allows you to tell Fabrication how many of the object you want it to generate. It will automatically build that many and return an array of the new objects. The block receives the index of the generation as a parameter in case you need it.

If we want to get a little bit more fancy, we can generate active record models as well.

class Company < ActiveRecord::Base
  has_many :divisions
  belongs_to :location
end

Fabricator(:company) do
  divisions(:count => 3) { |company, index| Fabricate(:division, :company => company) }
  after_create { |company| company.update_attribute(:location, Fabricate(:location) }
end

company = Fabricate(:company)
# At this point, we have a location but no divisions.
Division.count
# => 0, because they haven’t been created.
company.divisions.any?
# => true, because the divisions get created when the “getter” for the association is called.
Division.count
# => 3, because now they exist!

Of course, with great power comes great responsibility. This feature is very handy but can also be very dangerous. It is something you need to keep in mind as you are writing your specs.

And finally, you can generate Mongoid Documents very easily.


class Author
  include Mongoid::Document
  field :name
  field :books => Array
end

Fabricator(:author) do
  name { Faker::Name.name }
  books(:count => 5) { Fabricate(:book) }
end

author = Fabricate(:author)

It is that simple! I have been successfully using this in a new Rails 3/Mongoid project I am working on. It won’t step on the toes of other frameworks, so you can also use it alongside your existing factory_girl or machinist implementation.

Please check it out, try it out in your projects, and let me know what you think! Also report any bugs or feature requests you find!

Sorry, Everyone!

I really messed up recently and I want to apologize to anyone who may have been misinformed or mislead by me. I have no idea how I came to think this nugget of unwisdom that I have been repeating. I must have read an article on it somewhere that was either wrong or maybe I just misunderstood and then began to propagate some misinformation. I have no one to blame but myself though and I feel really terrible and embarrassed about it.

It came out today during Hashrocket's live book club. I was explaining an issue I found in a codebase today where they were using contexts in jQuery to scope selectors. I was explaining that when you pass in a jQuery object as a context, the selector function ignores this parameter as it is expecting a raw DOM object.

I was called out during my monologue and as it turns out, I was dead wrong about it. One of the folks sitting in the circle looked up the jQuery API to get some more context for what I was talking about and noticed that the docs said something contrary to what I was saying. I tested it after the book club and of course it works just like the api docs say it does.

It gets even worse because I have talked about this in numerous blog posts, presentations, and conversations with other developers. The good news is that what I was saying you should do is valid, so anyone listening to me would still be writing working code.

The real problem here is that I took something on faith and didn't look it up or research it for myself. The takeaway is that reading the source code for libraries is critical. Not only will you understand exactly how the code we depend on every day works, but I guarantee you will learn something. I failed to do that in this instance and it caused quite a problem. At the very least, read the API docs before you go running your mouth.

So, to set the record straight, when you are using a context in jQuery you can pass in a raw DOM element, a jQuery object, or a Document and it will work as you expect.

Again, I am deeply sorry for confusion this has caused.

Making Your Test Suite Scream with Specjour

You know all those other Macs you have lying around the house sitting idle all the time? Well I have some great news. You can finally put those freeloaders to work! With specjour ( http://github.com/sandro/specjour ), you can distribute your test suite across all the cores on your network!

It uses bonjour to communicate and can support multiple projects simultaneously. As long as the machine has the dependencies required for the test suite (gems and unix packages), it can participate in the testing goodness. The current contents of your project get rsync’d to the managers, so they will always match your local changes.

You get started by installing it into your Rails project. First, setup the dependency in the test group of your Gemfile.

group :test do
  gem ‘specjour’, ‘0.2.5’
end

Now make a small update to your config/database.yml. A number needs to be appended to the test database name to support multiple simultaneous tests for the same project. It matches that used by parallel_test, so if you used that previously you should be all set.

test:
  database: blog_test<%=ENV['TEST_ENV_NUMBER']%>

To fire up a local manager, open up a new terminal tab and simply run:

specjour

To execute your test suite, run:

rake specjour

It will automatically determine the number of cores on your machine and utilize them all. With it working on your main dev machine, you are all ready to get the real magic started!

SSH to another machine on your network that you want to run the tests for you. Make sure you install the dependencies your project needs (mysql, imagemagick, mongodb, etc) and all the gems it needs. Run specjour just like you did on the first machine.

Back on your dev machine, run rake specjour again. This time you will see more workers in the list and your suite should run considerably faster.

There are additional options you can pass to specify project names to listen for and how many cores to use, but for most people the defaults should work fine. Those options are passed to the manager and would look something like this:

specjour --workers 4 --projects blinq,workbeast

We have seen drastic improvements in the execution times of long running test suites using specjour. But even if your suite only takes a couple of minutes to run and you only have one machine, you should still seen a nice performance gain.

That Pesky Git Error Message

If you are using git on OSX, then you have undoubtedly run into this error message at one point or another:

”.git/COMMIT_EDITMSG” 69L, 2767C written
error: There was a problem with the editor 'vim'.
Please supply the message using either -m or -F option.

This happens when you do a git commit but accidentally type :Wq when you attempt to write the file. It then bitches that you didn’t type a valid command and so you type the correct command, :wq, only to be greeted by this message in the terminal.

You do have MacVim installed though, right? If not, install it through homebrew (brew install macvim) or go here and grab it from the website: http://code.google.com/p/macvim/. Be sure to put mvim in your path so you can launch it from the command line.

With MacVim all set up, correcting this issue is actually very simple. All you need to do is symlink vim to mvim and you will never see the error again.
I put mvim in /usr/local/bin, so to create the symlink I typed:

ln -s /usr/local/bin/mvim /usr/local/bin/vim

You can put it anywhere you want as long as it is before /usr/bin/vim in your path.

 

Integration Testing with Capybara and Selenium

You may not realize this, but your javascript is full of bugs. Because of the ghetto nature of most applications’ javascript, it is easy to break things that seem unrelated to what you are currently working on. It can be tough to know what exactly is acting on what parts of your site, depending on who did it, when it was written, what libraries were used, etc.

A few options exist for javascript-enabled integration testing, but the easiest to set up and most reliable is still selenium. With capybara, it is simply a matter of tweaking some settings and turning it on where you need it.

To set up selenium, you can start by adding database_cleaner to the test group in your Gemfile.

gem 'database_cleaner', ‘0.5.2’

Now you need to add the following code to spec/support/database_cleaner.rb.

require 'database_cleaner'

Spec::Runner.configure do |config|

  DatabaseCleaner.strategy = :truncation

  config.before :each do
    Capybara.reset_sessions!
    DatabaseCleaner.clean
  end

end

Then, you need to turn off transactional fixtures in your spec_helper.rb.

config.use_transactional_fixtures = false

To set up a specific test to use the selenium driver, you just need to put before and after blocks at the start of your test.

before(:all) { Capybara.current_driver = :selenium }
after(:all) { Capybara.use_default_driver }

Now when you run this test, you will see a Firefox window pop and the browser will dance for you. You shouldn’t need to change anything else in your tests for it to work thanks to the capybara dsl.

Integration Testing Setup with RSpec and Capybara

Also see updated post using RSpec 2

Integration testing is critical for modern web applications. It provides a chance to exercise all the features of your site in a real or mock browser and make sure that everything still work correctly with any changes made. It plays a key role in insuring the quality of your application and that your users have as bug-free an environment as possible.

Integrating it into your existing rspec setup is a breeze, too. I am a big fan of Jonas Nicklas’ Capybara (http://github.com/jnicklas/capybara), which is a great gem that lets you mix and match web drivers over a common interface and allows you to test specific functions of your site with the appropriate platform. You can easily use it directly with RSpec to write a comprehensive integration test suite for your application.
Let’s get started by running rake. If you don’t have a passing test suite right now, then shame on you! You need to fix that before doing anything else. If you don’t have a test suite at all, then...well...thanks for reading this and hopefully you will get off to a good start when you’re done.

Once you are all green, setup the latest capybara and rspec gems. Update your Gemfile with the necessary includes.

source :gemcutter

...

group :test do
  gem 'capybara', '0.3.7'
  gem 'rspec-rails', '1.3.2'
  gem ‘factory_girl’, ‘1.2.4’

  ...
end

Run bundle install --relock. If you are updating or installing RSpec for the first time, be sure to run the generator to get your configuration up to date:

script/generate rspec

One last piece of setup, we need to update the spec_helper.rb with the settings for Capybara.

require 'capybara/rails'
require 'capybara/dsl'

Spec::Runner.configure do |config|
  config.use_transactional_fixtures = true
  config.use_instantiated_fixtures = false
  config.fixture_path = RAILS_ROOT + '/spec/fixtures/'

  config.include(Capybara, :type => :integration)
end

Just to make sure all this is working properly, go ahead and run rake again. If this doesn’t work, you need to fix whatever the problem is before moving on.

Now on to Capybara! By default it uses the rack-test driver, which is similar to webrat in that it is headless and does not run javascript. Unless you have a very javascript intensive app, the rack-test driver should handle the majority of your test cases. The really cool thing about Capybara is that you can use another driver like selenium when you need javascript and rack-test when you don’t.

Now let’s test a simple sign in process. Create a file called spec/integration/guest_signs_in_spec.rb and fill it in like so. Be sure to change the field, button, and link labels to match your actual screens.

require ‘spec_helper’

context ‘as a guest on the sign in page’ do

  #Make sure your factory generates a valid user for your authentication system
  let(:user) { Factory(:user) }

  #Browse to the homepage and click the Sign In link
  before do
    visit root_path
    click ‘Sign In’
  end

  context ‘with valid credentials’ do

    #Fill in the form with the user’s credentials and submit it.
    before do
      fill_in ‘Email’, :with => user.email
      fill_in ‘Password’, :with => ‘password’
      click ‘Submit’
    end

    it ‘has a sign out link’ do
      page.should have_xpath(‘//a’, :text => ‘Sign Out’)
    end

    it ‘knows who I am’ do
      page.should have_content(“Welcome, #{user.email}!”)
    end

  end

  context ‘with invalid credentials’ do

    #No form entry should produce an error
    before do
      click ‘Submit’
    end

    it ‘has errors’ do
      page.should have_xpath(“//div[@id=‘errorExplanation’]”)
    end

  end

end

That is a trivial example and you would typically want to make more numerous and comprehensive asserts than that, but it should get you going with your first test.

Now that you have a modern integration test setup, I expect to see the quality of your app improve dramatically! Happy TDD’ing!