Model Builder

Build active record models on the fly.

Handy when following TDD to develop a reusable component, that isn’t strictly related to a project business layer (therefore should not reference it).

Scenario

Take a look at this case of code duplication:

class User < ActiveRecord::Base
  def map_all_names
    to_a.map &:name
  end
end

class Topic < ActiveRecord::Base
  def map_all_names
    to_a.map &:name
  end
end

That can be easily improved through an abstraction:

class User < ActiveRecord::Base
  include NameUtils
end

class Topic < ActiveRecord::Base
  include NameUtils
end

module NameUtils extend ActiveSupport::Concern
  included do
    define_singleton_method :map_all_names do
      all.map &:name
    end
  end
end

Nice. Now we’ve a reusable abstraction, that could even fit into a gem to be applied at another projects.

But thinking about a gem context, we will not be able to use User or Topic models at our tests. They belong to our business intelligence. So, how to test it?

Here is the need of don’t rely our business intelligence during abstraction tests.

Solution

ModelBuilder.build 'MappableName', {
  includes: NameUtils,
  attributes: { name: :string },
  validates: [:name, presence: true]
}

Now your ‘MappableName’ model is able to receive NameUtils tests:

MappableName.map_all_names

And, in order to clean database:

# Add this to your spec_helper.rb or rails_helper.rb

RSpec.configure do |config|
  config.after(:suite) do
    ModelBuilder.clean
  end
end

See full test examples here and here.

<img src=“https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif” alt=“Donate” />

Changelog

2.2.1

  • Bug fixes and improvements for creating/dropping tables

  • Bug fixes and improvements for cleaning strategy: now you have to call ‘clean’ method at ‘after :suite’ instead of ‘before :all’

    # Add this to your spec_helper.rb or rails_helper.rb
    
    RSpec.configure do |config|
      config.after(:suite) do
        ModelBuilder.clean
      end
    end
    

2.2.0

  • Bug fixes and improvements for creating/dropping tables

  • Bug fixes and improvements for cleaning strategy: now you have to ‘clean’ method at ‘before :all’ instead of ‘before :each’

2.1.0

  • Improving support to namespaced classes/models. Now the builder accepts:

    ModelBuilder.build 'Namespaced::Models' ...