2

According to the ruby geocoder documentation (rubygeocoder.com), it's possible to use the geocoder gem with a Sinatra app, but I'm running into issues getting it to work and haven't been able to find any working examples or related stackoverflow issues either. I think the problem is due to the fact that it's a Sinatra app and not a full rails app.

My Gemfile:

source "https://rubygems.org"
ruby '2.1.2'
gem 'dotenv', '~> 0.10.0'
gem 'pg', '~> 0.17.1'
gem 'rack-flash3'
gem "sinatra"
gem "activerecord"
gem "sinatra-activerecord"
gem "geocoder"
gem 'omniauth'
gem 'omniauth-google-oauth2'
gem "sqlite3"
gem "shotgun"

The model (which has float latitude and longitude columns) that I want to search by:

class Item < ActiveRecord::Base  
 extend Geocoder::Model::ActiveRecord

  attr_accessor :latitude, :longitude
  belongs_to :profile
  has_and_belongs_to_many :categories
  has_many :reports, dependent: :destroy
}

Here's the app.rb code with the '/' route:

class FL < Sinatra::Base
  get '/' do
    @items = Item.near('Detroit, MI, US')
    puts "ITEMS ARE:"
    pp @items
    erb :index
  end
  ...
end

Here's the relevant app.rb contents:

require 'rubygems'
require 'sinatra/base'
require 'sinatra/flash'
require 'sinatra/activerecord'
require 'geocoder'
require 'omniauth'
require 'sinatra/flash'
require 'json'
require 'pp'
require 'rack-flash'
require './models/model_init'
require './helpers/helper'
require './auth'
require './admin'
require './api'

class FL < Sinatra::Base

  set :root, File.dirname(__FILE__)

  enable :logging
  enable :sessions
  #set :logging, true

  register Sinatra::ActiveRecordExtension
  register Sinatra::Flash

  set :show_exceptions, true if ENV['RACK_ENV'] == 'development'

  use Rack::Session::Cookie, :secret => ENV['RACK_COOKIE_SECRET']

end

Finally, here is the error i receive:

NoMethodError - undefined method `near' for #<Class:0x0000010750d0b8>:
/Users/bob/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.0/lib/active_record/dynamic_matchers.rb:26:in `method_missing'
/Users/bob/rails_projects/fl2/api.rb:21:in `block in <class:FL>'
/Users/bob/.rvm/gems/ruby-2.1.2/gems/sinatra-1.4.5/lib/sinatra/base.rb:1603:in `call'
/Users/bob/.rvm/gems/ruby-2.1.2/gems/sinatra-1.4.5/lib/sinatra/base.rb:1603:in `block in compile!'
/Users/bob/.rvm/gems/ruby-2.1.2/gems/sinatra-1.4.5/lib/sinatra/base.rb:966:in `[]'
/Users/bob/.rvm/gems/ruby-2.1.2/gems/sinatra-1.4.5/lib/sinatra/base.rb:966:in `block (3 levels) in route!'

Looking at the stacktrace, it looks like its not finding the geocoder package for some reason. I'm not sure if if it's a simple configuration that I'm missing, or if what I'm attempting isn't possible without some gem customization (something beyond my understanding at this point). Any insight, suggestions to try, or examples would be much appreciated. thanks!

Adding my config.ru:

config.ru

require 'bundler/setup'
Bundler.require(:default)

use Bundler.setup(:default)  #added this by suggestion

require 'logger'
use Rack::Deflater

Dotenv.load

require "./fl_app"
run FL
  • Actually, I've been able to confirm that its loading geocoder ok, because the following line is able to run and produce output: @location = Geocoder::Calculations.extract_coordinates([42.44, -83.33]), it's just not loading (or for some other reason is not able to access) the methods related to the Models. – pontiac_ventura May 22 '14 at 17:02
  • Are you able to load the `Item` class in a console or spec separately from Sinatra? – ian May 22 '14 at 22:20
  • I'm not sure of how to load it separately from Sinatra. Should I be able to? I'm not able to use the rails console, since it's not a rails app. I can load it in the irb console however, with the following: 1. require 'sinatra/activerecord' 2. load './models/item.rb'. From there I can instantiate new Items with Item.new. I'm not sure if that answers your question. – pontiac_ventura May 24 '14 at 13:37
  • It sounds like you've done it correctly. The database access code and the code that runs Sinatra should be able to run separately (to a certain degree). If you were able to run it that way then it suggests something is wrong in the Sinatra set up code. I would move the `require 'geocoder'` into the model files (always keep the requires where they are needed). Also, I'd sandbox this using Bundler. Use `bundle install --binstubs --path vendor`, use `Bundler.setup(:default)` and then start the app using `bundle exec whatever-command-you-use-to-start-it` and see if that makes a difference. – ian May 25 '14 at 14:01
  • Thanks for responding. I tried as suggested, requiring geocoder in model files, and sandboxing, adding Bundler.setup(:default) to my config.ru (see above). I started the server several ways ('bundle exec shotgun config.ru', 'rack -p 4567'), but with no luck. WHat you say sounds correct regarding it being a problem with how Sinatra is configured. I'm trying to use modular style, but I find all the variations on how to configure and run Sinatra apps confusing. I think I need to read up some more on configurations and learn more on how these ruby frameworks work together. – pontiac_ventura May 25 '14 at 15:13
  • Are you able to share the code as a whole? – ian May 25 '14 at 16:13
  • 1
    @iain I created a public github repo here: github.com/jockeyfullofbourbon/fl – pontiac_ventura May 27 '14 at 20:40

1 Answers1

0

I found a solution to this issue, but can't explain why it works. I had to add the line:

  reverse_geocoded_by :latitude, :longitude

to my Item model. Once I added that line I was able to use geocoder's 'near' method.

Even though I'm not actually doing any geocoding (converting lat/long to addresses, or vice versa), it still appears to be necessary for the library to work correctly. Thanks @iain for all your helpful advice.