Garrett Heinlen

Enthusiastic Ruby developer, actively seeking to be ballin'. I enjoy long talks on the internet and my perfect evening is coding with the ones I love..


Extensions add methods at runtime to classes.

Extensions can be easily compared to decorators, presenters, concerns, and whatever other jargon you possess. We've chosen the name Extensions because it makes sense in the context in which we are using them, but feel free to label them as you please.


I got hired as a Contractor at Blake Education to build a greenfield project hurray. We are building an app to help teach students their year's curriculum through fun html5 canvas games. Teachers will give their students homework via the app and it will all be self-marking.

The problem

From the start, we knew there would be two entirely different ways to interact with the app - as a teacher, and as a student. We could have easily made a simple, project killing, monolithic app with Teacher:: and Student:: namespacing, but we decided against that approach.

We instead tackled this problem by splitting these up into small, isolated, separate apps with an intermediate gem for sharing common models between them.

wf-student, wf-teacher, wf-models.

wf-models - holder of all things shared

wf-teacher - controller of all things student

wf-student - receiver of fun, travel, and knowledge

Where do extensions come into play?

We use extensions to keep the wf-models very thin and very dumb. We don't want these shared models to know anything about the specific business logic of either app. Instead we extend these classes when the wf-teacher or wf-student app is started and inject methods into these classes.


config/application.rb ```ruby config.toprepare do Dir.entries("app/extensions") .select{ |f| ! f} .each do |filename|

array = file_name.split("_")
klass_name =
klass = klass_name.constantize

klass.class_eval do
  include "#{klass}Extensions".constantize

end end ```

Here we find the model class and include the respected extension module.

How we use them


wf-teacher School Extension

module SchoolExtensions
  extend ActiveSupport::Concern

  included do

  def address
    [street, suburb, state, postcode, country].join(', ')

  def all_students_except_from(obj) obj.student_ids)

  def all_students_except(student_id)" <> ?", student_id)

  module ClassMethods

wf-model School Class

class School < ActiveRecord::Base
  has_many :students
  has_many :teachers

  def to_param

  def to_s

Here we add methods that are specific to the teacher app that the student app will never need to use or know about. Thus, we moved this logic into the teacher app by extending the real class at runtime and the student will never be any wiser. This restricts the wf-student school class to a very limited amount of public api methods and makes it easier to see what you have available by only showing what is relevant to the app.


  • wf-models stays thin!
  • methods only exist where they belong
  • keeps files small!

Things to be weary of

Don't just throw every method in the world into an extension and hide the fact that your shared model has 100 methods. Design and forethought is still a very important part about designing software and not every design pattern will apply to every project.


  • Keep shared models dumb
  • Keep extensions small
  • Keep business logic where it belongs
comments powered by Disqus