Class: IPLookup::DB

Inherits:
Object
  • Object
show all
Defined in:
lib/ip_lookup/db.rb

Constant Summary collapse

DEFAULT_UPDATE_PERIOD_IN_DAYS =
30
DEFAULT_UPDATE_URI =
"https://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(silent_exceptions) ⇒ DB

Returns a new instance of DB.



13
14
15
# File 'lib/ip_lookup/db.rb', line 13

def initialize(silent_exceptions)
  @silent_exceptions = silent_exceptions
end

Instance Attribute Details

#silent_exceptionsObject (readonly)

Returns the value of attribute silent_exceptions.



11
12
13
# File 'lib/ip_lookup/db.rb', line 11

def silent_exceptions
  @silent_exceptions
end

Class Method Details

.db_ageObject



85
86
87
# File 'lib/ip_lookup/db.rb', line 85

def db_age
  (Time.now - File.mtime(full_db_path)) / (24 * 60 * 60)
end

.db_exists?Boolean

Returns:



81
82
83
# File 'lib/ip_lookup/db.rb', line 81

def db_exists?
  File.file? full_db_path
end

.db_filenameObject



93
94
95
# File 'lib/ip_lookup/db.rb', line 93

def db_filename
  "/geolite-city.mmdb"
end

.db_pathObject



97
98
99
100
101
102
103
# File 'lib/ip_lookup/db.rb', line 97

def db_path
  if Gem.loaded_specs["ip_lookup"]
    File.join(Gem.loaded_specs["ip_lookup"].full_gem_path, "/support")
  else
    File.join(File.expand_path("../..", File.dirname(__FILE__)), "/support")
  end
end

.fetch_db(update_uri) ⇒ Object



44
45
46
47
48
49
50
51
52
# File 'lib/ip_lookup/db.rb', line 44

def fetch_db(update_uri)
  uri = URI(update_uri)

  response = Net::HTTP.get(uri)

  sio_response = StringIO.new(response)
  gz = Zlib::GzipReader.new(sio_response)
  gz.read
end

.flock(file) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/ip_lookup/db.rb', line 64

def flock(file)
  # return and don't update db if file is locked, because db is already been updated
  return unless file.flock(File::LOCK_EX | File::LOCK_NB)

  if file.flock(File::LOCK_EX)
    begin
      yield file
    ensure
      file.flock(File::LOCK_UN)
    end
  end
end

.full_db_pathObject



89
90
91
# File 'lib/ip_lookup/db.rb', line 89

def full_db_path
  File.join(db_path, db_filename)
end

.mutexObject



23
24
25
# File 'lib/ip_lookup/db.rb', line 23

def self.mutex
  @mutex ||= Mutex.new
end

.save_db(result) ⇒ Object



54
55
56
57
58
59
60
61
62
# File 'lib/ip_lookup/db.rb', line 54

def save_db(result)
  Dir.mkdir(db_path) unless File.exist?(db_path)

  File.open(full_db_path, 'w') do |file|
    flock(file) do |f|
      f.write(result)
    end
  end
end

.update(update_period: DEFAULT_UPDATE_PERIOD_IN_DAYS, update_uri: DEFAULT_UPDATE_URI) ⇒ Object



38
39
40
41
42
# File 'lib/ip_lookup/db.rb', line 38

def update(update_period: DEFAULT_UPDATE_PERIOD_IN_DAYS, update_uri: DEFAULT_UPDATE_URI)
  return unless update_db? update_period

  save_db fetch_db(update_uri)
end

.update_db?(update_period) ⇒ Boolean

Returns:



77
78
79
# File 'lib/ip_lookup/db.rb', line 77

def update_db?(update_period)
  !db_exists? || (update_period >= 0 && db_age > update_period)
end

Instance Method Details

#lookup(ip_address) ⇒ Object



17
18
19
20
21
# File 'lib/ip_lookup/db.rb', line 17

def lookup(ip_address)
  db.lookup ip_address
rescue Errno::ENOENT
  raise DBFileNotFoundError, "Couldn't find DB file. Please update DB before using lookup." unless silent_exceptions
end