Context pattern

This gem gives you the scaffolding needed to easily use the Context Pattern in your Ruby on Rails application

What is the context pattern?

The context pattern provides a way of thinking about and writing Rails applications that results in better code that is easier to maintain. This is done through the introduction of a new category of object known as a Context Object.

A Context Object is responsible for interpreting the current state of the request, providing the context for a controller to do its work, and defining an interface that may be referenced by views. Every request has exactly one context object associated with it. This context is built up throughout the life cycle of a request.

If you have never encountered the context pattern before, you should read the explanatory blog post to get a thorough understanding of the motivations behind and benefits of this code pattern, examples of before and after code, and a thorough explanation of how everything works.

This README is intended to provide a reference for those who are already somewhat familiar with the context pattern.

Setting up the gem

To use this gem, you need to do two things:

  1. Require it in your Gemfile: ruby gem 'context-pattern'

  2. Add the following two lines to your ApplicationController: ruby include Context::Controller helper Context::BaseContextHelper

Simple example

The example below is a simple one that is used to demonstrate various facets of how this gem and the context pattern work. Suppose we have an online bookstore and are looking at a BooksController#show action. We want to retrieve the logged in user from the session and the book being viewed from the params. We use a decorator to provide some functionality around showing the user's name (this is contrived, but demonstrative).

class ApplicationController < ActionController::Base
  include Context::Controller
  helper Context::BaseContextHelper

  before_action :set_application_context

  def set_application_context
    extend_context :Application, params: params, session: session
  end
end

class BooksController < ApplicationController
  def show
    extend_context :BookShow
  end
end

class ApplicationContext < Context::BaseContext
  view_helpers :current_user

  attr_accessor :session, :params

  def current_user
    User.find_by(id: session[:user_id])
  end
  memoize :current_user
end

class BookShowContext < Context::BaseContext
  view_helpers :book

  decorate :current_user, decorator: UserPresenter, memoize: true

  def book
    Book.find(params[:id])
  end
  memoize :book
end

class UserPresenter < SimpleDelegator
  def abbreviated_name
    "#{first_name} #{last_name[0]}"
  end
end

View file:

Hi, <%= current_user.abbreviated_name %>.
Here is information about <%= book.title %>

Basic components of using the gem

Best practices for usage

The following suggestions are not requirements for using this gem, but bits of advice that have been pulled together from using the context pattern across the WegoWise codebase over a period of five years.

How to test context objects

To be filled in soon.