13

I can't get geocoder to work correct as my local ip address is 127.0.0.1 so it can't located where I am correctly.

The request.location.ip shows "127.0.0.1"

How can I use a different ip address (my internet connection ip) so it will bring break more relevant data?

Blankman
  • 259,732
  • 324
  • 769
  • 1,199

6 Answers6

21

A nice clean way to do it is using MiddleWare. Add this class to your lib directory:

# lib/spoof_ip.rb

class SpoofIp
  def initialize(app, ip)
    @app = app
    @ip = ip
  end

  def call(env)
    env['HTTP_X_FORWARDED_FOR'] = nil
    env['REMOTE_ADDR'] = env['action_dispatch.remote_ip'] = @ip
    @status, @headers, @response = @app.call(env)
    [@status, @headers, @response]
  end
end

Then find an IP address you want to use for your development environment and add this to your development.rb file:

config.middleware.use('SpoofIp', '64.71.24.19')
Sean Rucker
  • 1,066
  • 2
  • 11
  • 20
  • 1
    probably a noob point, but you would have to add something in eg config/application.rb to auto load that class, eg: config.autoload_paths += Dir["#{config.root}/lib/**/"] – Will Jan 02 '13 at 00:51
  • I tried this method ages ago was worked amazingly. Tried it again recently on another app didnt work. About 2 hours later i tried downgrading the version of geocoder... and it worked! Version of geocoder i did it with originally was `1.1.2` version i installed today was `1.1.6` so something must have changed within these versions – DickieBoy Jan 17 '13 at 12:56
  • 6
    @DickieBoy, you're right, that method doesn't work with Geocoder 1.1.6 due to the following [change](https://github.com/alexreisner/geocoder/commit/f67defd8d2b25511023be21c318aef42562058b2). The solution makes env['HTTP_X_FORWARDED_FOR'] = nil, but it doesn't delete the key from the hash so it gets selected by the `location` method and a search for nil is performed by geocoder. Commenting that line works in my case. – deivid Feb 18 '13 at 15:13
  • FWIW I can confirm @deivid's above fix for Rails 4.0.0 using the Geocoder 1.1.8 gem. Following @Ruckstar's answer and commenting out the line `env['HTTP_X_FORWARDED_FOR'] = nil` does the trick. – Jason Gilmore Sep 13 '13 at 02:56
  • It doesn't work for me, with or without commenting out the Jason line, I meet the following error : `.rvm/gems/ruby-2.0.0-p247/gems/activesupport-4.0.0.rc1/lib/active_support/inflector/methods.rb:226:in 'const_get': uninitialized constant SpoofIp (NameError)` – Flo Rahl Sep 16 '13 at 08:11
  • This works in rails 4, either add the autoload path for lib or move it into the initializer directory. – Igrabes Aug 26 '16 at 04:53
  • If you're running into issues try reloading spring (if you're using it). That fixed it for me – Mini John Aug 12 '20 at 17:56
5

For this I usually use params[:ip] or something in development. That allows me to test other ip addresses for functionality and pretend I'm anywhere in the world.

For example

class ApplicationController < ActionController::Base
  def request_ip
    if Rails.env.development? && params[:ip]
      params[:ip]
    else
      request.remote_ip
    end 
  end
end
jesse reiss
  • 4,509
  • 1
  • 20
  • 19
  • I'm unfamiliar with "geocoder" which I assume is a gem or something, but I imagine there's some way to configure it. I use GeoIP for geocoding : http://geoip.rubyforge.org/ and that's easy enough to work with using this method. – jesse reiss May 24 '11 at 20:41
  • You're in a development environment, so there's no way to use the real requests ip address. You need to find someway to tell "geocoder" that in development it should use another value. – jesse reiss May 24 '11 at 20:42
4

I implemented this slightly different, and this works well for my case.

In application_controller.rb i have a lookup method which calls the Geocoder IP lookup directly passing in the results of request.remote_ip.

def lookup_ip_location
  if Rails.env.development?
    Geocoder.search(request.remote_ip).first
  else
    request.location
  end
end

Then in config/environments/development.rb i monkey-patched the remote_ip call:

class ActionDispatch::Request
  def remote_ip
    "71.212.123.5" # ipd home (Denver,CO or Renton,WA)                                                                                                                                                                                                                                                                        
    # "208.87.35.103" # websiteuk.com -- Nassau, Bahamas                                                                                                                                                                                                                                                                      
    # "50.78.167.161" # HOL Seattle, WA                                                                                                                                                                                                                                                                                       
  end
end

I just hard code some addresses, but you could do whatever you'd like here.

ipd
  • 5,674
  • 3
  • 34
  • 49
  • I found that to get `request.location` to work properly I had to modify this answer to rename the `lookup_ip_location` method to just `location` and place it within that `ActionDispatch::Request` class. – fabsays Sep 30 '15 at 11:39
1

This is an updated answer for geocoder 1.2.9 to provide a hardcoded IP for development and test environments. Just place this at the bottom of your config/initilizers/geocoder.rb:

if %w(development test).include? Rails.env
  module Geocoder
    module Request
      def geocoder_spoofable_ip_with_localhost_override
        ip_candidate = geocoder_spoofable_ip_without_localhost_override
        if ip_candidate == '127.0.0.1'
          '1.2.3.4'
        else
          ip_candidate
        end
      end
      alias_method_chain :geocoder_spoofable_ip, :localhost_override
    end
  end
end
kross
  • 3,627
  • 2
  • 32
  • 60
1

I had the same question. Here is how I implemented with geocoder.

#gemfile
gem 'httparty', :require => 'httparty', :group => :development 

#application_controller
def request_ip
  if Rails.env.development? 
     response = HTTParty.get('http://api.hostip.info/get_html.php')
     ip = response.split("\n")
     ip.last.gsub /IP:\s+/, ''      
   else
     request.remote_ip
   end 
end

#controller
ip = request_ip
response = Geocoder.search(ip)

( code part with hostip.info from geo_magic gem, and based on the other answer to this question. )

now you can do something like response.first.state

BlissOfBeing
  • 625
  • 1
  • 6
  • 11
-1

you may also do this

request.safe_location
Asnad Atta
  • 3,855
  • 1
  • 32
  • 49