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

Provide more helpful error message when _type field doesn't correspond to a Class name

    • Type: Icon: Improvement Improvement
    • Resolution: Done
    • Priority: Icon: Minor - P4 Minor - P4
    • 7.0.0
    • Affects Version/s: 6.0.0
    • Component/s: None
    • Labels:
      None
    • Environment:
      - Ruby (2.3.1)
      - Rails (5.0.0)
      - mongoid (6.0.0)

      What
      Part of my project requires reading mongodb collections written by another piece of software. Trying to work with this document caused an undescriptive error to be raised from `ActiveSupport::Inflections`. Digging a bit further in the source code I realized that it had to do with the document loading. This other piece of software is using the `_type` field which is reserved by mongoid. It was trying to convert "http://..." into a constant which raises `NameError: wrong constant name`.

      Offending lines
      https://github.com/mongodb/mongoid/blob/master/lib/mongoid/factory.rb#L23
      https://github.com/mongodb/mongoid/blob/master/lib/mongoid/factory.rb#L46

      Confirmed with monkey-patch

      Very specific to my problem, this ignores types matching http://.

      module Mongoid
        module Factory
          extend self
          def from_db(klass, attributes = nil, selected_fields = nil)
            type = (attributes || {})[TYPE]
            if type.blank? || type =~ /http:\/\//
              klass.instantiate(attributes, selected_fields)
            else
              type.camelize.constantize.instantiate(attributes, selected_fields)
            end
          end
        end
      end
      

      Idea

      • Show a more descriptive error message. If you happen to misspell the class name with some funky characters you would end up with this error.
      • Optional: allow `global` configuration of the `type` field.
      • Optional: allow `document` configuration of the `type` field.

      Document causing this error

      {
          "_id" : "richtext",
          "ops" : [
              {
                  "insert" : "Hi!"
              }
          ],
          "_type" : "http://sharejs.org/types/rich-text/v1",
          "_v" : 1,
          "_m" : {
              "ctime" : 1476286743185.0,
              "mtime" : 1476286743185.0
          },
          "_o" : ObjectId("57fe591743247f0011b3e04d")
      }
      

      Error:

      Running via Spring preloader in process 16
      Loading development environment (Rails 5.0.0)
      irb(main):001:0> RealtimePage.first
      Overwriting existing field _id in class RealtimePage.
      MONGODB | Adding mongo:27017 to the cluster.
      MONGODB | mongo:27017 | furrow_development.find | STARTED | {"find"=>"realtime_pages", "filter"=>{}, "sort"=>{"_id"=>1}, "limit"=>1, "singleBatch"=>true}
      MONGODB | mongo:27017 | furrow_development.find | SUCCEEDED | 0.000988278s
      NameError: wrong constant name
          from /bundler-cache/gems/activesupport-5.0.0/lib/active_support/inflector/methods.rb:270:in `const_get'
          from /bundler-cache/gems/activesupport-5.0.0/lib/active_support/inflector/methods.rb:270:in `block in constantize'
          from /bundler-cache/gems/activesupport-5.0.0/lib/active_support/inflector/methods.rb:266:in `each'
          from /bundler-cache/gems/activesupport-5.0.0/lib/active_support/inflector/methods.rb:266:in `inject'
          from /bundler-cache/gems/activesupport-5.0.0/lib/active_support/inflector/methods.rb:266:in `constantize'
          from /bundler-cache/gems/activesupport-5.0.0/lib/active_support/core_ext/string/inflections.rb:66:in `constantize'
          from /bundler-cache/gems/mongoid-6.0.0/lib/mongoid/factory.rb:46:in `from_db'
          from /bundler-cache/gems/mongoid-6.0.0/lib/mongoid/relations/eager.rb:16:in `with_eager_loading'
          from /bundler-cache/gems/mongoid-6.0.0/lib/mongoid/contextual/mongo.rb:248:in `block in first'
          from /bundler-cache/gems/mongoid-6.0.0/lib/mongoid/contextual/mongo.rb:501:in `try_cache'
          from /bundler-cache/gems/mongoid-6.0.0/lib/mongoid/contextual/mongo.rb:246:in `first'
          from /bundler-cache/gems/mongoid-6.0.0/lib/mongoid/contextual.rb:20:in `first'
          from /bundler-cache/gems/mongoid-6.0.0/lib/mongoid/findable.rb:148:in `first'
          from (irb):1
          from /bundler-cache/gems/railties-5.0.0/lib/rails/commands/console.rb:65:in `start'
          from /bundler-cache/gems/railties-5.0.0/lib/rails/commands/console_helper.rb:9:in `start'
      ... 8 levels...
          from /bundler-cache/gems/activesupport-5.0.0/lib/active_support/dependencies.rb:287:in `load'
          from /bundler-cache/gems/activesupport-5.0.0/lib/active_support/dependencies.rb:287:in `block in load'
          from /bundler-cache/gems/activesupport-5.0.0/lib/active_support/dependencies.rb:259:in `load_dependency'
          from /bundler-cache/gems/activesupport-5.0.0/lib/active_support/dependencies.rb:287:in `load'
          from /bundler-cache/gems/spring-1.7.2/lib/spring/commands/rails.rb:6:in `call'
          from /bundler-cache/gems/spring-1.7.2/lib/spring/command_wrapper.rb:38:in `call'
          from /bundler-cache/gems/spring-1.7.2/lib/spring/application.rb:191:in `block in serve'
          from /bundler-cache/gems/spring-1.7.2/lib/spring/application.rb:161:in `fork'
          from /bundler-cache/gems/spring-1.7.2/lib/spring/application.rb:161:in `serve'
          from /bundler-cache/gems/spring-1.7.2/lib/spring/application.rb:131:in `block in run'
          from /bundler-cache/gems/spring-1.7.2/lib/spring/application.rb:125:in `loop'
          from /bundler-cache/gems/spring-1.7.2/lib/spring/application.rb:125:in `run'
          from /bundler-cache/gems/spring-1.7.2/lib/spring/application/boot.rb:19:in `<top (required)>'
          from /usr/local/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
          from /usr/local/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
          from -e:1:in `<main>'
      irb(main):002:0>
      

            Assignee:
            emily.stolfo Emily Stolfo
            Reporter:
            digitalkookie Martin Samami
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: