sabaeus sabaeus - 3 months ago 13
Ruby Question

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.

Cam Cam
Answer

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"