How can I fix this unexpected token (JSON parser error) - ruby-on-rails

I am trying to save data from an API to my database, but I'm running into an error. The error states: unexpected token at 'object' (JSON::ParserError)
Here is my code:
require 'rest-client'
require 'pp'
endpoint = "https://api.leaddyno.com/v1/leads"
class TestDyno
def parser(page_number)
## API key
request = {:params => {:key => Rails.application.secrets.LEADDYNO_PRIVATE, page: page_number}}
## Parse JSON
response = JSON.parse(RestClient.get endpoint, request)
#response_count = response.count # Count results on the page.
pp response
puts response_count
end
def data
until #response_count == 0
1.upto(5) do |page_number|
response['object'].each do |item|
LeaddynoLead.save(
leaddyno_lead_id: item['id'],
email: item['email'],
first_name: item['first_name'],
last_name: item['last_name'],
latest_visitor_id: item['latest_visitor']['id'],
latest_visitor_code: item['latest_visitor']['tracking_code'],
url: item['url']['url'],
referrer_id: item['referrer']['id'],
referrer_url: item['referrer']['url'],
leaddyno_affiliate_id: item['affiliate']['id'],
leaddyno_affiliate_email: item['affiliate']['email'],
search_term: item['search_term']['term'],
search_engine: item['search_term']['search_engine'],
leaddyno_tracking_code: item['tracking_code'],
created_at: item['created_at'],
updated_at: item['updated_at']
)
sleep 0.5
end
end
end
end
end
retrieve = TestDyno.new
retrieve.data
I guess I need another set of eyes to look at this and see what is wrong?
The API docs are here if that helps. Thanks.

Related

Refactoring an API request on Rails

I have a rails worker using redis/sidekiq where I send some data to an API (Active Campaign), so I normally use all the http configurations to send data. I want to have it nice and clean, so it's part of a refactor thing. My worker currently looks like this:
class UpdateLeadIdWorker
include Sidekiq::Worker
BASE_URL = Rails.application.credentials.dig(:active_campaign, :url)
private_constant :BASE_URL
API_KEY = Rails.application.credentials.dig(:active_campaign, :key)
private_constant :API_KEY
def perform(ac_id, current_user_id)
lead = Lead.where(user_id: current_user_id).last
url = URI("#{BASE_URL}/api/3/contacts/#{ac_id}") #<--- need this endpoint
https = bindable_lead_client.assign(url)
pr = post_request.assign(url)
case lead.quote_type
when 'renter'
data = { contact: { fieldValues: [{ field: '5', value: lead.lead_id }] } }
when 'home'
data = { contact: { fieldValues: [{ field: '4', value: lead.lead_id }] } }
when 'auto'
data = { contact: { fieldValues: [{ field: '3', value: lead.lead_id }] } }
else
raise 'Invalid quote type'
end
pr.body = JSON.dump(data)
response = JSON.parse(https.request(pr).read_body).symbolize_keys
if response.code == '200'
Rails.logger.info "Successfully updated contact #{ac_id} with lead id #{lead.lead_id}"
else
raise "Error creating contact: #{response.body}"
end
end
def bindable_lead_client
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http
end
def post_request
post_request_ = Net::HTTP::Put.new(url)
post_request_['Accept'] = 'application/json'
post_request_['Content-Type'] = 'application/json'
post_request_['api-token'] = API_KEY
post_request_
end
end
But whenever I run this I get:
2022-07-28T00:52:08.683Z pid=24178 tid=1s1u WARN: NameError: undefined local variable or method `url' for #<UpdateLeadIdWorker:0x00007fc713442be0 #jid="e2b9ddb6d5f4b8aecffa4d8b">
Did you mean? URI
I don't want everything stuck in one method. How could I achieve to make this cleaner?
Thanks.
Pure ruby wise, The reason you get the error is because your method definition bindable_lead_client is missing the url argument. Hence undefined variable.
So def should look something like:
def bindable_lead_client (url)
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http
end
and call:
bindable_lead_client(url)
As for how to make this code better, falls under question being too subjective under StackOverflow guidelines, which encourage you to ask more specific questions.

HTTParty::Response is cast into Hash when passed as argument to another method

I have a service method that makes api requests and if the response was not ok, it would notify Bugsnag. It looks like this:
def send_request
#response = HTTParty.get(api_endpoint, options)
return JSON.parse(#response.body, symbolize_names: true) if #response.ok?
raise StandardError.new(JSON.parse(#response.body))
rescue StandardError => exception
BugsnagService.notify(exception, #response)
end
My BugsnagService#notify looks something like this:
class BugsnagService
def self.notify(exception, response = nil, **options)
if response
response_body = if valid_json?(response.body) # Error right here
JSON.parse(response.body)
else
response.body
end
options[:response_body] = response_body
options[:response_code] = response.code
end
# Raising exception in test and development environment, or else the exception will be
# silently ignored.
raise exception if Rails.env.test? || Rails.env.development?
Bugsnag.notify(exception) do |report|
report.add_tab(:debug_info, options) if options.present?
end
end
def self.valid_json?(json_string)
JSON.parse(json_string)
true
rescue JSON::ParserError => e
false
end
end
I set response = nil in my notify method because not every error is an API error, so sometimes I would just call BugsnagService.notify(exception).
I found out that if I just call it like I am in the snippet above, it would raise an error saying it can't call .body on a Hash. Somehow, when I pass #response into BugsnagService#notify, the object turns from HTTParty::Response into Hash.
But if I pass something in for the **options parameter, it will work. So I can call it like this:
BugsnagService.notify(exception, #response, { })
I've been trying to figure this one out but I couldn't find anything that would explain this. I'm not sure if there's something wrong with the way I define my parameters or if this is some bug with the HTTParty gem. Can anyone see why this is happening? Thanks!
The problem is that your #response is being passed in as the options, as response can be nil. The double splat is converting it to a hash.
Try:
def testing(x, y = nil, **z)
puts "x = #{x}"
puts "y = #{y}"
puts "z = #{z}"
end
testing 1, 2, z: 3
#=> x = 1
#=> y = 2
#=> z = {:z=>3}
testing 1, y: 2
#=> x = 1
#=> y =
#=> z = {:y=>2}
testing 1, { y: 2 }, {}
#=> x = 1
#=> {:y=>2}
#=> {}
I'd suggest the best approach would be to have response be a keyword arg, as in:
def self.notify(exception, response: nil, **options)
...
end
That way, you can still omit or include the response as desired, and pass in subsequent options.

Can't loop through JSON data because of the error "no implicit conversion of hash into integer"

Hello and good afternoon all!
I am getting an error in my console that states "TypeError: No implicit conversion of hash into integer" and I know that it is referring to my loop in my Ruby class document.
Here is my Ruby file:
require 'HTTParty'
require 'pp'
require 'pry'
=begin
find a way to access the latitude and longitude of the nearest charging station globally
find a way to access the latitude and longitude of the user
create a function that finds the nearest station based on accepting both sets of coordinates and finds the difference
=end
class ChargingStations
include HTTParty
attr_accessor :pois
puts "loading"
##latitude = ''
base_uri 'https://api.openchargemap.io/v2'
def self.puts_latitude
puts ##latitude
end
def initialize(pois)
##pois = pois
##latitude = ##pois
puts ##pois
end
def self.put_value
puts ##latitude
end
def self.find_sites
for i in ##pois do
puts ##pois[i]
if ##pois[i]["AddressInfo"]["StateOrProvince"] == "New York"
puts ##pois[i]
end
end
end
def self.generate
response = get('/poi')
puts "got here"
if response.success?
puts "success"
self.new(response)
else
puts "failure"
raise response.response
end
end
end
binding.pry
If you are able to answer the question, please explain why my loop does not work for myself and future developers.
Thank you!
Why don't you give this a try:
class ChargingStations
include HTTParty
##latitude = ''
base_uri 'https://api.openchargemap.io/v2'
class << self
def pois
##pois
end
def puts_latitude
puts ##latitude
end
def put_value
puts ##latitude
end
def state_or_provinces
#state_or_provinces ||= ##pois.map do |poi|
poi.try(:[],'AddressInfo').try(:[],'StateOrProvince')
end.uniq
end
def find_sites(state_or_province=nil)
#state_or_province = state_or_province
#state_or_province ||= 'New York'
##pois.select do |poi|
poi.try(:[],'AddressInfo').try(:[],'StateOrProvince') == #state_or_province
end
end
def generate
response = get('/poi')
if response.success?
##pois = response.parsed_response
##latitude = ##pois
return true
else
puts "failure"
raise response.response
end
end
end # Class methods
end
Then, in console, I get:
ChargingStations.generate
=> true
ChargingStations.find_sites.count
=> 2
ChargingStations.find_sites.first
=> {"ID"=>112491, "UUID"=>"5EA5B030-AFEF-4CFA-88DF-3A9F6CFFDAB5", "ParentChargePointID"=>nil, "DataProviderID"=>1, "DataProvider"=>{"WebsiteURL"=>"http://openchargemap.org", "Comments"=>nil, "DataProviderStatusType"=>{"IsProviderEnabled"=>true, "ID"=>1, "Title"=>"Manual Data Entry"}, "IsRestrictedEdit"=>false, "IsOpenDataLicensed"=>true, "IsApprovedImport"=>true, "License"=>"Licensed under Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)", "DateLastImported"=>nil, "ID"=>1, "Title"=>"Open Charge Map Contributors"}, "DataProvidersReference"=>nil, "OperatorID"=>5, "OperatorInfo"=>{"WebsiteURL"=>"http://www.chargepoint.net/", "Comments"=>nil, "PhonePrimaryContact"=>"1-888-758-4389", "PhoneSecondaryContact"=>nil, "IsPrivateIndividual"=>false, "AddressInfo"=>nil, "BookingURL"=>nil, "ContactEmail"=>"support#coulombtech.com", "FaultReportEmail"=>"support#coulombtech.com", "IsRestrictedEdit"=>nil, "ID"=>5, "Title"=>"ChargePoint (Coulomb Technologies)"}, "OperatorsReference"=>nil, "UsageTypeID"=>1, "UsageType"=>{"IsPayAtLocation"=>nil, "IsMembershipRequired"=>nil, "IsAccessKeyRequired"=>nil, "ID"=>1, "Title"=>"Public"}, "UsageCost"=>"free", "AddressInfo"=>{"ID"=>112837, "Title"=>"1 Locks Plaza", "AddressLine1"=>"1 Locks Plaza", "AddressLine2"=>nil, "Town"=>"Lockport", "StateOrProvince"=>"New York", "Postcode"=>"14094", "CountryID"=>2, "Country"=>{"ISOCode"=>"US", "ContinentCode"=>"NA", "ID"=>2, "Title"=>"United States"}, "Latitude"=>43.169316400362, "Longitude"=>-78.6954369797903, "ContactTelephone1"=>nil, "ContactTelephone2"=>nil, "ContactEmail"=>nil, "AccessComments"=>"Located at the Lockport Municipal building, \"The Big Bridge\" and the \"Flight of Five\" locks 34 and 35 on the Erie Canal.", "RelatedURL"=>nil, "Distance"=>nil, "DistanceUnit"=>0}, "NumberOfPoints"=>1, "GeneralComments"=>"Located at the \"Big Bridge\" and \"Flight of Five\" locks 34 and 35 and the Lockport Municipal building", "DatePlanned"=>nil, "DateLastConfirmed"=>nil, "StatusTypeID"=>50, "StatusType"=>{"IsOperational"=>true, "IsUserSelectable"=>true, "ID"=>50, "Title"=>"Operational"}, "DateLastStatusUpdate"=>"2018-11-04T12:56:00Z", "DataQualityLevel"=>1, "DateCreated"=>"2018-11-04T05:18:00Z", "SubmissionStatusTypeID"=>200, "SubmissionStatus"=>{"IsLive"=>true, "ID"=>200, "Title"=>"Submission Published"}, "UserComments"=>[{"ID"=>20389, "ChargePointID"=>112491, "CommentTypeID"=>10, "CommentType"=>{"ID"=>10, "Title"=>"General Comment"}, "UserName"=>"Robert Seemueller", "Comment"=>"Located next to the Erie Canal's \"Flight of Five\" locks, downtown shops and restaurants.", "Rating"=>5, "RelatedURL"=>nil, "DateCreated"=>"2018-11-04T05:22:02.4Z", "User"=>{"ID"=>19108, "IdentityProvider"=>nil, "Identifier"=>nil, "CurrentSessionToken"=>nil, "Username"=>"Robert Seemueller", "Profile"=>nil, "Location"=>nil, "WebsiteURL"=>nil, "ReputationPoints"=>289, "Permissions"=>nil, "PermissionsRequested"=>nil, "DateCreated"=>nil, "DateLastLogin"=>nil, "IsProfilePublic"=>nil, "IsEmergencyChargingProvider"=>nil, "IsPublicChargingProvider"=>nil, "Latitude"=>nil, "Longitude"=>nil, "EmailAddress"=>nil, "EmailHash"=>nil, "ProfileImageURL"=>"https://www.gravatar.com/avatar/d8475a6af1852aa7fb2e1263c4ae5fac?s=80&d=mm", "IsCurrentSessionTokenValid"=>nil, "APIKey"=>nil, "SyncedSettings"=>nil}, "CheckinStatusTypeID"=>10, "CheckinStatusType"=>{"IsPositive"=>true, "IsAutomatedCheckin"=>false, "ID"=>10, "Title"=>"Charged Successfully"}}], "PercentageSimilarity"=>nil, "Connections"=>[{"ID"=>158246, "ConnectionTypeID"=>1, "ConnectionType"=>{"FormalName"=>"SAE J1772-2009", "IsDiscontinued"=>nil, "IsObsolete"=>nil, "ID"=>1, "Title"=>"J1772"}, "Reference"=>nil, "StatusTypeID"=>50, "StatusType"=>{"IsOperational"=>true, "IsUserSelectable"=>true, "ID"=>50, "Title"=>"Operational"}, "LevelID"=>2, "Level"=>{"Comments"=>"Over 2 kW, usually non-domestic socket type", "IsFastChargeCapable"=>false, "ID"=>2, "Title"=>"Level 2 : Medium (Over 2kW)"}, "Amps"=>nil, "Voltage"=>nil, "PowerKW"=>nil, "CurrentTypeID"=>nil, "CurrentType"=>nil, "Quantity"=>2, "Comments"=>nil}], "MediaItems"=>[{"ID"=>16951, "ChargePointID"=>112491, "ItemURL"=>"https://s3-ap-southeast-2.amazonaws.com/openchargemap/images/US/OCM112491/OCM-112491.orig.2018110405191125.jpg", "ItemThumbnailURL"=>"https://s3-ap-southeast-2.amazonaws.com/openchargemap/images/US/OCM112491/OCM-112491.thmb.2018110405191125.jpg", "Comment"=>"", "IsEnabled"=>true, "IsVideo"=>false, "IsFeaturedItem"=>false, "IsExternalResource"=>false, "MetadataValue"=>nil, "User"=>{"ID"=>19108, "IdentityProvider"=>nil, "Identifier"=>nil, "CurrentSessionToken"=>nil, "Username"=>"Robert Seemueller", "Profile"=>nil, "Location"=>nil, "WebsiteURL"=>nil, "ReputationPoints"=>289, "Permissions"=>nil, "PermissionsRequested"=>nil, "DateCreated"=>nil, "DateLastLogin"=>nil, "IsProfilePublic"=>nil, "IsEmergencyChargingProvider"=>nil, "IsPublicChargingProvider"=>nil, "Latitude"=>nil, "Longitude"=>nil, "EmailAddress"=>nil, "EmailHash"=>nil, "ProfileImageURL"=>"https://www.gravatar.com/avatar/d8475a6af1852aa7fb2e1263c4ae5fac?s=80&d=mm", "IsCurrentSessionTokenValid"=>nil, "APIKey"=>nil, "SyncedSettings"=>nil}, "DateCreated"=>"2018-11-04T05:19:00Z"}, {"ID"=>16952, "ChargePointID"=>112491, "ItemURL"=>"https://s3-ap-southeast-2.amazonaws.com/openchargemap/images/US/OCM112491/OCM-112491.orig.2018110405224211.jpg", "ItemThumbnailURL"=>"https://s3-ap-southeast-2.amazonaws.com/openchargemap/images/US/OCM112491/OCM-112491.thmb.2018110405224211.jpg", "Comment"=>"", "IsEnabled"=>true, "IsVideo"=>false, "IsFeaturedItem"=>false, "IsExternalResource"=>false, "MetadataValue"=>nil, "User"=>{"ID"=>19108, "IdentityProvider"=>nil, "Identifier"=>nil, "CurrentSessionToken"=>nil, "Username"=>"Robert Seemueller", "Profile"=>nil, "Location"=>nil, "WebsiteURL"=>nil, "ReputationPoints"=>289, "Permissions"=>nil, "PermissionsRequested"=>nil, "DateCreated"=>nil, "DateLastLogin"=>nil, "IsProfilePublic"=>nil, "IsEmergencyChargingProvider"=>nil, "IsPublicChargingProvider"=>nil, "Latitude"=>nil, "Longitude"=>nil, "EmailAddress"=>nil, "EmailHash"=>nil, "ProfileImageURL"=>"https://www.gravatar.com/avatar/d8475a6af1852aa7fb2e1263c4ae5fac?s=80&d=mm", "IsCurrentSessionTokenValid"=>nil, "APIKey"=>nil, "SyncedSettings"=>nil}, "DateCreated"=>"2018-11-04T05:23:00Z"}, {"ID"=>16953, "ChargePointID"=>112491, "ItemURL"=>"https://s3-ap-southeast-2.amazonaws.com/openchargemap/images/US/OCM112491/OCM-112491.orig.2018110405240797.jpg", "ItemThumbnailURL"=>"https://s3-ap-southeast-2.amazonaws.com/openchargemap/images/US/OCM112491/OCM-112491.thmb.2018110405240797.jpg", "Comment"=>"", "IsEnabled"=>true, "IsVideo"=>false, "IsFeaturedItem"=>false, "IsExternalResource"=>false, "MetadataValue"=>nil, "User"=>{"ID"=>19108, "IdentityProvider"=>nil, "Identifier"=>nil, "CurrentSessionToken"=>nil, "Username"=>"Robert Seemueller", "Profile"=>nil, "Location"=>nil, "WebsiteURL"=>nil, "ReputationPoints"=>289, "Permissions"=>nil, "PermissionsRequested"=>nil, "DateCreated"=>nil, "DateLastLogin"=>nil, "IsProfilePublic"=>nil, "IsEmergencyChargingProvider"=>nil, "IsPublicChargingProvider"=>nil, "Latitude"=>nil, "Longitude"=>nil, "EmailAddress"=>nil, "EmailHash"=>nil, "ProfileImageURL"=>"https://www.gravatar.com/avatar/d8475a6af1852aa7fb2e1263c4ae5fac?s=80&d=mm", "IsCurrentSessionTokenValid"=>nil, "APIKey"=>nil, "SyncedSettings"=>nil}, "DateCreated"=>"2018-11-04T05:24:00Z"}], "MetadataValues"=>nil, "IsRecentlyVerified"=>true, "DateLastVerified"=>"2018-11-04T05:22:02.4Z"}
ChargingStations.find_sites('WA').count
=> 1
In general, when you use the construct for foo in fooArray to iterate over a Array, the foo is not the index but the actual item located in that position. So if you wanted your algorithm to work with minimal modifications, the "right" way would look like:
##pois.each_index do |i|
puts ##pois[i]
// rest of the algorithm ommited
end
In your case, assuming that the structure of your JSON data is something like [{lat: 10, lng: 10},{lat:5, lng:8}, {lat: 9, lng: -3], you are basically trying to do ##pois[{lat: 10, lng: 5}]], which will give you the exact "no implicit conversion" error that you're getting. You could just use i directly like puts i or i["AddressInfo"]["StateOrProvince"] and get the right answer.
However, as it has been mentioned in the comments, a more idiomatic approach would be ##pois.each do |poi|. And an even more idiomatic approach would be to rename that ugly-looking "pois" everywhere and make it
##positions.each do |position|
puts position
if position["AddressInfo"]["StateOrProvince"] == "New York"
puts position
end
end
Explicit variable names is the Ruby thing to do :)
And assuming the first puts is just a general test to see it's working and you actually want to only print the ones that are in New York...
##positions.each do |position|
puts position if position["AddressInfo"]["StateOrProvince"] == "New York"
end
And if you want to make that a one liner:
##positions.each { |pos| puts pos if pos["AddressInfo"]["StateOrProvince"] == "New York" }
(yeah, I know I just talked about explicit variable names but there is no need to be too rigid about it)

Can't get values from json stored in database

I'm trying to write app which logs json msgs to db. That part I got. The problem comes with getting that json back. I can't get values from it.
I've tried to get raw msgs from db and getting values from this ( json gem seems not to see it as json)
I've tried to parse it via .to_json , but it doesn't seem to work either. Maby you have some idea how to get it?
Thanks in advance
table:
mjl_pk bigserial
mjl_body text <- JSON is stored here
mjl_time timestamp
mjl_issuer varchar
mjl_status varchar
mjl_action varchar
mjl_object varchar
mjl_pat_id varchar
mjl_stu_id varchar
code:
#Include config catalog, where jsonadds is
$LOAD_PATH << 'config'
#Requirements
require 'sinatra'
require 'active_record'
require 'json'
require 'jsonadds'
require 'RestClient'
#Class for db
class Mjl < ActiveRecord::Base
#table name
self.table_name = "msg_json_log"
#serialization
serialize :properties, JSON
#overwrite ActiveRecord id with "mjl_pk"
def self.primary_key
"mjl_pk"
end
end
#Get json msg and write it to db
post '/logger' do
content_type :json
#Check if msg is json
if JSON.is_json?(params[:data])
#insert data into db
msg = Mjl.create(:mjl_body => params[:data] ,:mjl_issuer => 'LOGGER', :mjl_action => 'test', :mjl_object =>'obj')
else
#else return error
puts "Not a JSON \n" + params[:data]
end
end
#Get json with id = params[:id]
get '/json/:id' do
content_type :json
#Get json from db
json_body = Mjl.where(mjl_pk: params[:id]).pluck(:mjl_body)
puts json_body
json_body = json_body.to_json
puts json_body
#Get 'patientData' from json
puts json_body['key']
puts json_body[0]['key']
end
Output:
{
"key": "I am a value",
"group": {
"key2": "Next value",
"key3": "Another one"
},
"val1": "Val"
}
["{\n \"key\": \"I am a value\",\n \"group\": {\n \"key2\": \"Next value\",\n \"key3\": \"Another one\"\n },\n \"val1\": \"Val\"\n}"]
key
<--empty value from 'puts json_body[0]['key']'
I've also created a JSON Log in my project like this, this might help you...
In Controller
current_time = Time.now.strftime("%d-%m-%Y %H:%M")
#status_log = {}
#arr = {}
#arr[:status_id] = "2.1"
#arr[:status_short_desc] = "Order confirmed"
#arr[:status_long_desc] = "Order item has been packed and ready for shipment"
#arr[:time] = current_time
#status_log[2.1] = #arr
#status_log_json = JSON.generate(#status_log)
StoreStock.where(:id => params[:id]).update_all(:status_json => #status_log_json)
In View
#json_status = JSON.parse(ps.status_json) # ps.status_json contails raw JSON Log
= #json_status['2.1']['status_long_desc']
Hope this might help you.
when you are doing
json_body = Mjl.where(mjl_pk: params[:id]).pluck(:mjl_body)
you already have json
so no need doing
json_body = json_body.to_json
Since doing this you get the string representation of json, just remove that line and you will get all the values.
Finally I've found how to do it.
I saw explanation on JSON methods at:
from json to a ruby hash?
Code which works for me:
json_body = Mjl.where(mjl_pk: params[:id]).pluck(:mjl_body)
puts json_body
jparsed = JSON.parse(json_body[0])
puts jparsed['key']

Ruby, forming API request without implicitly stating each parameter

I'm trying to make a request to a web service (fwix), and in my rails app I've created the following initializer, which works... sorta, I have two problems however:
For some reason the values of the parameters need to have +'s as the spaces, is this a standard thing that I can accomplish with ruby? Additionally is this a standard way to form a url? I thought that spaces were %20.
In my code how can I take any of the options sent in and just use them instead of having to state each one like query_items << "api_key=#{options[:api_key]}" if options[:api_key]
The following is my code, the trouble area I'm having are the lines starting with query_items for each parameter in the last method, any ideas would be awesome!
require 'httparty'
module Fwix
class API
include HTTParty
class JSONParser < HTTParty::Parser
def json
JSON.parse(body)
end
end
parser JSONParser
base_uri "http://geoapi.fwix.com"
def self.query(options = {})
begin
query_url = query_url(options)
puts "querying: #{base_uri}#{query_url}"
response = get( query_url )
rescue
raise "Connection to Fwix API failed" if response.nil?
end
end
def self.query_url(input_options = {})
#defaults ||= {
:api_key => "my_api_key",
}
options = #defaults.merge(input_options)
query_url = "/content.json?"
query_items = []
query_items << "api_key=#{options[:api_key]}" if options[:api_key]
query_items << "province=#{options[:province]}" if options[:province]
query_items << "city=#{options[:city]}" if options[:city]
query_items << "address=#{options[:address]}" if options[:address]
query_url += query_items.join('&')
query_url
end
end
end
For 1)
You API provider is expecting '+' because the API is expecting in a CGI formatted string instead of URL formatted string.
require 'cgi'
my_query = "hel lo"
CGI.escape(my_query)
this should give you
"hel+lo"
as you expect
for Question 2) I would do something like
query_items = options.keys.collect { |key| "#{key.to_s}=#{options[key]}" }
def self.query_url(input_options = {})
options = {
:api_key => "my_api_key",
}.merge(input_options)
query_url = "/content.json?"
query_items = []
options.each { |k, v| query_items << "#{k}=#{v.gsub(/\s/, '+')}" }
query_url += query_items.join('&')
end
I'm a developer at Fwix and wanted to help you with your url escaping issue. However, escaping with %20 works for me:
wget 'http://geoapi.fwix.com/content.xml?api_key=mark&province=ca&city=san%20francisco&query=gavin%20newsom'
I was hoping you could provide me with the specific request you're making that you're unable to escape with %20.

Resources