Appraising Your Gem
One might argue that the more versions of ruby and rails your gem supports, the more valuable it is to the general population. Well, I guess it does also depend on what your gem does (rainbows and unicorns?).
Thoughtbot has done it again with appraisal, a neat and nifty gem for testing your gem in different ruby and rails environments. It's especially useful when combined with Travis to specify which continuous integration environments should be used or ignored. (see gringott's travis.yml for an example).
Note: appraisal's README on github is curently for for the 1.0.0.beta2 version. This can be confusing since the current rubygems version (and what you get if you just do
gem "appraisal" is 0.5.2. You can either use the beta version with
gem "appraisal", "1.0.0.beta2", or, you can use the 0.5.2 version of the README
As mentioned in the README, you can run your spec and cucumber tests against these ruby/rails versions using appraisal. What's not mentioned, though, is that you can also run your local webserver against your different appraisals as well.
Since appraisal essentially just pre-compiles the bundles that you are going to use for your different appraisals (e.g., rails-3.2, rails-4.0), you can use that to your advantage:
First, find out the path to the bundle that you want to test locally:
Look for the line that like:
bundle check --gemfile='/pathbot/to/rails/engine/gemfiles/rails_4.0.gemfile'
We are going to hand that path to our webserver so it knows what bundle to use. However, instead of using the --gemfile option, we are going to pass it as an inline environment variable:
BUNDLE_GEMFILE='/path/to/rails/app/gemfiles/rails_3.2.gemfile' bundle exec rails server
Or, if you are developing an engine, you can run your dummy app's rails server using
BUNDLE_GEMFILE='/path/to/rails/engine/gemfiles/rails_3.2.gemfile' bundle exec spec/dummy/bin/rails server
Note: spec/dummy is the location of your engine's dummy app. This might instead be in test/dummy, depending on how you set your engine up.
Running a local webserver against different ruby/rails appraisals is useful for being able to manually play around with why a particular test might not be working in a particular bundle (e.g.,only on firstname.lastname@example.org).
One last thing, maybe this was just something quirky on my end, but I ended up having issues when running my rake tests against my rails-3.* appraisals. I kept encountering this error:
undefined method `migration_error=' for ActiveRecord::Base:Class
Unable to find a solution, I am embarassed to say that I instead took the lazy (and very time-consuming) way out of repeatedly pushing to github after every commit so that Travis would run my rails-3.* tests for me so I could debug where my issue might be occurring. That wasted not only a lot of my time (5 minutes between fix and result), but also a lot of Travis' server hours... Sorry guys! Let me know how I can show you some love.
Anyway, the hidden clue to the solution to the
undefined method issue was hidden in one of the comments on one of the unaccepted answers of one of the StackOverflow questions. As Iliya Stepanov points out,
It was one string in config/initializers or environment. I don't remember exactly what string it was, but check carefully that files if you rolling back from Rails 4 to 3 and facing similar problems.
It turns out that in
spec/dummy/config/environments/development.rb there is this line:
config.active_record.migration_error = :page_load
I commented that out, and everything worked hunky dorey. It doesn't make me happy to think that I am suppressing potentially useful errors, but there were no migrations that needed to be migrated. Also, I'm pretty sure that might have only been related to the fact that I created a rails4 engine, then was trying to backport its dummy to rails3. Pretty sure.