在 Ecto migration 中从另一个 Repo 迁移数据
Migrate data from another Repo in Ecto migration
类似于这个问题:,我有一个 Ecto 迁移,我想在其中创建一些新表,但也从 不同的 迁移一些数据存储库。例如:
defmodule MyApp.Repo.Migrations.CreateFoo do
use Ecto.Migration
import Ecto.Query
def change do
create table(:foo) do
add(:status, :text)
end
flush()
execute &import_from_AnotherApp/0
end
defp import_from_AnotherApp()
foos = from(f in AnotherApp.Foo, where: ...)
|> AnotherApp.Repo.all
Enum.each(foos, fn(foo) ->
# Insert data from AnotherApp into MyApp foo table
end)
end
end
问题是当 运行 混合 ecto.migrate 我得到
** (RuntimeError) could not lookup Ecto repo AnotherApp.Repo because it was not started or it does not exist
我尝试在 mix.exs
中添加 AnotherApp
作为 MyApp
的依赖项,但我仍然遇到相同的错误。
这可以做到吗?
当您 运行 混合任务时,它们 运行 在自己的进程中,因此其他应用程序(包括容纳任务的主应用程序)可能无法启动。
有时您必须将这些行放入您的自定义混合任务中,我怀疑您可以将它们放入您的迁移中:
{:ok, _} = Application.ensure_all_started(:my_app)
{:ok, _} = Application.ensure_all_started(:another_app)
但是,有时仅确保它们已启动是不够的:有时您必须明确启动进程。在您的情况下,您必须启动其他应用程序的 Ecto.Repo
。通常,您 start your Ecto repos 将它们列在 application.ex
内的应用程序主管中,例如
def start(_type, _args) do
children = [
{MyApp.Repo, []},
{AnotherApp.Repo, []},
]
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
但是如果您的应用程序的常规功能不需要启动其他应用程序,那么您可以通过 运行ning MyApp.Repo.start_link([])
手动启动该过程。 -- 你可以把它放到你的迁移中看看它是否出现:
x = MyApp.Repo.start_link([])
IO.inspect(x)
运气好的话,你会得到一个 :ok
和一个进程 ID,但如果没有,你应该得到一些有用的调试信息。
希望对您有所帮助。
也许 with_repo(repo, fun, opts \ [])
应该为你做
https://hexdocs.pm/ecto_sql/Ecto.Migrator.html#with_repo/3
类似于这个问题:
defmodule MyApp.Repo.Migrations.CreateFoo do
use Ecto.Migration
import Ecto.Query
def change do
create table(:foo) do
add(:status, :text)
end
flush()
execute &import_from_AnotherApp/0
end
defp import_from_AnotherApp()
foos = from(f in AnotherApp.Foo, where: ...)
|> AnotherApp.Repo.all
Enum.each(foos, fn(foo) ->
# Insert data from AnotherApp into MyApp foo table
end)
end
end
问题是当 运行 混合 ecto.migrate 我得到
** (RuntimeError) could not lookup Ecto repo AnotherApp.Repo because it was not started or it does not exist
我尝试在 mix.exs
中添加 AnotherApp
作为 MyApp
的依赖项,但我仍然遇到相同的错误。
这可以做到吗?
当您 运行 混合任务时,它们 运行 在自己的进程中,因此其他应用程序(包括容纳任务的主应用程序)可能无法启动。
有时您必须将这些行放入您的自定义混合任务中,我怀疑您可以将它们放入您的迁移中:
{:ok, _} = Application.ensure_all_started(:my_app)
{:ok, _} = Application.ensure_all_started(:another_app)
但是,有时仅确保它们已启动是不够的:有时您必须明确启动进程。在您的情况下,您必须启动其他应用程序的 Ecto.Repo
。通常,您 start your Ecto repos 将它们列在 application.ex
内的应用程序主管中,例如
def start(_type, _args) do
children = [
{MyApp.Repo, []},
{AnotherApp.Repo, []},
]
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
但是如果您的应用程序的常规功能不需要启动其他应用程序,那么您可以通过 运行ning MyApp.Repo.start_link([])
手动启动该过程。 -- 你可以把它放到你的迁移中看看它是否出现:
x = MyApp.Repo.start_link([])
IO.inspect(x)
运气好的话,你会得到一个 :ok
和一个进程 ID,但如果没有,你应该得到一些有用的调试信息。
希望对您有所帮助。
也许 with_repo(repo, fun, opts \ [])
应该为你做
https://hexdocs.pm/ecto_sql/Ecto.Migrator.html#with_repo/3