Using Variants in Rails 4

I’ve been using Variants in Rails 4 to change my layouts for one controller action. It’s really straightforward – just set the variant name as a symbol, for example:

request.variant = :popup

Then name the template file with the variant name in it, e.g.

new.html+popup.haml

Another neat trick I discovered is that you can also use the variant to control the layout file. I wanted to have a different layout for my popup content, one that didn’t include all of the usual bumph like headers and menus. Turns out I didn’t need any other code, just create a template in my layout folder with the variant:

website.html+popup.haml

In addition to that, I can also use it with partials. Inside my haml file, I reference a partial as I would normally, and when the variant is set, it automatically chooses the partial with the variant if there is one.

...
= render partial: 'customer' 
...

Now I can use the popup variant across multiple controllers with this same simple layout.

I also discovered that setting variant to nil causes a problem. I wanted to do this:

request.variant = find_my_variant
...
...
...
def find_my_variant
  return nil if some_logic_determining_no_variant
  :variant_name
end

Instead I have to do this:

request.variant = find_my_variant unless find_my_variant.nil?
...
...
...
def find_my_variant
  return nil if some_logic_determining_no_variant
  :variant_name
end

I’m interested to know if there is a way to set a “blank” or default variant so that I can remove that extra check …

Try and Fetch

One of my colleagues showed me this awesome little method in Rails called try.

How many times have you written code to check for nil like this?

def get_value
  if @my_object.nil?
    ""
  else
    @my_object.value
  end
end

(well I have, many times!)

If you call try on an object if you’re not sure whether or not it will respond to that method. If it doesn’t, then you just get back nil:

def get_value
  @my_object.try(:value)
end

Particularly useful if you want to call a method on something you get back from a hash that may not be there:

@my_object[:my_key].try(:method)

While reading up on this, I also discovered the fetch method for Hashes, which allows me to specify a default value to return if the key is missing.

This means I can clean up stuff like this:

my_array = @my_hash[:my_key]
my_array.each {|array_item| ... some code ... } unless my_array.nil?

To this:

@my_hash.fetch(:my_key, []).each {|array_item| ... some code ... }

Less if statements, less branching, and so hopefully fewer bugs to write!

Controlling Asset Precompilation in Rails

I’ve run into issues recently with precompilation after introducing new gems containing partial SASS files (Bootstrap and Font Awesome).

Rails allows you to specify patterns or Procs to determine which files should – or in our case should not – be precompiled, like this:

Rails.application.config.assets.precompile = [Proc.new {|e| !(e =~ /(font-awesome|bootstrap)\/_/) } ]