Mystifying "undefined constant" issue with Ruby/Rails - ruby-on-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*

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.

Related

Getting uninitialized constant error from unused gem

I was trying to use the Addressable gem in a specific action in Rails.
My usual practice is to include the gem in the Gemfile, and then require the module where needed.
Gemfile:
gem 'addressable'
some_controller.rb:
class SomeController < ApplicationController
def new
require "addressable/uri"
current_url = Addressable::URI.parse(request.original_url)
....
end
end
However, I was getting a 500 error on other actions/controllers that did not use the gem.
Error during failsafe response: uninitialized constant Addressable
Finally, I removed all the code calling addressable, but kept the entry in the gemfile, and the 500 error persists on all actions. Why would this be?
Not sure why you're getting that specific error, but with a gem like Addressable where you don't want an automatic require 'addressable' performed then in your Gemfile you should have:
gem 'addressable', :require => false

ruby on rails roo gem cannot load zip/zipfilesystem

I am attempting to use the roo gem to process .xlsx spreadsheets that are uploaded by an outside party. I'm getting the following error:
LoadError (cannot load such file -- zip/zipfilesystem):
I've found a lot of questions similar to this one (such as cannot load such file -- zip/zip) and I've tried to follow their solutions. So far, to no avail.
I originally required 'roo' in the controller, and after getting this error tried requiring 'zip/zip', 'zip/zipfilesystem', and just 'zip'. None of these seem to fix anything. I've also tried adding :require => 'zip', :require => 'zip/zipfilesystem', :require => 'zip/zip' to the Gemfile, and none of that seemed to change anything. Here is some pertinent code:
in Gemfile:
# for spreadsheet upload management
gem 'roo'
gem 'rubyzip'
gem 'spreadsheet'
gem 'nokogiri'
installed versions:
nokogiri (1.6.0)
roo (1.12.1)
rubyzip (1.0.0)
spreadsheet (0.8.9)
in Controller:
require 'roo'
module BatchOrderProcessing
class DataFilesController < ApplicationController
def create
# some code here ...
when ".xlsx"
spreadsheet = Roo::Excelx.new(uploaded_io.path, nil, :ignore)
header = spreadsheet.row(1)
if # some validation stuff...
puts "spreadsheet format inappropriate"
redirect_to # some place
end
process_datafile(fname, spreadsheet)
# more code ...
end
private
def process_datafile(fname, spreadsheet)
#df = DataFile.new
#df[:filename] = ActiveRecord::Base.connection.quote(fname)
if #df.save
begin
# parse asynchronously
datafile_scheduler = Rufus::Scheduler.new
datafile_scheduler.in '3s' do
#df.process_spreadsheet(spreadsheet)
end
redirect_to #df
rescue => e
# more code ...
end
else
# more code ...
end
end
I think this thing is crapping out before it gets to the model (where the process_spreadsheet() code is), but just in case, here's some model code:
def process_spreadsheet(spreadsheet)
# do some stuff
puts "parsing spreadsheet"
(2..spreadsheet.last_row).each do |i|
row = Hash[[header, spreadsheet.row(i)].transpose]
row_array << row
invoice << row.to_s
# some more code....
dfi = DataFileItem.new()
dfi.attributes = row.to_hash.slice(*accessible_attributes)
dfi.data_file_id = self.id
dfi.save
self.data_file_items << dfi
# Update stuff in our DB based on rows in row_array...
end
I'm using rails 3.2.13 and ruby 2.0.0p195.
Am I requiring the wrong thing (or in the wrong way) somewhere? Let me know if any other code snippets would be helpful. Thaaaaanks.
rubyzip v1.0.0 was released 29 August 2013: https://github.com/rubyzip/rubyzip/releases
This is a new major version number, and more than one gem or project that depends on this has been caught out by the break with backwards-compatibility.
The quickest "get my code working like before" fix is to alter Gemfile reference to rubyzip:
gem 'rubyzip', '< 1.0.0'
In the longer-term, this may not be the best fix, it depends on how and/or why you are using rubyzip. I expect some gem publishers such as roo's authors will need to figure out how to transition nicely so that their own users don't end up with simultaneous requirements for incompatible versions of rubyzip.
Just opinion:
Seeing this in action has actually made me much less a fan of Ruby gems semantic versioning for major versions. If I ever break with backwards compatibility on any of my own projects, I think I'll just start a new gem, and put a notice on the old gem.
Try adding the zip-zip gem to your project. It provides a simple adapter for your dependencies using the RubyZip v0.9.9 interface allowing you to upgrade to RubyZip v1.0.0.
This has been fixed in the roo gem. You need to update to version 1.12.2 or higher to fix. See the issue here: https://github.com/Empact/roo/pull/65

Getting uninitialized constant error when trying to run tests

I just updated all my gems and I'm finding that I'm getting errors when trying to run Test::Unit tests. I'm getting the error copied below. That comes from creating new, empty Rails project, scaffolding a simple model, and running rake test.
Tried Googling "uninitialized constant" and TestResultFailureSupport. The only thing I found was this bug report from 2007.
I'm using OS X.
These are the gems that I updated right before the tests stopped working:
$ sudo gem outdated
Password:
RedCloth (4.2.1 < 4.2.2)
RubyInline (3.8.1 < 3.8.2)
ZenTest (4.1.1 < 4.1.3)
bluecloth (2.0.4 < 2.0.5)
capistrano (2.5.5 < 2.5.8)
haml (2.0.9 < 2.2.1)
hoe (2.2.0 < 2.3.2)
json (1.1.6 < 1.1.7)
mocha (0.9.5 < 0.9.7)
rest-client (1.0.2 < 1.0.3)
thoughtbot-factory_girl (1.2.1 < 1.2.2)
thoughtbot-shoulda (2.10.1 < 2.10.2)
Has anyone else seen this issue? Any troubleshooting suggestions?
UPDATE
On a hunch I downgraded ZenTest from 4.1.3 back to 4.1.1 and now everything works again.
Still curious to know if anyone else has seen this or has any interesting comments or insights.
$ rake test
(in /Users/me/foo)
/usr/local/bin/ruby -I"lib:test" "/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/unit/helpers/users_helper_test.rb" "test/unit/user_test.rb"
/usr/local/lib/ruby/gems/1.8/gems/activesupport-2.3.2/lib/active_support/dependencies.rb:105:in `const_missing': uninitialized constant Test::Unit::TestResult::TestResultFailureSupport (NameError)
from /usr/local/lib/ruby/gems/1.8/gems/test-unit-2.0.2/lib/test/unit/testresult.rb:28
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
from /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.3.2/lib/active_support/dependencies.rb:158:in `require'
from /usr/local/lib/ruby/gems/1.8/gems/test-unit-2.0.2/lib/test/unit/ui/testrunnermediator.rb:9
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
from /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.3.2/lib/active_support/dependencies.rb:158:in `require'
... 6 levels...
from /usr/local/lib/ruby/1.8/test/unit/autorunner.rb:214:in `run'
from /usr/local/lib/ruby/1.8/test/unit/autorunner.rb:12:in `run'
from /usr/local/lib/ruby/1.8/test/unit.rb:278
from /usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader.rb:5
/usr/local/bin/ruby -I"lib:test" "/usr/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/functional/users_controller_test.rb"
This can happen if modules are declared in a single statement when the parent module they are nested inside has not yet been loaded. I haven't looked at the code in those gems, but my hunch is that's what is happening. Chuck's solution would suggest that. calling gem 'test-unit' first will load the parent module, so the setup of zen test ends up working ok.
e.g.
module Foo::Bar
def do_stuff
# insert awesomeness here...
end
end
Will result in an error if the parent Foo module hasn't already been defined (e.g. by another gem)
A safer way to declare this is
module Foo
module Bar
def do_stuff
# insert awesomeness here...
end
end
end
May be a bug in Zentest that needs patching.
This apparently comes from using Test::Unit 2.0 with the old Test::Unit. According to Kouhei Sutou on RubyForge, it can be fixed by calling gem 'test-unit' before you require 'test/unit'.
As this link suggests http://floehopper.lighthouseapp.com/projects/22289-mocha/tickets/50
it may happen due to preliminary initialization of mocha lib.
To prevent it from happeing it is advisable to add line
config.gem 'test-unit', :lib => 'test/unit'
to config/environment.rb
Here is the recipe for test_unit 2.0.7 on Rails 2.3.5:
In config/environments/test.rb:
config.gem 'test-unit', :version => '2.0.7', :lib => false
In test_helper.rb,
add require 'test/unit',
immediately after require 'test_help'
So it looks like this:
require 'test_help'
require 'test/unit'
If you receive this error:
%': one hash required (ArgumentError),
upgrade gem i18n to v0.3.6.
I was getting this without mocha or shoulda installed.
This post suggests it's due to an incompatibility in test-unit >= 2.0, which I installed as a dependency for the systools gems. Downgrading to 1.2.3 worked for me, a simple require might also.
Same issue with me too.
Nothing above mentioned worked for me except downgrading test-unit back to 1.2.3
I'm missing the coloring of the test-unit 2.x
Found the (ugly) solution:
gem 'unit/test'
must be called inside the tests too, not only in the Rakefile.
I ran into this today on Mac OS X 10.6. My solution is as follows:
config.gem 'test-unit', :lib => 'test/unit', :version => '1.2.3'
config.gem 'autotest'
config.gem 'cucumber'
config.gem 'cucumber-rails', :lib => false
config.gem 'ffaker', :lib => 'faker'
config.gem 'rspec', :lib => false, :version => '>= 1.2.0'
config.gem 'rspec-rails', :lib => false, :version => '>= 1.2.0'
config.gem 'selenium-client', :lib => 'selenium'
config.gem "thoughtbot-factory_girl", :lib => 'factory_girl', :source => "http://gems.github.com"
config.gem 'thoughtbot-shoulda', :lib => 'shoulda'
config.gem 'webrat'
config.gem 'ZenTest', :lib => 'zentest'
As with aronchick's comment, for me (OS X 10.6) solution was
sudo gem uninstall test-unit
all versions.
You get auto_test to work again with something like
RUBY="ruby -I.:lib:test -rubygems -e 'gem \"test-unit\"'" autotest
I am not a nuby to rails but I am still learning and hopefully always will be :-).
Rails 2.3 production environment using Ruby Enterprise Edition and passenger can produce a totally misleading useless error during startup (/var/log/passenger.log). Something like:
Exception NameError in PhusionPassenger::Rack::ApplicationSpawner (uninitialized constant XXX)
If you run script/console on the production server, you may see:
Loading production environment (Rails 2.3.4)
/home/ubuntu/MyApp/shared/bundle/ruby/1.8/gems/activesupport-2.3.4/lib/active_support/dependencies.rb:105:in const_missing:NameError: uninitialized constant XXX
This is happening to me in this instance only in production environment, not staging, not development. After a full day of research and experiments, I have concluded that in the production environment, REE or something must pre-load classes and the pre-loader apparently does not like to see classes being re-opened before they are created (an educated guess).
In app/models/calendar.rb:
Class Calendar < ActiveRecord::Base
# This defines the class
End
In app/models/event.rb
Class Event < ActiveRecord::Base
# This desined the class
End
Class Calendar
# This is supposed to 're-open' the Calendar class
has_many :events
end
The above generic sample code snippet can cause startup issue. I am not sure of the order that pre-loading classes takes place but I suspect that may be the issue. I moved the ‘has_many :events’ into the class definition in app/modeles/calendar.rb and my app now starts without error.
So, a good rule to follow is to put your Active Record Associations (has_many, belongs_to) inside the defining class (where the class is created).
If you add the following line to your environment.rb, or your config/environments/test.rb this should fix the issue
config.gem "test-unit", :lib => "test/unit", :version => ">=2.0.9", :env => "test"
I Believe you will need to add it before the mocha line if you use mocha.

'no such file to load -- net/ssh' from rails Controller on Ubuntu

I have a very simple controller:
require 'net/ssh'
class MyController < ApplicationController
def foo
render :text => 'bar'
end
end
But when I request http://server:3000/my/foo I get:
MissingSourceFile in MyController#foo
no such file to load -- net/ssh
The gem is installed
> gem list net-ssh
*** LOCAL GEMS ***
net-ssh (2.0.11)
Also, I tried require 'net/ssh' in IRB, and it works.
MyController works fine on Windows, but fail on Ubuntu.
What can be wrong?
In a project I am working on we have used the config/environment.rb file to hold the gem require stuff. So
Rails::Initializer.run do |config|
# ...
config.gem 'net-ssh'
config.gem 'daemons'
config.gem 'slave'
config.gem 'vpim'
config.gem 'json'
# ...
end
I think you will require 'net-ssh' rather than 'net/ssh'. However we did run into a problem where have a hyphen in the name of the gem led to failures. Then we had to do
config.gem 'Ruby-IRC', :lib => 'IRC'
so that version maybe required for you. So that would be
config.gem 'net-ssh', :lib => 'net/ssh'
in case of rails 3.0
this solution if OK.
add this in the yourapp/Gemfile,
gem 'net-ssh
This may help:
Rails Gem Dependencies and Plugin Errors
This is also worth watching:
Railscasts: Gem Dependencies
In my case, since it's a stand alone ruby app, I only needed to require rubygems.
You can also use Dr Nic's ''gemsonrails'' and load vendored gems as plugins, check:
http://gemsonrails.rubyforge.org
I think, the original problem was that I used normal user instead of root:
$ gem install net-ssh
WARNING: Installing to ~/.gem since /usr/lib/ruby/gems/1.8 and
/usr/bin aren't both writable.
WARNING: You don't have /home/alex/.gem/ruby/1.8/bin in your PATH,
gem executables will not run.
So, I guess, rails could not find this gem.

config.gem requires gem?

I have a bunch of config.gem statements in my environment.rb file:
config.gem "fastercsv", :version => "~>1.5.0"
config.gem "parseexcel", :version => "~>0.5.2"
config.gem "geokit", :version => "~>1.4.1"
config.gem "facebooker", :version => "~>1.0.50"
...
If I do "rake gems:install" then I get this issue:
rake aborted!
no such file to load -- fastercsv
Well...i know there is no such file to load because I am trying to install it. I suspect this may result from the location of my require. I have a module in my lib directory:
module SmartContactsImporter
require 'fastercsv'
require 'parseexcel'
...
Maybe Rails doesn't like me requiring a gem there but it seems silly since there is nothing wrong with having your module depend on a gem. Any ideas on how to solve this issue?
UPDATE
Turns out that this issue also occured with mechanize, geokit, and the list is continuing. It's a bit strange that config.gem doesn't work pretty easily out of the box. FYI I'm not freezing my gems.
If you leave out the require in SmartContactsImporter this should work (config.gem "fastercsv" will do the require for you).
You can work around it when a require is needed in environment.rb with a:
begin
require "rack/cache"
rescue LoadError
STDERR.puts "not loaded rack/cache: #{$!}"
end
This is ugly but it does do the trick.
You shouldn't require inside your module, config.gem will require it for you.
There's also a related issue with config.gem where it will attempt to require a dependent gem that is not yet installed whilst installing the gems, but this doesn't appear to be the case yet.

Resources