Contribution Libre Développement Ruby Ruby on Rails 2013 | 07 | 31

Airbrake fix

After installing airbrake gem my collection’s request Rspec.specs stoped working as expected.

I encounterd this error:

RuntimeError: can't add a new key into hash during iteration

Since Ruby 1.9(.3?) you cant modify Hash within iteration (even if they are ordered).

After some hours spent in debugger, I found that airbrake gem Notification class uses Rack request @env variable to collect params for aibrake/errbit notification.

Nothing weird here, but while collecting params in a loop , the clean_params method hit the racks request’s @env with the #cookies method, in order to obtain the cookie hash. Code below :

def cookies
      @env= @env.dup
      hash   = @env["rack.request.cookie_hash"] ||= {}
      string = @env["HTTP_COOKIE"]

      return hash if string == @env["rack.request.cookie_string"]
      hash.clear

      # According to RFC 2109:
      #   If multiple cookies satisfy the criteria above, they are ordered in
      #   the Cookie header such that those with more specific Path attributes
      #   precede those with less specific.  Ordering with respect to other
      #   attributes (e.g., Domain) is unspecified.
      cookies = Utils.parse_query(string, ';,') { |s| Rack::Utils.unescape(s) rescue s }
      cookies.each { |k,v| hash[k] = Array === v ? v.first : v }
      @env["rack.request.cookie_string"] = string
      @env = env
      hash
end

This method is available from the class Api (not private) and returns the cookie Hash, but it also have side effects … Sadly, it mutates the @env. I can’t say if this is bad design or not, but it looks weird to mee.

In order to get this working I submitted a fix to airbrake, not to Rack … Last words, thanks to ThoughBot guys, for all the opensource tools they provide, and reactivity to merge contribs.