18

Just asked how to check if an internet connection exists using javascript and got some great answers. What's the easiest way to do this in Ruby? In trying to make generated html markup code as clean as possible, I'd like to conditionally render the script tag for javascript files depending on whether or not an internet condition. Something like (this is HAML):

- if internet_connection?
    %script{:src => "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js", :type => "text/javascript"}
- else
    %script{:src => "/shared/javascripts/jquery/jquery.js", :type => "text/javascript"}
Community
  • 1
  • 1
Lance
  • 75,200
  • 93
  • 289
  • 503
  • 1
    possible duplicate of [Checking for internet connection](http://stackoverflow.com/questions/1641984/checking-for-internet-connection) – Ciro Santilli OurBigBook.com Sep 23 '14 at 09:46
  • @CiroSantilli the question you indicated is older, but this is better worded and has substantially better answers... – Brad Werth Sep 25 '14 at 04:45
  • 1
    @BradWerth whichever one we dupe is fine by me ;) I think the other is as good since the context here didn't add much to my underestanding: I read the one liner from the other question and understood the same question. – Ciro Santilli OurBigBook.com Sep 25 '14 at 07:01

7 Answers7

22
require 'open-uri'

def internet_connection?
  begin
    true if open("http://www.google.com/")
  rescue
    false
  end
end

This is closer to what the OP is looking for. It works in Ruby 1.8 and 1.9. It's a bit cleaner too.

MrKrisF
  • 221
  • 2
  • 3
  • +1 I had a similar need and that was the best AND most concise solution. – allesklar Feb 28 '12 at 12:02
  • The problem with this command is that it can block for a long time if the connection is messy and adding the `:read_timeout` is not always reliable: `open("http://www.google.com", { read_timeout: 5 } )` can block for way more than 5 seconds. – Mick F May 29 '14 at 11:22
  • 1
    Right now, with my messy internet connection: puts Benchmark.measure { open("http://www.google.com", { read_timeout: 5 } ) } outputs 0.010000 0.000000 0.010000 ( 35.588267) => nil – Mick F May 29 '14 at 11:24
14

I love how everyone simply assume that googles servers are up. Creds to google.

If you want to know if you have internet without relying on google, then you could use DNS to see if you are able to get a connection.

You can use Ruby DNS Resolv to try to translate a url into an ip address. Works for Ruby version 1.8.6+

So:

#The awesome part: resolv is in the standard library

def has_internet?
  require "resolv"
  dns_resolver = Resolv::DNS.new()
  begin
    dns_resolver.getaddress("symbolics.com")#the first domain name ever. Will probably not be removed ever.
    return true
  rescue Resolv::ResolvError => e
    return false
  end
end

Hope this helps someone out :)

Automatico
  • 12,420
  • 9
  • 82
  • 110
7

You can use the Ping class.

require 'resolv-replace'
require 'ping'

def internet_connection?
  Ping.pingecho "google.com", 1, 80
end

The method returns true or false and doesn't raise exceptions.

Simone Carletti
  • 173,507
  • 49
  • 363
  • 364
  • 1
    Why the need to require 'resolv-replace'? Also, 'ping' has been dropped from the 1.9 standard lib. I came up with a simple enough work around [here](http://github.com/myronmarston/vcr/commit/30b6242a1b0e97a21c27808e416e9b9e8215f994)...but if there's a better way to do this for 1.9, let me know. – Myron Marston Sep 21 '10 at 14:22
  • 1
    This is wrong. A firewall could be blocking ICMP, in which case this would return false. But the internet connection could be fine. – Mark Thomas Apr 03 '14 at 13:03
  • Is this the most ideal way? I mean how does windows get to know if i have to sign in a wifi? Do they ping some servers? (It is completely off topic) – Rishav Mar 02 '18 at 18:47
4

Same basics as in Simone Carletti's answer but compatible with Ruby 2:

# gem install "net-ping"

require "net/ping"

def internet_connection?
  Net::Ping::External.new("8.8.8.8").ping?
end
Community
  • 1
  • 1
fguillen
  • 36,125
  • 23
  • 149
  • 210
1
require 'open-uri'

page = "http://www.google.com/"
file_name = "output.txt"
output = File.open(file_name, "a")
begin
  web_page = open(page, :proxy_http_basic_authentication => ["http://your.company.proxy:80/", "your_user_name", "your_user_password"])  
  output.puts "#{Time.now}: connection established - OK !" if web_page
rescue Exception
  output.puts "#{Time.now}: Connection failed !"
  output.close
ensure
  output.close
end
Ryan Wersal
  • 3,210
  • 1
  • 20
  • 29
Javix
  • 11
  • 1
0

I was trying to find a solution to a problem similar to yours and could not find any. Unfortunately the Ping.pingecho method doesn't work for me for some reason i don't know. I came up with a solution. The latest way to do it using httparty. I wanted this in a module and so did it this way and it works just fine

# gem install httparty
require "httparty"

module Main
  def Main.check_net
    begin
      a = HTTParty.get("https://www.google.com")
      if a.length() >= 100
        puts "online"
      end
    rescue SocketError
      puts "offline"
    end
  end
end

include Main
Main.check_net

A socket error to Google might not happen so this method will work

bit817
  • 40
  • 5
-1
def connected?
  !!Socket.getaddrinfo("google.com", "http")  
rescue SocketError => e
  e.message != 'getaddrinfo: nodename nor servname provided, or not known'
end

Since it uses a hostname the first thing it needs to do is DNS lookup, which causes the exception if there is no internet connection.

Kris
  • 19,188
  • 9
  • 91
  • 111
  • Often DNS lookups are cached on a local server; this is no guarantee that the internet is reachable. – Mark Thomas Apr 03 '14 at 13:07
  • Certainly a possibility. – Kris Apr 03 '14 at 13:07
  • @MarkThomas The same argument can be used for the webpage itself. Often there are CDN servers and possibly caches on the routers themselves. And what about countries that block google.com? The only sure way to know is that you connect to a server you own that has some time-dependent data that it transfers to you that you can verify locally, and then, you only know you have access to that server. I know DNS is more common, but I'm just saying that there can be lots of other things going on as well. – Automatico Apr 03 '14 at 13:48
  • While it's true that there are many potential hops, routers, caches, CDNs, etc. that make it nebulous to define at what point are you hitting "the Internet", I would certainly say that resolving DNS is too early in the process. It is very common when a network is down for DNS to still resolve. – Mark Thomas Apr 03 '14 at 14:10