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"}
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.
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 :)
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.
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
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
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
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.
Related
im building a small game in ruby to practice programming, so far everything has went well but im trying to implement multiplayer support, i can connect to the server and i can send information but when I try to read form the server it just freezes and my screen goes completely black. and i cant find the cause, ive read the documentation for the gem im using for TCP and i dont know, maybe i missed something, but if any of you have some insight I would really appreciate it
heres the repo if this code isnt enough
https://github.com/jaypitti/ruby-2d-gosu-game
heres the client side code
class Client
include Celluloid::IO
def initialize(server, port)
begin
#socket = TCPSocket.new(server, port)
rescue
$error_message = "Cannot find game server."
end
end
def send_message(message)
#socket.write(message) if #socket
end
def read_message
#socket.readpartial(4096) if #socket
end
end
heres the gameserver
require 'celluloid/autostart'
require 'celluloid/io'
class Server
include Celluloid::IO
finalizer :shutdown
def initialize(host, port)
puts "Starting Server on #{host}:#{port}."
#server = TCPServer.new(host, port)
#objects = Hash.new
#players = Hash.new
async.run
end
def shutdown
#server.close if #server
end
def run
loop { async.handle_connection #server.accept }
end
def handle_connection(socket)
_, port, host = socket.peeraddr
user = "#{host}:#{port}"
puts "#{user} has joined the arena."
loop do
data = socket.readpartial(4096)
data_array = data.split("\n")
if data_array and !data_array.empty?
begin
data_array.each do |row|
message = row.split("|")
if message.size == 10
case message[0]
when 'obj'
#players[user] = message[1..9] unless #players[user]
#objects[message[1]] = message[1..9]
when 'del'
#objects.delete message[1]
end
end
response = String.new
#objects.each_value do |obj|
(response << obj.join("|") << "\n") if obj
end
socket.write response
end
rescue Exception => exception
puts exception.backtrace
end
end # end data
end # end loop
rescue EOFError => err
player = #players[user]
puts "#{player[3]} has left"
#objects.delete player[0]
#players.delete user
socket.close
end
end
server, port = ARGV[0] || "0.0.0.0", ARGV[1] || 1234
supervisor = Server.supervise(server, port.to_i)
trap("INT") do
supervisor.terminate
exit
end
sleep
it just freezes and my screen goes completely black. and i cant find the cause
A good trick you can look at is attaching to your process with either rbspy or rbtrace to see that is going on when it is stuck.
You can also try first reducing dependencies here a bit and doing this with a simple threadpool prior to going full async with celluloid or event machine.
First of all you should not be rescuing Exception all over the place. Wrapping long begin rescue blocks around nested iterators is begging for trouble.
It sounds like a threading issues, memory and/or CPU but that's just a guess. Try to monitor your resources or use some performance checking gems. But for the love of Satoshi Nakamoto, please write some test coverage and see your methods fail miserably, then fix them!
Some of these may help:
group :development do
gem 'bullet', require: false
gem 'flamegraph', require: false
gem 'memory_profiler', require: false
gem 'rack-mini-profiler', require: false
gem 'seed_dump'
gem 'stackprof', require: false
gem 'traceroute', require: false
end
In my Rails app I am making various API calls like this one:
class SearchFacebook
FALLBACK_STARS = 5.0
def self.call
begin
url = "https://graph.facebook.com/v2.12/#{FACEBOOK_PAGE_ID}"
response = RestClient.get(url, :params => {:access_token => FACEBOOK_ACCESS_TOKEN, :fields => "overall_star_rating"})
json = JSON.parse(response)
stars = json["overall_star_rating"]
rescue RestClient::ExceptionWithResponse => error
stars = FALLBACK_STARS
end
{:stars => stars}
end
end
The problem is that I am running my app in my local environment a lot of the time. When there's no Internet connection available (which happens a lot to me, don't ask why), I get the following error:
SocketError.
Failed to open TCP connection to api.facebook.com:443 (getaddrinfo:
nodename nor servname provided, or not known)
How can I rescue from being offline?
I checked RestClient documentation already but to no avail. Thanks for any help.
Can you use a blanket rescue => e and use byebug to inspect the exception being raised. You could then rescue that error if in a development environment.
There are some other options mentioned here Check if Internet Connection Exists with Ruby?
OK, I solved this by simply rescuing from a SocketError:
rescue SocketError, RestClient::ExceptionWithResponse => error
I found this answer quite helpful.
I can't understand what the below ruby code does. Can anyone give me some explanation. Thanks!
map '/healthz' do
run Healthz.new(logger)
end
The Healthz is:
class Healthz
def initialize(logger)
#logger = logger
end
def call(env)
#logger.debug "healthz access"
healthz = Component.updated_healthz
[200, { 'Content-Type' => 'application/json', 'Content-Length' => healthz.length.to_s }, healthz]
rescue => e
#logger.error "healthz error #{e.inspect} #{e.backtrace.join("\n")}"
raise e
end
end
And the lib used are:
require "eventmachine"
require 'thin'
require "yajl"
require "nats/client"
require "base64"
require 'set'
Since you're using eventmachine and thin, I'd guess that code is some kind of routing code for a simple web application.
That is, it maps the /healtz route of the application to the Healtz class, so that if you start up the app, and point your browser to localhost:<whatever_port_thin_uses>/healtz, it would start up a Healtz.new instance for you.
Since I don't know what Healtz actually does, I've no idea what will actually happen, but my guess is that it's some kind of rack application.
And, as I already stated, this is just my guess, from seeing the list of libs you're using.
I'm trying to verify whether a user has control of a domain as part of my rails 3 app by uploading a randomly generated file to the root of their domain (the same way google does it for google apps). Currently I'm using Net::HTTP and it seems to work if the address is valid but if the address is not valid I get this error.
getaddrinfo: nodename nor servname provided, or not known
Is there a way to somehow ignore this error or a better/ different way to wrtite the code for the controller?
def check
require 'net/http'
require 'uri'
result = Net::HTTP.get_response(URI.parse('http://www.example.com/21312324213123.html'))
if Net::HTTPSuccess
#test = "true"
else
#test = "false"
end
end
Any help would be great. Thanks.
All you need to do is rescue from that exception and return that as a separate case.
def check
# ...
rescue => e
# Uh oh, got an exception
#error = e.to_s
#test = "false"
end
I want to be able to spec out that when Open-Uri open() calls either timeout or raise an exception such as SocketError I am handling things as expected, however I'm having trouble with this.
Here is my spec (for SocketError):
#obj.should_receive(:open).with("some_url").and_raise(SocketError)
And the part of my object where I'm using open-uri:
begin
resp = open(url)
resp = resp.read
rescue SocketError
something = true
end
However in this situation the spec fails as with a nil.read error.
This is the second time this week I've come across this problem, the previous time I was attempting to simulate a TimeoutError when wrapping open() with a timeout() {}, that time I gave up and just caused an actual timeout to happen by opening up the class. I could obviously cause this to throw a SocketError by trying to call an invalid URL, but I'm sure there is a correct way to mock this out with RSpec.
Update: I obviously wasn't thinking clearly that late at night, the error was actually when I re-tried the URL after the SocketError, the and_raise(SocketError) part worked fine.
The line you provided should work, based on the information you've given: I made a tiny test class and spec (see below) with only the described functionality, and things behaved as expected. It might be helpful if you could provide a little more context - the full "it" block from the spec, for instance, might expose some other problem.
As mentioned, the following spec passes, and I believe it captures the logic you were attempting to verify:
require 'rubygems'
require 'spec'
class Foo
attr_accessor :socket_error
def get(url)
#socket_error = false
begin
resp = open(url)
resp = resp.read
rescue SocketError
#socket_error = true
end
end
end
describe Foo do
before do
#foo = Foo.new
end
it "should handle socket errors" do
#foo.should_receive(:open).with("http://www.google.com").and_raise(SocketError)
#foo.get("http://www.google.com")
#foo.socket_error.should be_true
end
end