When Yukihiro “Matz” Matsumoto created Ruby, his guiding philosophy was to design a language that makes the programmer productive while still being fun to use. At Returnly, our Engineering team strives to write Ruby on Rails code that follows through on Matz’ vision. Here are three design patterns we use every day that enable us to be productive while having some fun along the way.
One use case of this pattern is to expose a common interface between components in your codebase while abstracting away implementation details such as environment-specific behavior.
Here’s a simple implementation of an
OrderCreator that supports both local and production use cases:
class OrderCreator def initialize(order_lines) @order_lines = order_lines end def create adapter.create(@order_lines) end private def adapter return OrderCreators::Fake if Rails.env.development? OrderCreators::Shopify end end
When developing locally, this adapter allows us to iterate quickly by stubbing out API calls in our
Fake adapter. And even better, we can extend this adapter to easily add support for additional e-commerce platforms:
def adapter return OrderCreators::Shopify if platform.shopify? return OrderCreators::Magento if platform.magento? OrderCreators::Default end
The memoization pattern allows us to run expensive queries or calculations once per session, and then reuse the results as many times as needed afterward.
Suppose you need to access the current user’s information multiple times in a session, you can memoize the data like so:
def current_user @current_user ||= User.find(params[:user_id]) end
||= operator (explained well here) is key to the memoization. The first call to the
#current_user method will result in a database lookup, but each subsequent call will use the in-memory value.
The policy pattern allows for encapsulation of complex business logic and helps keep your controllers skinny.
For example, suppose an e-commerce merchant would like to offer a special Black Friday promotion, but only to shoppers who meet certain qualifications (in this case, first-time shoppers spending over $200):
class BlackFridayPromotionPolicy def initialize(user, order) @user = user @order = order end def eligible? @user.first_time_shopper? && @order.total_amount > 200 end end
Then in our controller:
class OrdersController < ApplicationController def create OrderCreator.new(@order_lines).create redirect_to :special_offer if shopper_is_eligible_for_promotion? end private def shopper_is_eligible_for_promotion? BlackFridayPromotionPolicy.new(current_user, @order).eligible? end end
Thanks for reading! Let us know what Ruby patterns you use in the comments below.
And if you're into the exciting world of e-commerce and engineering, visit our job openings here!