Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

strange 'require' behavior in development environment

#4149

My model uses 'open-uri' to download images from remote locations.
In file app/models/asset.rb:

require 'open-uri'
class Asset < ActiveRecord::Base
...
 def some_method(uri)
  <uses open-uri here>
 end
...
end

It works fine in the production environment and in the development environment when using rails console.
But it throws the folloving exception when trying to download an image via web interface in development environment:

uninitialized constant OpenURI

For now, I made it work placing the require statement inside the class, like this:

class Asset < ActiveRecord::Base
 require 'open-uri'
 ...
 def some_method(uri)
  <uses open-uri here>
 end
...
end
but it looks strange, isn't it?

My configuration: edge Rails, Ruby 1.8.7, Ubuntu 9.10.

Reported by Valentine Bichkovsky · March 10th, 2010 @ 07:37 PM

State: committed
Milestone: 3.0.2
Assigned to: Yehuda Katz (wycats) Yehuda Katz (wycats)
Importance: High

Activity

  1. Maximilian Schulz
    Maximilian Schulz

    I have the exact same problem. And valentin's method of putting the require statement into the class definition actually helps. Seems very strange to me.

    April 19th, 2010 @ 12:05 PM

  2. kates
    kates

    I can't reproduce the problem. Requiring outside the class works for me in both production and development.

    ruby 1.8.7 (2010-01-10 patchlevel 249) [i686-linux]
    Rails 3.0.0.beta3

    April 21st, 2010 @ 11:12 AM

  3. jbermudes
    jbermudes
    • Tag changed from development environment, rails 3, require to rails3

    I also have this problem when using it in the application controller. Requiring it inside the application controller class seems to fix it for the first request, but subsequent requests cause a NameError(uninitialized constant OpenURI)

    ruby 1.9.2dev (2010-04-15 trunk 27346) [i686-linux]
    Rails 3.0.0.beta3

    April 27th, 2010 @ 06:44 AM

  4. Ganesh Shankar
    Ganesh Shankar

    Could not reproduce this error in Rails 2.3.5 (ruby 1.8.7 (2009-06-08 patchlevel 173) [universal-darwin10.0])

    We used the following in our attempt to reproduce: (app/models/person.rb)

    require 'open-uri'
    
    class Person < ActiveRecord::Base
      def foo
        foo = open('http://google.com')
      end
    end
    

    April 27th, 2010 @ 11:18 AM

  5. Josh Sharpe
    Josh Sharpe

    I can confirm this is still happening here:

    $ rails --version Rails 3.0.0.beta3
    $ ruby --version ruby 1.9.2dev (2010-04-28 trunk 27525) [x86_64-darwin10.3.0]

    My require statement is in a module defined in lib/foo.rb -- so it doesn't necessarily have to be in a controller or AR class.

    However, the error is only generated when making a request to a controller that eventually hits the Module on the second attempt. The first attempt works fine, as do other routes that don't use the Module.

    This issue occurs while running in development -- it does not occur while running in production

    April 28th, 2010 @ 04:42 PM

  6. Josh Sharpe
    Josh Sharpe

    requiring open-uri at the top of environment.rb and removing it from all of my Modules 'fixes' this -- although it's definitely the wrong solution.

    April 28th, 2010 @ 05:54 PM

  7. Neeraj Singh
    Neeraj Singh

    I am not able to recreate this problem with rails3 beta3. This is what I did.

    rvm use ruby-1.8.7
    rails g scaffold User name:string
    rake db:migrate
    
    # add following line at the top of app/models/user.rb
    require 'open-uri'
    
    rails s
    

    I refreshed the page a number of times. All seems fine.

    Some more info about my environment.

    server booted with WEBrick
    
    $ ruby -v
    ruby 1.8.7 (2010-01-10 patchlevel 249) [i686-darwin10.3.0]
    
    $ rails -v
    Rails 3.0.0.beta3
    

    April 28th, 2010 @ 06:18 PM

  8. Valentine Bichkovsky
    Valentine Bichkovsky

    Neeraj Singh, it is not the 'require' statement, that causes an error. Try to actually use open-uri in your code, like opening some URL in some of your model's methods, and that method should be called from the controller when you refresh the page.

    About the second attempt - I was also getting this error on the second attempt.

    I think, it is connected with class reloading in development mode. Everything is loaded as it has on the first attempt, but then, on the second attempt, when class is reloaded, something is not working correctly. It also explains why the error occurs in development mode only.

    April 29th, 2010 @ 11:36 AM

  9. Neeraj Singh
    Neeraj Singh
    • Tag changed from rails3 to activesupport, dependencies, rails3

    I spent some time today looking into this issue. Here are my thoughts.

    First this is how you can reproduce the problem.

    require 'open-uri'
    class UsersController < ApplicationController
      def index
        open("http://www.ruby-lang.org/") {|f| }
        render :text => 'hello'
      end
    end
    

    Everything will work fine in production mode.

    In development mode start the server and visit http://localhost:3000/users . First time things will look fine. Now refresh the page and you will see uninitialized constant OpenURI error.

    active_spport/dependencies.rb has following code.

    def load_file(...)
    ...
    newly_defined_paths = new_constants_in(*parent_paths) do
      result = Kernel.load path
    end
    autoloaded_constants.concat newly_defined_paths unless load_once_path?(path)
    ...
    end
    

    Above mentioned piece of code finds all the constants defined in users_controller and adds those constants to autoloaded_constants. At the end of the request all the items from autloaded_constants are removed. It means OpenURI is removed from the constant.

    However this strategy has one issue.

    First look at this discussion to see how in some cases the constants which are removed using remove_const are not restored using require.

    Exactly the same thing is happening here. In the case I illustrated above OpenURI is getting removed using remove_const method. However require 'open-uri' returns false the second time when page is refreshed. This is precisely because of the reason mentioned in this discussion .

    The main point is that removing a constant using remove_const does not necessarily removes the constant from $LOADED_FEATURES which is what require checks to see if constant needs to be loaded or not.

    May 12th, 2010 @ 11:05 PM

  10. Matt Jones
    Matt Jones

    There are (AFAIK) two options to make this behave better:

    • require open-uri in an initializer which will keep the remove_const bogeyman away

    • use require_dependency instead of require, which will reload open-uri when the controller is reloaded

    May 13th, 2010 @ 01:25 AM

  11. Michael Koziarski
    Michael Koziarski
    • State changed from new to wontfix

    You could investigate making dependencies.rb magically solve this but I'm guessing it's a tonne more work than it's worth. That code is pretty robust and does what it does very well, it's just that it doesn't do everything people have dreamed up :).

    Moving the require of open-uri into your action would work though that obviously has its own set of problems. Alternatively you could put your controllers into load_once_paths but that's probably worse.

    All in all the two options matt mentions are the simplest way to avoid the problems you're encountering here, and are easy to reason about.

    May 13th, 2010 @ 10:28 PM

  12. José Valim
    José Valim
    • Milestone cleared.
    • State changed from wontfix to open
    • Assigned user set to Yehuda Katz (wycats)
    • Importance changed from to High

    An example app reproducing this bug:

    http://github.com/paulca/uninitialized_constant_example

    August 12th, 2010 @ 02:55 PM

  13. Zachary Scott
    Zachary Scott

    I can confirm this from the example app (rails 3.0.0.rc) in 1.9.2-rc2 and 1.8.7 ree.
    All tests run fine, but development server breaks.

    August 16th, 2010 @ 09:05 AM

  14. Santiago Pastorino
  15. Jeremy Kemper
  16. Jeff Kreeftmeijer
    Jeff Kreeftmeijer
    • Tag cleared.

    Automatic cleanup of spam.

    November 8th, 2010 @ 08:52 AM