Date::ABBR_MONTHS issue in AWS S3 Ruby Library
March 26th, 2008
In the aws/s3 ruby library you will find the following piece of code under logging.rb:
datetime.sub!(month, Date::ABBR_MONTHS[month.downcase].to_s)
It will result in the following exception for some versions of Ruby, but apparently not all versions
NameError: uninitialized constant Date::ABBR_MONTHS
Oddly enough, according to the Standard Ruby Documentation, this constant should exist right in the Date class
But, If you do some digging you will find that the actual place for the constant is:
Date::Format::ABBR_MONTHS
I came across this error when trying to call the attributes method on AWS::S3::Logging::Log::Line
So that leaves me with a few questions:
- How did the aws/s3 code work for the developers that wrote it ? The most plausible explanation, especially given the rDocs, is that perhaps they were using a different version of Ruby …
- If so, how come the constant has been moved around?
- How do I get around this issue without monkey patching the AWS/S3 Gem ?
Resolution
Instead of overwriting the faulty function in the AWS/S3 Ruby library, I decided instead to add the constant to the Date class.
- Create a file under lib folder called date_fix.rb
- Place the following code within it:
1 2 ABBR_MONTHS = Date::Format::ABBR_MONTHS 3 end
- Require the file in your environment.rb or if you want the change to be less global, require the file where ever you are using code that needs the patch:
I think this approach is better than the other alternatives (upgrading Ruby from patchlevel 111 to patchlevel 114 in hopes of fixing the issue (it probably won’t) or monkey patching the aws/s3 library) because it is non-intrusive. We’re simply adding a constant to a class so no code dependencies can be broken by the change.
However, in case you want you change fix the AWS/S3 function instead, do this instead:
- Create a file under lib folder called s3_aws_fix.rb
- Please the following code within it:
1 2 3 4 # Time.parse doesn't like %d/%B/%Y:%H:%M:%S %z so we have to transform it unfortunately 5 #:nodoc: 6 month = datetime[/[a-z]+/i] 7 datetime.sub!(%r|^(\w{2})/(\w{3})|, '\2/\1') 8 datetime.sub!(month, (Date.constants.member?('ABBR_MONTHS') ? Date::ABBR_MONTHS : Date::Format::ABBR_MONTHS)[month.downcase].to_s) 9 datetime.sub!(':', ' ') 10 Time.parse(datetime) 11 end 12 end 13 end 14 end
- Require the file in your environment.rb after the require ‘aws/s3’ call or any where else.
I was using:
- AWS / S3 Ruby Gem Version: 0.4.0
- Ruby version 1.8.6 patch level 111 (the one that comes with Mac OSX I believe)
1 Response Follows
Sorry, comments are closed for this article.
on March 28th, 2008 at 09:28 AM Nice post. Good tip, you should probably patch the aws/s3 library