Video

Want to see the full-length video right now for free?

Sign In with GitHub for Free Access

Notes

On this week's episode, Chris is again joined by Melanie Gilman to discuss the amazing array of extensions added to Ruby by Rails' Active Support component.

What Is It?

Active Support is the collection of extensions to Ruby that Rails provides. It adds additional utility methods to core classes like Date and String to bring even more user-friendliness to Ruby's already very friendly landscape.

In this video we'll provide an overview of some of our favorite methods from Active Support, but be sure to check out the outline in the Active Support Guide which provides a much more thorough summary of the provided methods.

Object Methods

Some methods are so useful that Active Support includes them on Object, making them available on every object instance.

Present and Blank

"".present?
#=> false
"hello".present?
#=> true

[].present?
#=> false
[1, 2, 3].present?
#=> true

{}.present?
#=> false
{ a: 1, b: 2 }.present?
#=> true


"".blank?
#=> true
"hello".blank?
#=> false

[].blank?
#=> true
[1, 2, 3].blank?
#=> false

{}.blank?
#=> true
{ a: 1, b: 2 }.blank?
#=> false

Presence

presence allows you to check for the presence of a value and use it if present, otherwise it will return nil. This allows you to collapse the common object.present? && object expressions.

def keywords(words)
  words.presence || Topic.all.pluck(:name).join(", ")
end

# Equivalent method without using presence
def keywords(words)
  if words.present?
    words
  else
    Topic.all.pluck(:name).join(", ")
  end
end

Try

try allows you to call a method on an object only if the object responds to the method, otherwise it returns nil. This can be useful in cases where an object may be present, or may be nil, as nil.try(:any_method) will just return nil again.

def status
  statuses_by_id[@trail.id].try(:first) || Unstarted.new
end

Note - While it is possible to chain multiple try calls, e.g. video.try(:trail).try(:name).try(:titleize), this is likely something you want to avoid. try violates "Tell Don't Ask" as well as the "Law of Demeter", and chaining multiple together compounds this quickly.

String Methods

Active Support provides a number of methods that transform a string in some way. Many of these are used in Rails' convention-based mappings between controllers, models, table names, etc.

"snake_case_string".camelize
#=> "SnakeCaseString"

"camelCaseString".underscore
#=> "camel_case_string"

"a_long_variable_name".humanize
#=> "A long variable name"

"a string for a url".parameterize
#=> "a-string-for-a-url"

"a lower case string".titleize
#=> "A Lower Case String"

"post".pluralize
#=> "posts"

"posts".singularize
#=> "post"

" \n  weird\n\r \t whitespace \n".squish
#=> "weird whitespace"

Array Methods

fruits = ["apples", "oranges", "bananas"]
fruits.to_sentence.capitalize
#=> "Apples, oranges, and bananas"

# The `in?` method is the `include?` method with caller and receiver flipped
"apples".in? fruits
#=> true
fruits.include? "apples"
#=> true

Forty Two

Ruby provides the .first method to access the first element of an array. Active Support provides similar methods for additional elements in an array, e.g. second and third. While these only go up to fifth, oddly enough there is an outlier forty_two method which exists for fun reasons. Quoting the docs:

Thanks to social wisdom and positive constructiveness all around, forty_two is also available.

Dates and Times

Dates and Times are notoriously difficult to work with, but with Active Support we have a whole slew of methods that make working with dates and even doing Date and Timezone math easy and very readable.

Date.today
#=> Tue, 08 Jul 2014
Date.today.next_month
#=> Fri, 08 Aug 2014
Date.today + 3.days
#=> Fri, 11 Jul 2014
Date.today.beginning_of_week
#=> Mon, 07 Jul 2014
Date.today.next_week(:friday)
#=> Fri, 18 Jul 2014
Date.today.tuesday?
#=> true
Date.today.all_week
#=> Mon, 07 Jul 2014..Sun, 13 Jul 2014
3.days.ago
#=> Sat, 05 July 2014

Using Active Support Outside of Rails

Rails includes all of Active Support by default, but luckily it exists as a standalone gem and can be included in non-Rails apps if desired.

You can load all of Active Support with:

require "active_support/all"

or load just the extensions for a specific class like String with:

require "active_support"
require "active_support/core_ext/string"

Is Monkey Patching the World A Good Idea?

Monkey patching has gone somewhat out of favor of late, especially when you consider the recent work to introduce Refinements to Ruby. With this in mind it is worth thinking about whether we are comfortable monkey patching nearly every object in our system.

In general the community seems to support the majority of Active Support, and certain examples such as the Date & Time math are absolutely critical pieces of many web applications.

It's possible to make a comparison to Prototype.js as both Active Support and Prototype provide much of their functionality by extending and modifying core classes. While similar in functionality to Prototype.js, Active Support has the benefit of running in a controlled server process. One of the major concerns with Prototype was that it modified and extended core objects in the JavaScript environment that is shared by all code running on the page. With Rails, our code runs on our servers and we can control all of it, making these sorts of collisions less likely and more manageable.

tl;dr While Active Record is somewhat extreme in the extensions it makes, the community has embraced these changes and in many cases they provide drastically simpler and more expressive ways to write your code. Solid understanding of what is in Active Support is definitely worth your time.