This project is archived and is in readonly mode.

#4149 ✓committed
Valentine Bichkovsky

strange 'require' behavior in development environment

Reported by Valentine Bichkovsky | March 10th, 2010 @ 07:37 PM | in 3.0.2

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.

Comments and changes to this ticket

  • Maximilian Schulz

    Maximilian Schulz April 19th, 2010 @ 12:05 PM

    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.

  • kates

    kates April 21st, 2010 @ 11:12 AM

    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

  • jbermudes

    jbermudes April 27th, 2010 @ 06:44 AM

    • 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

  • Ganesh Shankar

    Ganesh Shankar April 27th, 2010 @ 11:18 AM

    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
    
  • Josh Sharpe

    Josh Sharpe April 28th, 2010 @ 04:42 PM

    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

  • Josh Sharpe

    Josh Sharpe April 28th, 2010 @ 05:54 PM

    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.

  • Neeraj Singh

    Neeraj Singh April 28th, 2010 @ 06:18 PM

    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
    
  • Valentine Bichkovsky

    Valentine Bichkovsky April 29th, 2010 @ 11:36 AM

    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.

  • Neeraj Singh

    Neeraj Singh May 12th, 2010 @ 11:05 PM

    • 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.

  • Matt Jones

    Matt Jones May 13th, 2010 @ 01:25 AM

    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

  • Michael Koziarski

    Michael Koziarski May 13th, 2010 @ 10:28 PM

    • 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.

  • José Valim

    José Valim August 12th, 2010 @ 02:55 PM

    • 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

  • Zachary Scott

    Zachary Scott August 16th, 2010 @ 09:05 AM

    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.

  • Santiago Pastorino
  • Jeremy Kemper

    Jeremy Kemper October 15th, 2010 @ 11:01 PM

    • Milestone set to 3.0.2
  • Jeff Kreeftmeijer

    Jeff Kreeftmeijer November 8th, 2010 @ 08:52 AM

    • Tag cleared.

    Automatic cleanup of spam.

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Pages