Some Ways ActiveSupport Helps Ruby Developers

Manu Ajith
Share

Ruby is an object-oriented, interpreted language invented by Yukihiro Matsumoto in 1993 that is heavily inspired by Perl and Lisp. Since its inception, Ruby has been designed to be a “joy to use” – meaning a strong focus on readability and elegance.

Ruby on Rails, often simply Rails, is an open source web application framework which runs on the Ruby programming language. Ruby on Rails is intended to emphasize Convention over Configuration (CoC), and the rapid development principle of Don’t Repeat Yourself (DRY). Rails is a powerful framework that can help you become more productive and confident.

Rails uses various gems, many that are frameworks in their own right, to give you abstractions that help write clean and DRY code. One of those gems is ActiveSupport, which defines itself on Rubygems.org as:

A toolkit of support libraries and Ruby core extensions extracted from the Rails framework. Rich support for multibyte strings, internationalization, time zones, and testing.

Essentially, ActiveSupport extends many of the core Ruby classes to give the syntactic sugar that Rails uses. Let’s take a look at some of these abstractions and see how they help (and hurt) you as a developer.

Hash in Ruby

A Hash is a dictionary-like collection of unique keys and their values. Also called associative arrays, they are similar to Arrays, but where an Array uses integers as its index, a Hash allows you to use any object type.

Example of a Hash:

#initialize an empty hash colors
colors = { }

#add a color with key as red
colors[:red] = "Red Color"

#add a color with key as blue
colors[:blue] = "Blue Color"

#display the hash
colors  #=> {:red=>"Red Color", :blue=>"Blue Color"}

The value of a particular key can be fetched from the hash by:

Hash[key]    
or
Hash.fetch(:key)

If we want to fetch the value for the key :red, then

colors[:red]  #=> "Red Color"

But if we try colors['red'] we will get the value as nil.

colors['red'] #=> nil

This is because Hash treats symbols and string in keys differently. This can be explained further if we add another key-value to our hash.

colors['red'] = "Red color, here key is not a symbol"

Now, if we try to fetch the value for the key, it will return our new value.

colors['red'] #=> "Red color, but key is not a symbol"
colors[:red] #=> "Red Color"

Consider an example where we have two hashes, a = {"red": "Red color"} and b = {:red => "Red color"}.

If we merge these two hashes, like so

a.merge! b   #=> {"red" => "Red color, :red => "RED COLOR"}

and try to fetch the values from hash

a['red']  #=> "Red color"
a[:red]   #=> "RED COLOR"

the result is not ideal, to say the least.

This can be a bit confusing at times, especially if you have worked with Rails. Rails allows you to access, for example, params[:name] or params['name'] in a controller action receive the same value. This is due to Rails use of ActiveSupport::HashWithIndifferentAccess instead of the normal Hash.

HashWithIndifferentAccess

HashWithIndifferentAccess is a class defined inside the ActiveSupport gem that helps us overcome the aforementioned issue. Here, the symbols in the keys will be converted to strings, so we can fetch the values from a hash using both symbols as well as strings.

Example:

(If you arent using Rails then dont forget to require active_support)

require 'active_support/core_ext/hash/indifferent_access'
colors = HashWithIndifferentAccess.new
colors[:red] = "Red color"

#Fetch the value using symbol
colors[:red]  #=> "Red color"

#Fetch the value using string
colors["red"]  #=> "Red color"

If we want to convert an existing Hash to HashWithIndifferentAccess

colors = { blue: 'Blue color', white: 'Red Color' }.with_indifferent_access

HashWithIndifferentAccess is used by all Rails developers, sometimes unknowlingly.

ActiveSupport::Inflectors

Inflectors is a module that ships along with the ActiveSupport and is included in your Rails app. Inflectors offers many methods that are helpful for developers. If we want to use the module independently in our ruby scripts, we need to include the module inside our ruby code as:

require 'active_support/inflector'

Some of the commonly used and beneficial inflectors are explained here.

Camelize

It converts strings to CamelCase strings. These are mostly beneficial when working with Ruby constants.

Example:

'manu'.camlize #=> 'Manu'

Humanize

This method uses regular expressions to convert the strings to more human readable strings. These can be used in urls, among other things.

Example:

'author_id'.humanize #=> 'Author'

Titelize

This will generate a nice and clean, title-like output after removing special characters from the string

Example:

'x-men: the last stand'.titleize #=> "X Men: The Last Stand"

More methods can be found in the Rails API guide and details on the code can be found on github

ActiveSupport Extensions

ActiveSupport::Extensions offer utilities for extending Ruby.
These extensions are part of the ActiveSupport core and can be loaded into a Rails app by including active_support. If you only want a particular method, then include that by cherry-picking it, like so:

require 'active_support/core_ext/object/try.rb'

Some useful methods that are part of the ActiveSupport::Extensions are described below:

try method

The try method is one of the most useful methods included with ActiveSupport. You can use this method to in place of a block that checks if an object is nil before calling a method on that object.

Example:

# without try
if @user.first_name
  puts @user.first_name
end    

# with try
@user.try(:first_name)

Thus try would help us to avoid the unnecessary conditional statements.

Extensions to Numeric

Formatting

Using this method, numbers can be formatted in a variety of ways.

Phone Numbers:

Example:

5551234.to_s(:phone)
# => 555-1234
1235551234.to_s(:phone)
# => 123-555-1234
1235551234.to_s(:phone, area_code: true)
# => (123) 555-1234
1235551234.to_s(:phone, delimiter: " ")
# => 123 555 1234
1235551234.to_s(:phone, area_code: true, extension: 555)
# => (123) 555-1234 x 555
1235551234.to_s(:phone, country_code: 1)
# => +1-123-555-1234

Currency

Example:

1234567890.50.to_s(:currency)                 # => $1,234,567,890.50
1234567890.506.to_s(:currency)                # => $1,234,567,890.51
1234567890.506.to_s(:currency, precision: 3)  # => $1,234,567,890.506

Percentage

Example:

100.to_s(:percentage)
# => 100.000%
100.to_s(:percentage, precision: 0)
# => 100%
1000.to_s(:percentage, delimiter: '.', separator: ',')
# => 1.000,000%
302.24398923423.to_s(:percentage, precision: 5)
# => 302.24399%

Human Readable Values

Example:

123.to_s(:human)               # => "123"
1234.to_s(:human)              # => "1.23 Thousand"
12345.to_s(:human)             # => "12.3 Thousand"
1234567.to_s(:human)           # => "1.23 Million"
1234567890.to_s(:human)        # => "1.23 Billion"
1234567890123.to_s(:human)     # => "1.23 Trillion"
1234567890123456.to_s(:human)  # => "1.23 Quadrillion"

Conversions

to_sentence

This methods converts an array of words into a sentence.

Example:

%w().to_sentence                # => ""
%w(Earth).to_sentence           # => "Earth"
%w(Earth Wind).to_sentence      # => "Earth and Wind"
%w(Earth Wind Fire).to_sentence # => "Earth, Wind, and Fire"

More methods and a detailed explanation can be found by browsing the source code of ActiveSupport itself.

Conclusion

Many of the methods that are part of Rails or its included modules are under-utilized. One of the best resources to explore these are by browsing the source code itself.

Manu S Ajith

@manusajith

CSS Master, 3rd Edition