fbpx

Testing Modules in Rspec

There comes a time when we might need to write some unit tests for a module. To do this, we can just extend some class and test the methods on that class. Here is an example using Rspec’s subject class; extending it with SomeProject::MyHelpers to unit test a method called :helpfulness.

require 'spec_helper'

describe SomeProject::MyHelpers do

  # add the module methods as instance methods to Rspec's subject
  subject do
    self.extend(described_class)
  end

  describe 'The helpfulness of my helper' do
    it 'helps a lot' do
      expect(subject.helpfulness).to eq "a lot"
    end
  end
end

Rename a Phoenix Application

When we build a Phoenix application with $ mix phoenix.new my_app, our application module name is set to MyApp. This module name, as well as the snake case version, is referenced everywhere, making it very cumbersome if you need to ever rename the application. Here is a shell script I wrote the does the job in less than a second. Just make the script executable and run it by passing a snake case version of the new name for your application. You will be shown a preview and asked to confirm before proceeding.

Common Table Expressions in Postgres

PostgresSQL WITH Queries, also known as Common Table Expressions (CTEs), allows us to write complex queries by defining temporary tables for use in a larger query. In other words, we can create in-memory temporary tables and query against them. Here is an (trivial) example where we want the email addresses of all the users who signed up on the biggest sales day.

WITH top_sales_by_date AS (
  SELECT date, SUM(order_total) AS total_sales
  FROM orders
  GROUP BY date
  ORDER BY total_sales DESC
)
SELECT email
FROM users
WHERE sign_up_date = (
  SELECT date
  FROM top_sales_by_date LIMIT 1
)

The top_sales_by_date is a table created just for this query that aggregates the order totals grouped by date, the ordered by total sales. We can use the date value from the top record in the temp table to find the emails of users who signed up on this date.

Recursion in Elixir

Coming from an object oriented language with data mutability, learning looping in Elixir required that I let go of my current understanding about iterating over a collection. In fact, just forget looping and think recursion. So, what’s recursion?

Recursion is solving a problem whereby one applies the same solution to smaller instances of that problem. Think, a function calling itself. So, here is what it looks like in Elixir:

defmodule Recursionism do

  def operate_on_list_items([], _) do
    []
  end

  def operate_on_list_itmes([head | tail], fun) do
    [fun.(head) | operate_on_list_items(tail, fun)]
  end
end

Recursionism.operate_on_list_items([1, 2, 3], fn(n) -> n * n end)

Let’s break this down:

  • First we define a multi-clause function called Recusionism.operate_on_list/2. Multi-cause functions are multiple functions of the same name and arity that are executed depending on the matching of the arguments.
  • Then, when we call Recusionism.operate_on_list_items([1, 2, 3], fn(n) -> n * n end), it matches the second multi-clause function definition and executes it.
  • That second function, uses the anonymous function (it’s second argument) to operate on the first item in the list (head). The result of applying the anonymous function (fun.(head)) becomes the first item in a new list.
  • In order to complete the list, the operate_on_list_items function calls itself by passing all the remaining items in the original list (tail) as the first argument, along with the same anonymous function as the second argument.
  • When there are no more items in the list, calling operate_on_list_items matches the first multi-clause function definition and returns an empty list, thereby stopping the recursion.
  • The end result is building a list by doing [1 | [4 | [9 | []]]], which evaluates to [1, 4, 9]

Efficient Object Oriented Design with UML Sequence Diagrams

So, you have a feature to write. Now what? Do you start coding right away and hope for the best? Hopefully not. Here’s an example of using a Universal Modeling Language (UML) Sequence Diagram to plan a feature.

sequence_example

In this example, User calls the create() method on Post, which in turns calls the send() method on the Messenger class. The dotted line is called the object’s Lifeline. The part of the Lifeline that is wider, is where the object is active.

What are the benefits of a sequence diagram? It turns the focus from the objects themselves to the messages that pass between them. You can see what public interfaces you’ll need to implement. As Sandi Metz writes in her book, Practical Object-Oriented Design in Ruby, this process can also reveal ‘hidden objects’ – object you didn’t know you needed. If you do TDD, you also know what tests to write. What happens if you make a mistake? Just fix the diagram. It’s a lot cheaper than fixing code.

Module Decorators

Why decorate objects instead of using inheritance?

It’s a more dynamic, flexible and transparent alternative to subclassing. There’s several different ways of using the decorator pattern in Ruby, but I’m just going to show the module/extend approach. You can read about other decorator techniques in Dan Croak’s blog post.

Use a module and extend to add instance methods on an object. This will still maintain the ability to use super as demonstrated in this trivial example:

class Report
  def number_of_pages
    10
  end
end

module CustomerAdmendment
  def number_of_pages
    super + 5
  end
end

module AdminAdmendment
  def number_of_pages
    super + 1
  end
end

report = Report.new
report.number_of_pages # => 10
report.extend(CustomerAdmendment).number_of_pages # => 15
report.extend(AdminAdmendment).number_of_pages  # => 16

With the module/extend technique we can maintain the original interface and delegate through all the decorators.

Ruby’s Safe Navigation Operator

nil‘s in Ruby can be annoying. Thankfully, Ruby version 2.3.0 gave us a safe navigation operator, something that other languages like C# and Swift already had. It’s very much like ActiveSupport’s try method, which checks if a receiver responds to a method before calling that method. If the receive doesn’t respond to the method, nil is returned.

Usage

Here is a trivial example to demonstrate how this works. Let’s say you need to call upcase an object attribute that may or may not be defined. At some point, this might happen:

person = Struct.new(:first_name)
bob = person.new
=> #<struct first_name=nil>

bob.first_name.upcase
# => undefined method `upcase' for nil:NilClass

Before Ruby 2.3.0, we might have solved this problem with something like:

bob.first_name.upcase if bob.first_name
=> nil

Using the Safe Navigation Operator (&.) we can do this:

bob.first_name&.upcase
=> nil

In this example, calling first_name on the bob instance returns nil, so &. halts the method chain right there.