rails2 ruby geocoder issue when finding the distance - ruby

I'm using ruby geocoder gem in my rails2 app. When a user tries to sign up i'm taking his ip and fetching lat and long using geocoder. Next, taking user entered address and fetching lat and longitude. Finally checking the distance between those two.If distance is greater than 100 am adding an error. This is happening in before_create callback(As per clients requirement). But the issue here is geocoder is sending continuous requests and breaking.Below is my code.
Given some dummy address and ip for testing purpose.
def validate_address_and_ip
p "validate_address_and_ip"
dup_addr = "Level 8, Umiya Business Bay Tower 1,Cessna Business Park, Maratahalli ORR,Sarjapur Ring Road, Kadubeesanahalli,Bangalore"
ip_based_lat_lng = Geocoder.search("183.82.98.134").map{ |obj| [obj.latitude, obj.longitude] }.flatten#ip_address
p "ip_based_lat_lng=", ip_based_lat_lng
addr_results = Geocoder.search(dup_addr)#address.full_address
addr_based_result = addr_results.first.geometry["location"]
lat,lang = addr_based_result["lat"], addr_based_result["lng"]
dist_in_miles = Geocoder::Calculations.distance_between(ip_based_lat_lng, [lat, lang]).round
puts "***************#{dist_in_miles}*******************************"
if 300 > 100
p "*****************in if condition**********************"
self.errors.add_to_base('zip code and IP mismatch.')
return false
puts "***************#{self.errors}*******************************"
end
end
Error: Numerical argument out of domain - sqrt
in log am getting
"validate_address_and_ip"
"ip_based_lat_lng="
[17.3753, 78.4744]
******311***************
"*******in if condition***********"
"validate_address_and_ip"
Geocoding API not responding fast enough (use Geocoder.configure(:timeout => ...) to set limit).
"ip_based_lat_lng="
[]
Why is that method getting called multiple times? Can anyone tell me the issue

Related

Only convert a subset of iprange to ip array in ruby

I have a range of ip addresses that thanks to some google fu I have been able to take the range and convert to an array of IP addresses. However I am running out of memory when the script is ran against a range of say 10.234.xxx.1/24. As such I am trying to see if there is a way to pull out a subset of 32 addresses so that I don't have this extra memory usage.
ips.each do |ip|
ip_from = ip.instance_of?(Nexpose::HostName) ? ip.host : (ip.from..ip.to).map(&:to_s)
ip_from2 = ip_from.select{ |i| /[0-9]*\.[0-9]*\.[0-9]*\.([2-3][0-9]|64)$/ =~ i }
ip_from2.each do |ip2|
log.log_debug_message("Getting credentials for #{ip2}")
secret_summary = ss.get_secret_id(token, ip2)
unless secret_summary.nil?
log.log_debug_message("Found credentials for #{ip2}")
# Gets OS
asset_data = {}
asset_data[:ip] = ip2
res = ss.get_secret_simple(token, secret_summary[:secret_id])
asset_data[:username] = res[:username]
asset_data[:password] = res[:password]
credential = Nexpose::SiteCredential.for_service(ss.check_type(secret_summary[:secret_type]),
asset_data[:username],
asset_data[:password],
nil,
ip2)
I would like to only have it hold 32 addresses in the array as you can see in the select statement on line 3. Any help is appreciated.
Sidenote: I have modified the nexpose_thycotic gem to make this work for my purposes. I am working through rapid7 as well but I was hoping someone on StackOverflow may be able to answer a little quicker as this is a time sensitive matter.

Save Google Cloud Speech API operation(job) object to retrieve results later

I'm struggling to use the Google Cloud Speech Api with the ruby client (v0.22.2).
I can execute long running jobs and can get results if I use
job.wait_until_done!
but this locks up a server for what can be a long period of time.
According to the API docs, all I really need is the operation name(id).
Is there any way of creating a job object from the operation name and retrieving it that way?
I can't seem to create a functional new job object such as to use the id from #grpc_op
What I want to do is something like:
speech = Google::Cloud::Speech.new(auth_credentials)
job = speech.recognize_job file, options
saved_job = job.to_json #Or some element of that object such that I can retrieve it.
Later, I want to do something like....
job_object = Google::Cloud::Speech::Job.new(saved_job)
job.reload!
job.done?
job.results
Really hoping that makes sense to somebody.
Struggling quite a bit with google's ruby clients on the basis that everything seems to be translated into objects which are much more complex than the ones required to use the API.
Is there some trick that I'm missing here?
You can monkey-patch this functionality to the version you are using, but I would advise upgrading to google-cloud-speech 0.24.0 or later. With those more current versions you can use Operation#id and Project#operation to accomplish this.
require "google/cloud/speech"
speech = Google::Cloud::Speech.new
audio = speech.audio "path/to/audio.raw",
encoding: :linear16,
language: "en-US",
sample_rate: 16000
op = audio.process
# get the operation's id
id = op.id #=> "1234567890"
# construct a new operation object from the id
op2 = speech.operation id
# verify the jobs are the same
op.id == op2.id #=> true
op2.done? #=> false
op2.wait_until_done!
op2.done? #=> true
results = op2.results
Update Since you can't upgrade, you can monkey-patch this functionality to an older-version using the workaround described in GoogleCloudPlatform/google-cloud-ruby#1214:
require "google/cloud/speech"
# Add monkey-patches
module Google
Module Cloud
Module Speech
class Job
def id
#grpc.name
end
end
class Project
def job id
Job.from_grpc(OpenStruct.new(name: id), speech.service).refresh!
end
end
end
end
end
# Use the new monkey-patched methods
speech = Google::Cloud::Speech.new
audio = speech.audio "path/to/audio.raw",
encoding: :linear16,
language: "en-US",
sample_rate: 16000
job = audio.recognize_job
# get the job's id
id = job.id #=> "1234567890"
# construct a new operation object from the id
job2 = speech.job id
# verify the jobs are the same
job.id == job2.id #=> true
job2.done? #=> false
job2.wait_until_done!
job2.done? #=> true
results = job2.results
Ok. Have a very ugly way of solving the issue.
Get the id of the Operation from the job object
operation_id = job.grpc.grpc_op.name
Get an access token to manually use the RestAPI
json_key_io = StringIO.new(ENV["GOOGLE_CLOUD_SPEECH_JSON_KEY"])
authorisation = Google::Auth::ServiceAccountCredentials.make_creds(
json_key_io:json_key_io,
scope:"https://www.googleapis.com/auth/cloud-platform"
)
token = authorisation.fetch_access_token!
Make an api call to retrieve the operation details.
This will return with a "done" => true parameter, once results are in and will display the results. If "done" => true isn't there then you'll have to poll again later until it is.
HTTParty.get(
"https://speech.googleapis.com/v1/operations/#{operation_id}",
headers: {"Authorization" => "Bearer #{token['access_token']}"}
)
There must be a better way of doing that. Seems such an obvious use case for the speech API.
Anyone from google in the house who can explain a much simpler/cleaner way of doing it?

How do I mock AWS SDK (v2) with rspec?

I have a class which reads/processes messages from an SQS queue using the aws-sdk-rails gem (which is a wrapper on aws-sdk-ruby v2). How do I mock the AWS calls so I can test my code without hitting the external services?
communicator.rb:
class Communicator
def consume_messages
sqs_client = Aws::SQS::Client.new
# consume messages until the queue is empty
loop do
r = sqs_client.receive_message({
queue_url: "https://sqs.region.amazonaws.com/xxxxxxxxxxxx/foo",
visibility_timeout: 1,
max_number_of_messages: 1
})
break if (response.message.length == 0)
# process r.messages.first.body
r = sqs_client.delete_message({
queue_url: "https://sqs.region.amazonaws.com/xxxxxxxxxxxx/foo",
receipt_handle: r.messages.first.receipt_handle
})
end
end
end
The AWS SDK already provides stubbing. q.v. http://docs.aws.amazon.com/sdkforruby/api/Aws/ClientStubs.html for more information (Linked to official documentation.)
I had a hard time finding examples mocking AWS resources. I spent a few days figuring it out and wanted to share my results on Stack Overflow for posterity. I used rspec-mocks (doubles & verifying doubles). Here's an example with the communicator.rb example in the question.
communicator_spec.rb:
RSpec.describe Communicator do
describe "#consume_messages" do
it "can use rspec doubles & verifying doubles to mock AWS SDK calls" do
sqs_client = instance_double(Aws::SQS::Client)
allow(Aws::SQS::Client).to receive(:new).and_return(sqs_client)
SQSResponse = Struct.new(:messages)
SQSMessage = Struct.new(:body, :receipt_handle)
response = SQSResponse.new([SQSMessage.new(File.read('data/expected_body.json'), "receipt_handle")])
empty_response = SQSResponse.new([])
allow(sqs_client).to receive(:receive_message).
and_return(response, empty_response)
allow(sqs_client).to receive(:delete_message).and_return(nil)
Communicator.new.consume_messages
end
end
end

ruby - many instances - parallel processing

I'm new to ruby, and I,m not sure why is my program not working as expected.
The problem is that I'm playing with reading certain website and I'm trying to read some info. The problem is that I don't know how to create many instances of the XsidVehicle class.
There is 200 objects I'm trying to read, if each instance waits until the previous finishes then reading the info will take at least 200 seconds. I would like to create many instances with different IDs that would read different pages at the same time.
require 'open-uri'
class XsidVehicle
def VehicleID(id)
#id = id
individual_source = open("https://www.motocykle.com/cars/id/#{id}")
puts individual_source[individual_source.index(id),individual_source.index(id)+12]
end
end
source = open('https://www.motocykle.pl/cars').read
newItem = source.index('lId=')
endOfThePage = source.index('</html>')
myNewSource = source[newItem.to_i,endOfThePage.to_i]
for i in 0..199 do
#puts "This is i: #{i}"
iid = myNewSource[myNewSource.index('"')+1,20]
iid = iid[0,iid.index('"').to_i]
myNewSource = myNewSource[myNewSource.index('class=').to_i,myNewSource.length]
myNewSource = myNewSource[myNewSource.index('listingId=').to_i,myNewSource.length]
puts "iid #{i}: #{iid}" #here i noticed that the class instance is created then it navigates to the website to read it, and then a new instance is created. But I want many instances to be created at the same time, so not to be restricted by ordered processing.
vehicle = XsidVehicle.new
vehicle.VehicleID(iid)
end

How to retrieve the web site URL that provides the email service from an email string?

I am using Ruby on Rails v3.0.9 and I am finding the best way to retrieve the "last part" of a email string and the related web site URL (that is, the web site that provides the email service).
For example, if I have
sample_email_title#gmail.com
I would like to retrieve
gmail.com
and "transform" that so to have the following:
http://www.gmail.com
How can I accomplish that?
You could do something like this:
a = "my_email#gmail.com"
b = a.split("#").last
=> "gmail.com"
"http://www." + b
=> "http://www.gmail.com"
You could do it all in one line with:
"http://www." + "my_email#gmail.com".split('#').last
There may be better ways, but this is fairly simple.
The mail exchange server will often be on a different domain than the email address, so you will have to lookup the MX records using the DNS server to get that information:
require 'resolv'
def mx_host_of_domain(domain)
mx = nil
Resolv::DNS.open do |dns|
servers = dns.getresources(domain, Resolv::DNS::Resource::IN::MX)
if servers && !servers.empty?
mx = servers.sort_by(&:preference).first.exchange.to_s
end
end
mx
end
email = 'stackoverflow' + '#' + 'larshaugseth.com'
mxhost = mx_host_of_domain email.split('#').last
# => in1.smtp.messagingengine.com
url = "http://www.#{mxhost.split('.').last(2).join('.')}/"
# => http://www.messagingengine.com/
Note that there is no guarantee for a web server to be located at this address. In my case the real web address to the email service is https://www.fastmail.fm/, but luckily the one generated by using the above method will forward you there.

Resources