Note that this seems to affect only recent Rails 2 versions.
You will not encounter this until you are writing to the cookie more than once, but when doing so, integration tests (Cucumber) may break for you with this error:
You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.[] (NoMethodError)
Background
The regular/short cucumber backtrace is not of any help but looking at the full trace reveals that ActionPack's action_controller/integration.rb
is breaking while doing this:
cookies = @headers['Set-Cookie']
cookies = cookies.to_s.split("\n") unless cookies.is_a?(Array)
cookies.each do |cookie|
name, value = cookie.match(/^([^=]*)=([^;]*);/)[1,2]
@cookies[name] = value
end
This won't work when you there are empty lines in a cookie -- which is exactly what happened for me. That is how my cookie looked when debugging:
(rdb:1) puts headers['Set-Cookie']
remember_token=abcdef123456; path=/; expires=Mon, 31-Dec-2029 23:03:29 GMT
foo=23; path=/; expires=Thu, 30-Jan-2020 23:03:29 GMT
bar=42; path=/; expires=Thu, 30-Jan-2020 23:03:30 GMT
_some_session=foobarbaz; path=/; expires=Thu, 31-Dec-2020 23:03:30 GMT; HttpOnly
Solution
This seems to be a bug in Rails, the CookieStore (for sessions) or Rack::Utils.set_cookie_header
-- I did not bother looking closer.
My problems went away when introducing an initializer that cleans up line breaks:
module ActionController
module Session
CookieStore.class_eval do
def call_with_line_break_fix(*args)
status, headers, body = call_without_line_break_fix(*args)
headers['Set-Cookie'].gsub! "\n\n", "\n" if headers['Set-Cookie'].present?
[ status, headers, body ]
end
alias_method_chain :call, :line_break_fix
end
end
end
Put that into a file like config/intializers/cookie_store_with_line_break_fix.rb
and you are good to go.
If you don't feel like monkey-patching, you could also write a Rack middleware Show archive.org snapshot that tidys up your cookie data. I prefer doing API-stable patches, if possible.