Search code examples
rubysinatrarackrails-geocoder

how to get ip address using rack and geocoder


I want to get the location of an IP address with geocoder. The docs say to use the following line:

result = request.location

But that gives a NameError and says "request" is undefined. So I figured I needed a Rack::Request object:

result = Rack::Request.new(env)

But that toos gives a NameError - this time saying that env is undefined.

So I checked for env in a new script with the following:

require "rack" 
def pp(hash)
 hash.map {|key,value| "#{key} => #{value}"}.sort.join("<br/>") 
end
Rack::Handler::WEBrick.run lambda {|env| [200,{},[pp(env)]]} , :Port=>3000

When I run that and go to localhost:3000 I see the env hash. Is env not set by default in Rack?

I cannot figure this out, and I know it's because I'm missing something.


Solution

  • Fixing your Geocoder setup

    The code you're following from the docs assumes you will be hosting the snippet from "within a rails controller or Sinatra app." To get it working with Sinatra is fairly straightforward. Populate the following two files from your project directory:

    # Gemfile
    source 'https://rubygems.org'
    
    gem 'sinatra'
    gem 'geocoder'
    
    #######################
    
    # main.rb
    require 'sinatra'
    require 'geocoder'
    
    get '/' do
      <<-HTMLOUT
      <html>
      <body>
      <p><strong>Request Location</strong>: #{request.location.inspect}</p>
      </body>
      </html>
    HTMLOUT
    end
    

    Then from your terminal run bundle install and start up the app ruby main.rb -p 4567. Go to http://localhost:4567 to check. Because it's localhost, none of the geocode data will be populated... but that should get you started.


    Regarding the undefined error

    You should be able to find Rack's environment variable within ENV['RACK_ENV']. Try adding this snippet to your code:

    env = ENV["RACK_ENV"] || "development"
    

    Ruby shorthand default assignment

    This Ruby shorthand assignment technique is useful for assigning a default value if our config has not been set. For example:

    # pretend FAKE_ENV is your ENV  
    FAKE_ENV = {"DEFINED_KEY" => "defined_value"}
    env = FAKE_ENV["DEFINED_KEY"] || "my_default"
    # => "defined_value
    env = FAKE_ENV["UNDEFINED_KEY"] || "my_default"
    # => "my_default"