On Fri, Feb 21, 2014 at 5:18 PM, Gary Weaver <[email protected]> wrote:
1. Classes couldn't load in the first place if there was no way to load > them because of interdependency problems. Rails initially autoloads these > files without problems. > By now the error has been reported in development mode. In development mode Rails does not eager load models. But in any case, in general, this depends ultimately on the code being loaded in the runtime environment which without more information could have conditional code or anything possible in Ruby. Without a way to reproduce we cannot move forward in understanding what happens in that application. 2. I would think that you shouldn't get an infinite loop in this case if > you keep track of what needs to be loaded, and because of that, it is aware > that there is a circular reference I assume by checking that without > letting a SystemStackError occur before you find that out. > dependencies.rb keeps track of files loaded to autoload constants indeed, that's what allows Active Support to raise that particular error. That way it can avoid the infinite loop (infine nested calls to const_missing that never return to be specific), fail fast, and give a meaningful message. A. Keep that list of things to load. > B. Try to load them in as sane an order as possible based on dependencies > that are known. > The dependencies in a given file cannot be known a priori. You need to execute and let const_missing be triggered as needed. > C. For things with circular dependency, put those in a bucket of unknown > order (hopefully there aren't too many) and use the "try and try again" > approach iterating through things that need to be loaded, only stopping > when you cannot load anything else in the list to be loaded in that > iteration. > That optimistic apprach is used for *unloading* constants. dependencies.rb keeps track of the constants that were autoloaded in a flat collection (autoloaded_constants). Then it iterates over the collection to remove them without a topological sort or anything fancy. If the constant to be removed was already removed fine, move along. But you cannot do eager loading as an alternative to const_missing. First, eager loading does not solve the problem I wrote above with a.rb and b.rb, that circularity is fundamental. Second, even without circularities it would be too costly in development mode. In production mode is considered to be worthwhile mainly for thread-safety and to leverage copy on write. Third, const_missing is triggered when you eager load files. In production mode dependencies.rb still plays its role by autoloading constants, because when a file is interpreted, even if it is being eager loaded by Rails, constants not yet loaded can be present at file or class level (say). Finally, you cannot evaluate a file, and if something errs mark it for a second try, because the error condition (or missing constant) could be at any point in said file and that would generally imply executing code twice: the code that runs fine until you reach the problematic spot. Evaluating code twice is not acceptable, you cannot do that. Anyway, let's see if you guys can track it down and we are able to discern if there's something to improve in dependencies.rb or the application should do something in a different way. The error message includes which is the problematic constant name. That's the key data to start debugging. When dealing with constant autoloading it is very important to remember that dependencies.rb does NOT emulate Ruby algorithms for constant name resolution (that's just not possible with const_missing). dependencies.rb has rather its own rules inspired by those algorithms. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/rubyonrails-core. For more options, visit https://groups.google.com/groups/opt_out.
