ActiveRecord Without a Database?

Total Downloads Downloads Today Code Quality Network Stars Version Build Documentation Depfu Chat License: MIT

Replacement for broken Class.new(ActiveRecord::Base).

Very useful in testing Rails apps, and even more so for testing gems without having to specify full blown models.

If you prefer an exceptionally hacky alternative that could also be used for real runtime code, see my other gem activerecord-tablefree!

Installation

Add this line to your application’s Gemfile:

gem 'anonymous_active_record'

And then execute:

$ bundle

Or install it yourself as:

$ gem install anonymous_active_record

Usage

Require the library in your spec_helper or other test suite boot file.

require 'anonymous_active_record'

Let’s say you want to write specs for a module, HasBalloon, which provides a method has_balloon?, and will be mixed into ActiveRecord classes.

module HasBalloon
  def has_balloon?
    name == 'Spot' ? true : false # only Spot has a balloon
  end
end

This won’t work (really!):

  let(:ar_with_balloon) do
    Class.new(ActiveRecord::Base) do
      attr_accessor :name
      include HasBalloon
      def flowery_name
        "#{b_f}#{name}#{b_f}"
      end
      def b_f
        has_balloon? ? '🎈' : '🌸'
      end
    end
  end

So do this instead:

  let(:ar_with_balloon) do
    AnonymousActiveRecord.generate(columns: ['name']) do
      include HasBalloon
      def flowery_name
        "#{b_f}#{name}#{b_f}"
      end
      def b_f
        has_balloon? ? '🎈' : '🌸'
      end
    end
  end
  it 'can test the module' do
    expect(ar_with_balloon.new(name: 'Spot').flowery_name).to eq('🎈Spot🎈')
    expect(ar_with_balloon.new(name: 'Not Spot').flowery_name).to eq('🌸Not Spot🌸')
  end

Generate Options

AnonymousActiveRecord.generate(
    table_name: 'a_table_name', 
        # if table_name is not set klass_basename will be used to derive a unique random table_name
        # default is a unique random table name
    klass_basename: 'anons', # is default
    columns: ['name'], 
        # default is [], 
        # meaning class will have ['id', 'created_at', 'updated_at'], as the AR defaults
    timestamps: true, # is default
    connection_params: { adapter: 'sqlite3', encoding: 'utf8', database: ':memory:' } # is default
) do
   # code which becomes part of the class definition
end

The block is optional.

Factory Options

AnonymousActiveRecord.factory(
    source_data: [{name: 'Phil'}, {name: 'Vickie'}],
        # Array of hashes, where each hash represents a record that will be created
    # ... The rest of the options are the same as for generate, see above.
) do
  # same as for generate, see above.
end

The block is optional.

There is also a factory! method that will raise if the create fails, accomplished by calling create! instead of create.