Rails core_ext: Array - extract_options

in rails
If you’re not familiar with the series, please take a look at this post.

This post will be short because in the extract_options.rb file there are a few lines of code to read but I preferred to publish it for the sake of completeness of the series. By the way, it’s an important extension to the Array class because it’s widely used in the rails code itself. Just for curiosity, I use a command like the following to search through the rails code:

ack "\.extract_options\!" --no-group --ignore-dir=test

I got 67 lines today so this one is really widely used. Well, first of all the code:

class Hash
  # By default, only instances of Hash itself are extractable.
  # Subclasses of Hash may implement this method and return
  # true to declare themselves as extractable. If a Hash
  # is extractable, Array#extract_options! pops it from
  # the Array when it is the last element of the Array.
  def extractable_options?
    instance_of?(Hash)
  end
end

class Array
  # Extracts options from a set of arguments. Removes and returns the last
  # element in the array if it's a hash, otherwise returns a blank hash.
  #
  #   def options(*args)
  #     args.extract_options!
  #   end
  #
  #   options(1, 2)           # => {}
  #   options(1, 2, :a => :b) # => {:a=>:b}
  def extract_options!
    if last.is_a?(Hash) && last.extractable_options?
      pop
    else
      {}
    end
  end
end

So, I think this time there is no much to say. The code is very well-documented and easy to read. I really liked the explanation about the extractable_options? method in the Hash class, the method ensures only instances of Hash will be extractable in the most elegant way possible. Regarding the extract_options! code, I won’t comment it because it is very simple to read and to understand. However, it’s worth the reading because this method allows many rails helpers like highlight and excerpt to have that nice API. Furthermore, other many rails APIs like the mapper.rb uses the extract_options! method extensively.

So, that’s enough for now. Stay tuned!

Fork me on GitHub