Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mystifying "undefined constant" issue with Ruby/Rails

I've got a Rails project where a constant is being nuked at some point while serving a request.

I'm using the mime/types and restclient gems. The restclient module defines an extension to MIME which contains the method type_for_extension.

module RestClient
    ...
    def stringify_headers headers
      result[key] = target_values.map { |ext| MIME::Types.type_for_extension(ext.to_s.strip) }.join(', ')
      ...
    end
  end
end

module MIME
  class Types
    def type_for_extension ext
      candidates = @extension_index[ext]
      candidates.empty? ? ext : candidates[0].content_type
    end
    class << self
      def type_for_extension ext
        @__types__.type_for_extension ext
      end
    end
  end
end

I can access MIME::Types.type_for_extension on my first invocation of a given controller action. On the second invocation, it's gone.

I can still use MIME::Types.type_for, but the added method is simply gone, so when I try to use the RestClient module it throws an exception on the line showin in stringify_headers:

NoMethodError, message: undefined method `type_for_extension' for MIME::Types:Class

**How is this possible? type_for_extension defined in the same file as stringify_headers; how could the latter get nuked but not the former?


EDIT: FIXED IT!

In my config:

config.gem "aws-s3", :version => ">= 0.6.2", :lib => "aws/s3"  
config.gem 'mime-types', :lib => 'mime/types'

aws-s3 was loading mime-types via require_library_or_gem, which ultimate invoked ActiveSupport::Dependencies.autoload_module! which maintains a table called autoloaded_constants which are nuked when ActionController.close calls Dispatcher.cleanup_application.

Fix was to load mime-types first, so it's not autoloaded.

*whew*

like image 682
Mud Avatar asked Jul 16 '11 22:07

Mud


1 Answers

Answering my own question by request.

In my config:

config.gem "aws-s3", :version => ">= 0.6.2", :lib => "aws/s3"  
config.gem 'mime-types', :lib => 'mime/types'

aws-s3 library was loading mime-types via require_library_or_gem, which ultimately invoked ActiveSupport::Dependencies.autoload_module! which maintains a table called autoloaded_constants which are nuked when ActionController.close calls Dispatcher.cleanup_application.

Fix was to load mime-types first, so it's not autoloaded.

like image 57
Mud Avatar answered Nov 07 '22 13:11

Mud