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
    • None
    • Environment:
      - Ruby (2.3.1)
      - Rails (5.0.0)
      - mongoid (6.0.0)
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      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 (Inactive)
            Reporter:
            digitalkookie Martin Samami
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved:
              None
              None
              None
              None