All you need to know about writing a mountable Rails Gem with rspec

Yuva's avatar

Yuva

This article briefly talks about how to write a mountable rails gem and what are the practices that I followed

First things first

Rails generates nice boilerplate for your gem which is sometimes hard to get it right in the first go. Use this simple command and you are good to go

$ rails plugin new <gem-name> --mountable --skip-test-unit --dummy-path=spec/dummy
  1. The --mountable option helps in creating a mountable gem.
  2. The --skip-test-unit skips generation of test templates in test folder
  3. The --dummy-path specifies where the dummy test application (which we will be using for testing) should be generated. It is usually created in test folder but you want that to be created in spec folder so that you can use rspec

Importance of dummy app

Some of the gems that you develop which depend on rails need to run specs in rails environment. Since gem doesn't have a rails env, it uses dummy app's rails env to run such tests. This is useful when you write specs for controllers, helpers etc.

When you set up rspec by adding rspec-rails to your Gemfile, you need to add these lines at the top of spec_helper.rb so that rspec loads rails env of dummy app.

ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../dummy/config/environment", __FILE__)

General flow of development

  1. Never checkin Gemfile.lock in your git repository {or whatever SCM that you are using}

  2. First, add all the dependent gems that your gem needs in Gemfile and develop your gem.

  3. Once you have finalized your dependent gems, move those gem declarations to gemspec file. Add all dependent gems with add_dependency method and add all development dependent gems with add_development_dependency method

    Gem::Specification.new do |s|
      # your information
     
      s.add_dependency "strong_parameters", "~> 0.2.1"
     
      s.add_development_dependency "factory_girl_rails"
    end
  4. Its important to note that you should require your dependent gems explicitly in the root file of your gem. Say if your gem is named my_cool_gem, then you should have my_cool_gem.rb created inside lib folder. If your gem is dependent on strong_parameters, then you need to add these lines:

    require "my_cool_gem/engine"
    require "strong_parameters"
     
    module MyCoolGem
    end