I'm attempting to use the Geocoder gem with a DataMapper model in a Sinatra application.
environment.rb:
require 'rubygems'
require 'bundler/setup'
require 'dm-core'
require 'dm-timestamps'
require 'dm-validations'
require 'dm-aggregates'
require 'dm-migrations'
require 'dm-types'
require 'geocoder'
require 'sinatra' unless defined?(Sinatra)
# load models
$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/lib")
Dir.glob("#{File.dirname(__FILE__)}/lib/*.rb") { |lib| require File.basename(lib, '.*') }
DataMapper.setup(:default, (ENV["DATABASE_URL"] || "sqlite3:///#{File.expand_path(File.dirname(__FILE__))}/#{Sinatra::Base.environment}.db"))
DataMapper.finalize
DataMapper.auto_upgrade!
lib/location.rb:
class Location
include DataMapper::Resource
include Geocoder::Model::Base
property :id, Serial
property :address, String, :required => true
# geocoder gem
geocoded_by :address, :latitude => :lat, :longitude => :lng
# geocoder
after_validation :geocode, :if => :address_changed?
end
When I attempt to start an IRB session, an exception is generated:
irb> require './environment'
NameError: uninitialized constant Geocoder::Model
...
What am I not understanding?
First up, it looks like the Geocode gem won't have direct support for Datamapper, as per this issue.
Second, when you include a module inside a class, the methods are available to the instance of the class, and not at the class level. For example:
This works because when you
includea module, that module gets added to the ancestor chain of that class. Any methods that get sent to the instance which are not available on the instance are forwarded to the ancestors. However, there's another method calledextendwhich adds the methods at a class-level rather than at instance level:Inorder to get class-level inclusion, there is another way (which is what the Geocoder gem uses for supported models:
The
includedhook is provided for models which can be overridden to do something when theinclude Namestep executes. Since there's no Datamapper specific module that is not executing this step, you see that error.