Reputation: 10207
In my Rails 4 app I have this module which retrieves a bunch of geo data about a user based on his/her IP address:
module GeoLocation
def self.get(key, ip_address)
response_hash = JSON.parse(response(ip_address))
response_hash[key]
end
private
def self.response(ip_address)
@response ||= RestClient.get("http://api.hostip.info/get_json.php?ip=#{ip_address}&position=true")
end
end
Since I don't want to hit the api.hostip.info service too many times, I thought it's a good idea to store its JSON response in an instance variable.
This works.
But if the user's IP address (which is stored in the database) changes, my function still shows the data based on the old IP address.
Is there a way to redefine the instance variable @response
if the user's IP address database field changes?
Thanks for any help.
Upvotes: 0
Views: 65
Reputation: 3053
You have two main options.
The first is to create a new method that you call if you notice that the ip address changed:
def self.new_response(ip_address)
@response = RestClient.get("http://api.hostip.info/get_json.php?ip=#{ip_address}&position=true")
end
The better option, I think, would be to use caching to store the response, instead of an instance variable. You could then use the ip address as part of the cache.
def self.response(ip_address)
Rails.cache.fetch("api-response-#{ip_address}") do
RestClient.get("http://api.hostip.info/get_json.php?ip=#{ip_address}&position=true")
end
end
This way, you will always be storing the location information for that particular ip address and the cache and will automatically cache the new response when the ip changes.
Upvotes: 1
Reputation: 36860
You could store the responses in a hash and just return the appropriate hash entry...
def self.response(ip_address)
@response ||= {}
@response[ip_address] ||= RestClient.get("http://api.hostip.info/get_json.php?ip=#{ip_address}&position=true")
end
Upvotes: 3