Deploying to Heroku broken by dependency on sqlite
The switch to sqlite makes a lot of sense, but breaks Heroku deployment.
Here's what we're testing as a workaround. Curious if you have additional thoughts, or might want to bake this into the gem/documentation:
-
Don't require ziptz by default in Gemfile.
gem "ziptz", require: false -
Add a method or rake task to do something like the following:
require "ziptz" zips_by_tz = TZInfo::Timezone .all_identifiers .map { |tz| [tz, Ziptz.instance.zips(tz)] } .reject { |tz, zips| zips.blank? } zones = zips_by_tz.map(&:first) index = zips_by_tz.reduce([]) do |memo, (tz, zips)| zips.each do |zip| n = zip[0].to_i memo[n] ||= {} memo[n][zip] = zones.index(tz) end memo end (0..9).each do |i| File.open("config/zip_codes/#{i}.json", "w") do |file| file.write({ time_zones: zones, zip_codes: indexed[i] }.to_json) end endThis method can be run in development once, then whenever the ziptz gem is updated. It updates local config files, which would be committed into version control. There is a separate file for each starting digit so each file is < 50KB, improving speed and reducing object allocations. This could be split into 100 buckets pretty easily too for more marginal benefit.
-
Add a method to fetch a time zone by zip code from a JSON file at runtime:
module ZipCode def self.time_zone_name(zip) lookup = JSON.parse(File.read("config/zip_codes/#{zip[0]}.json")) zone_index = lookup.dig("zip_codes", zip) if zone_index lookup.fetch("time_zones").fetch(zone_index) end end end
Would something the approach in the https://github.com/infused/ziptz/tree/in_memory branch work? Instead of using the on-disk database, it creates an in-memory SQLite3 database during initialization.
@infused I'd need to try deploying something with that change to be certain, but I think the issue is that the Heroku environment does not include dependencies that sqlite3 needs in order to be installed. They do as much as possible to prevent folks from using sqlite as their production db without realizing that it won't be persistent on Heroku's ephemeral file system.