Uploaded image for project: 'Mongoid'
  1. Mongoid
  2. MONGOID-5343

Resolve association target class names to classes during association processing, use classes instead of names in all subsequent operations

    • Type: Icon: Epic Epic
    • Resolution: Unresolved
    • Priority: Icon: Critical - P2 Critical - P2
    • None
    • Affects Version/s: None
    • Component/s: Associations
    • None
    • To Do
    • Resolve association class names
    • 0
    • 0
    • 0
    • 100

      When an application declares an association, Mongoid must figure out the class of its target. The class may be specified explicitly by the user via the class_name option or it may be unspecified, in which case Mongoid figures it out based on the association name.

      Note that what Mongoid needs is the actual class, but what a user specifies, and what Mongoid starts with in the absense of user specification, is the class name. The name may be ambiguous when submodules are involved. For example, in the following definition:

      module Foo
        class Bar
          include Mongoid::Document
      
          has_many :things
        end
      end
      

      ... the things association could refer to the top-level ::Thing or to the Foo::Thing nested under Foo.

      An additional complication is that in a Rails application, models are usually autoloaded, meaning in roughly 50% of the cases when the above code executes neither ::Thing nor Foo::Thing have been defined and, importantly, attempting to check whether either is defined could trigger the autoloading of both.

      In turn, autoloading comes with its own issue which is described in https://jira.mongodb.org/browse/MONGOID-4750: when a file is being loaded, if the code inside it raises an exception during the loading process, the file would still be considered loaded but only some of the code in it would have been evaluated. Subsequently the exception could be hidden/replaced by a LoadError, thus the original cause of the problem would be lost or, worse, partially loaded code would exist in application with no indication that this happened.

      AR currently behaves as follows:

      • When it encounters an association definition, it tries to obtain the class of the target.
      • This may trigger autoloading.
      • In turn, this may silently cause the application code to be partially loaded.

      Mongoid currently behaves as follows:

      The current Mongoid behavior is making it difficult to work with since the natural and correct thing to do is to compare classes when figuring out association targets but Mongoid has the self-imposed prohibition on such comparisons due to not having the classes available during association processing.

      Proposed changes in this epic are:

      Resolve class names to classes during association processing (i.e. when the association declaration like has_many is being evaluated).
      Perform this resolution in the same way Ruby does (look up in the same module first then go up modules to top level)
      Add test coverage for class name resolution matching Ruby semantics for embedded and referenced associations, specifically that bare names are looked up in modules first and then on top level

      This leaves the issue of partial application code loading. We could recommend a linter task/code snippet to users in our documentation which would load each of their models individually, which would provide diagnostics for when one of the models is broken and unloadable.

            Assignee:
            Unassigned Unassigned
            Reporter:
            neil.shweky@mongodb.com Neil Shweky (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: