2016-06-21 5 views
0

Ich versuche, den Geocoder mit einem DataMapper-Modell in einer Sinatra-Anwendung zu verwenden.Geocoder mit Sinatra und DataMapper verwenden

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 

Wenn ich versuche, einen IRB-Sitzung zu starten, wird eine Ausnahme generiert:

irb> require './environment' 
NameError: uninitialized constant Geocoder::Model 
... 

Was bin ich nicht zu verstehen?

Antwort

0

Zunächst sieht es so aus, als ob der Geocode-Edelstein keine direkte Unterstützung für Datamapper, as per this issue, hätte.

Zweitens, wenn Sie ein Modul in eine Klasse aufnehmen, sind die Methoden für die Instanz der Klasse verfügbar und nicht auf Klassenebene. Zum Beispiel:

module Name 
    def name 
    puts "Module" 
    end 
end 

class SomeClass 
    include Name 
end 

SomeClass.new.name # => "Module" 

Dies funktioniert, weil, wenn Sie include ein Modul, das Modul an die Vorläuferkette dieser Klasse hinzugefügt wird. Alle Methoden, die an die Instanz gesendet werden und nicht auf der Instanz verfügbar sind, werden an die Vorfahren weitergeleitet. Allerdings ist es eine andere Methode extend genannt, die die Methoden in einer Klasse-Ebene hinzufügt, anstatt auf Instanzebene:

# module definition same as before 

class SomeClass 
    extend Name 

    name # works! 
end 

Inorder Klasse-Level-Aufnahme zu bekommen, gibt eine andere Art und Weise (was ist das, was die Geocoder gem uses for supported models:

# module code same as before 

module Name 
    def name 
    puts "Module" 
    end 

    def self.included(klass) 
    klass.extend(self) 
    end 
end 

der included Haken für die Modelle zur Verfügung gestellt wird, die außer Kraft gesetzt werden kann, etwas zu tun, wenn der include Name Schritt ausführt. Da gibt es keinen Datamapper spezifisches Modul, das diesen Schritt nicht ausgeführt wird, sehen Sie, dass Fehler.

+0

@craig Danke für die Bearbeitung! – Kashyap