I have this piece of code:
case Timex.Timezone.get(data) do
{:error, _} = error ->
error
data ->
{:ok, data}
end
to put timezones that are saved in the database into a struct.
Well when running a migration that gets some data through an Ecto Query I get this error:
** (ArgumentError) argument error
(stdlib) :ets.lookup(:tzdata_current_release, :release_version)
lib/tzdata/release_reader.ex:47: Tzdata.ReleaseReader.current_release_from_table/0
lib/tzdata/release_reader.ex:14: Tzdata.ReleaseReader.simple_lookup/1
lib/tzdata/release_reader.ex:7: Tzdata.ReleaseReader.zone_and_link_list/0
lib/tzdata.ex:40: Tzdata.zone_exists?/1
lib/timezone/timezone.ex:152: Timex.Timezone.name_of/1
lib/timezone/timezone.ex:180: Timex.Timezone.get/2
lib/common/ecto/timezone.ex:27: Common.Ecto.Timezone.load/1
(ecto) lib/ecto/type.ex:661: Ecto.Type.process_loaders/3
(ecto) lib/ecto/schema.ex:1490: Ecto.Schema.load!/5
(ecto) lib/ecto/schema.ex:1442: Ecto.Schema.safe_load_zip/4
(ecto) lib/ecto/schema.ex:1443: Ecto.Schema.safe_load_zip/4
(ecto) lib/ecto/schema.ex:1430: Ecto.Schema.__safe_load__/6
(ecto) lib/ecto/repo/queryable.ex:282: Ecto.Repo.Queryable.process_source/6
(ecto) lib/ecto/repo/queryable.ex:170: Ecto.Repo.Queryable.preprocess/5
(postgrex) lib/postgrex/query.ex:77: DBConnection.Query.Postgrex.Query.decode_map/3
(postgrex) lib/postgrex/query.ex:64: DBConnection.Query.Postgrex.Query.decode/3
(db_connection) lib/db_connection.ex:1019: DBConnection.decode/6
(ecto) lib/ecto/adapters/postgres/connection.ex:73: Ecto.Adapters.Postgres.Connection.prepare_execute/5
(ecto) lib/ecto/adapters/sql.ex:256: Ecto.Adapters.SQL.sql_call/6
Which has that code in the stack trace and doing some Inspects can verify that that's indeed the call that triggers the error, although doing:
iex(1)> Timex.Timezone.get("America/Los_Angeles")
#<TimezoneInfo(America/Los_Angeles - PDT (-07:00:00))>
In iex -S mix
works.
This error happens because Timex
needs to be started to function. This is normally done automatically if you add it to your mix.exs
dependencies at application startup. However, in mix tasks you have to manually select which applications to start. In your custom mix tasks, you can make sure an application is started via Application.ensure_all_started(:timex)
.
In your ecto.migrate
case, we don't have access to the actual mix task, so we need to be a bit more creative by using mix aliases in your mix.exs
file:
def project do
[
...
aliases: aliases(),
...
]
end
defp aliases do
[
"ecto.migrate_s": ["ecto.migrate.startup", "ecto.migrate"],
]
end
And a Task ecto.migrate.startup
for our Application.ensure_all_started(:timex)
defmodule Mix.Tasks.Ecto.Migrate.Startup do
use Mix.Task
def run(args) do
Mix.shell.info("Starting apps required for ecto.migrate...")
Application.ensure_all_started(:timex)
end
end
Now you should be able to run mix ecto.migrate_s
which first starts timex
and then runs your migrations. (This is not a perfectly clean solution, but I'm not aware of alternatives right now)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With