Search code examples
rubymongoidmonkeypatching

Monkey Patching Mongoid models contained in a Ruby gem


I have a Ruby gem which gets used across multiple projects that contains some Mongoid models.

I'm currently trying to reuse them in a project and monkey patch some extra methods. However, when I require the project and run the tests. I get a NoMethodError. Any ideas where I'm going wrong?

Here's my main project file:

require 'bundler'
Bundler.require(:default)

require 'mongoid-elasticsearch'
Mongoid::Elasticsearch.prefix = ENV["MONGOID_ENVIRONMENT"]

require 'mongoid_address_models/require_all' # This is where I include my gem

Mongoid.load!(File.join(File.dirname(__FILE__), "..", "config", "mongoid.yml"), ENV["MONGOID_ENVIRONMENT"] || :development)

# Here are my monkey patched models
require 'models/street'
require 'models/locality'
require 'models/town'
require 'models/postcode'

require 'sorting_office/address'

module SortingOffice
end

And this is an example of one of the monkey patched models

class Postcode

  REGEX = /([A-PR-UWYZ01][A-Z01]?[0-9IO][0-9A-HJKMNPR-YIO]\s?[0-9IO][ABD-HJLNPQ-Z10]{2})/i

  def self.calculate(address)
    postcode = UKPostcode.new(address.match(REGEX)[0])
    where(name: postcode.norm).first
  end

end

When I call Postcode.calculate(address) (for example), I get a NoMethodError


Solution

  • I think I've nailed this now. Rather than putting the monkey patch inside lib/models, I moved them to lib/sorting_office/models and required them like so:

    require 'sorting_office/models/street'
    require 'sorting_office/models/locality'
    require 'sorting_office/models/town'
    require 'sorting_office/models/postcode'
    

    I'd still be interested to know WHY this worked though