Jared Rader

TIL - Ruby Array Multiplication

Today I learned that if you call a multiplication operator on a Ruby array, it duplicates each element of the array by the multiplier.

So for example:

>> [1,2,3] * 3
=> [1, 2, 3, 1, 2, 3, 1, 2, 3]

>> ['Jared Rader'] * 3
=> ["Jared Rader", "Jared Rader", "Jared Rader"]

Thoughts on Ruby Inheritance Patterns

Developers writing code in object-oriented languages like Ruby and JavaScript have a complicated relationship with inheritance. I have seen opinions stating that class inheritance is absolutely evil and should be avoided in all circumstances, and those who favor composition over inheritance, but don’t discount class inheritance entirely.

Those that are against class inheritance entirely often favor composing classes with modules to add behavior. The funny thing here is that including modules functions pretty much exactly the same as class inheritance. If a method is not defined in the class, Ruby looks up the inheritance tree, starting with the modules included.

The favor for composition comes from the fact that composing classes with modules is more flexible than what a class hierarchy offers and classes can essentially achieve multiple inheritance through module inclusion.

I decided to take the idea to its extreme recently in a project at work. After students enroll in courses at Bloc, they are taken through an onboarding workflow where they create a profile, select their mentor, create a schedule of appointments, etc. We created a neat class called OnboardWorkflow that defined a series of determined steps so that students would go through onboarding in the order we wanted them to.

Refactoring Fat Models with DCI

Rails developers are familiar with the maxim “fat models, skinny controllers”. If logic starts creeping into our controllers, most developers seem content to push that logic into a model. But obese models can make for painful development. At Bloc, we’ve reached the point where this has become painful enough that I decided something needed to be done about it. After reading through Jim Gay’s fantastic Clean Ruby, I identified many areas in which our application could benefit from the DCI (data, context, interaction) design pattern.

DCI, according to that wikipedia link above, “separates the domain model (data) from use cases (context) and Roles that objects play (interaction)”. In Clean Ruby, Jim Gay illustrates this concept with transferring money between two accounts. The domain model is an account, which takes on the role of a transferrer of money from itself to another account, in the context of transferring money.

The situation I came across in the Bloc application involved populating a progress bar with data related to a student’s enrollment. This used to be fairly straightforward, but after introducing our Track products, in which students can take a track of two courses, it became a little more complicated.

Practical Object-Oriented Refactoring

This post first appeared on the Bloc blog in January 2015

As code bases grow, the need to refactor grows with it. A couple weeks ago, I saw an opportunity to refactor Bloc’s scheduled emails, which we activate in a Rakefile.

The Rakefile looked something like this:

task :send_greeting_email => :environment do
  Enrollment.starting_in_the_next_two_weeks.each do |enrollment|

    EnrollmentMailer.program_coordinator_greeting(enrollment).deliver
  end
end

task :send_get_started_emails => :environment do
  starting_enrollments = Enrollment.where('course_start_date > ? AND course_start_date < ?', Time.now, Time.now).where(sent_get_started_email: false)

  starting_enrollments.each do |enrollment|
    EnrollmentMailer.get_started(enrollment).deliver
  end
end

task :send_final_day_email => :environment do
  Enrollment.active.graduating_on(Date.today).each do |enrollment|
    EnrollmentMailer.graduation_letter(enrollment).deliver
    MentorMailer.confirm_grad(enrollment).deliver
  end
end

Plus several more notifications.

I wanted to test the code in this file, but as it is, it’s not very friendly to testing. However, there was a pattern among all these scheduled emails - grabbing specific enrollments and performing certain email actions. Sounds like a great use case for a service object.

A Functional Approach to Verbal Math in Ruby

Inspired by my functional approach to solving the verbal math problem in JavaScript, I decided to implement a similar approach in Ruby.

My first solution took advantage of Ruby’s everything-is-an-object nature, sending number objects symbols and values, which made solving the problem pretty easy.

However, it’s possible to take a functional approach in Ruby that is nearly equivalent to how you could solve this problem in JavaScript. And then, you can even combine this with Ruby’s object-oriented nature and metaprogramming capabilities to create a truly elegant solution.

While JavaScript has anonymous functions, Ruby has something similar in blocks, procs, and lambdas.

Here’s a language conversion to illustrate how you can achieve very similar functionality in Ruby and JavaScript (Check out my last post where I explain the JavaScript function in-depth):

JavaScript:

function plus(amount) {
  function add(number) {
    return number + amount;
  }
  return add;
}