所以我在Phoenix 1.3 router.ex文件中做了一些元编程魔术。
我需要使用Demo.Repo从数据库中获取一些数据,而我却神奇地组装了一些路线。我如何在router.ex中使用它?
当我运行mix phx.routes
时,出现错误:
repo Demo.Repo is not started, please ensure it is part of your supervision tree
我是否需要以某种方式编辑application.ex文件以在不同的监督树中启动它?
以下是我所拥有的:
defmodule DemoWeb.Router do
use Utils
# other routes not included
car_resources("/cars", CarController, 1)
end
defmodule Utils do
@moduledoc """
Helper functions for autogenerating routes
"""
alias Demo.Repo
alias CarType
defmacro __using__(_options) do
# quote gets the representation of any expression
quote do
import unquote(__MODULE__) # import __MODULE__ into the user's code
@before_compile unquote(__MODULE__)
end
end
defmacro car_resources(path, controller, level) do
quote do
resources unquote(base_path(path, level), unquote(controller)
end
end
def base_path(path, level) do
# do stuff
end
def cars do
%{
1 => Repo.get_by!(CarType, name: "ford"),
2 => Repo.get_by!(CarType, name: "honda"),
}
end
end
答案 0 :(得分:2)
Ecto.Repo
是GenServer
in a nutshell,因此人们可能会使用明确的开始/停止生命周期:
def cars do
with {:ok, pid} <- Demo.Repo.start_link() do
cars = %{
1 => Repo.get_by!(CarType, name: "ford"),
2 => Repo.get_by!(CarType, name: "honda"),
}
Demo.Repo.stop(pid)
cars
else
error -> IO.inspect(error, label: "unable to connect")
end
end
虽然这可能有用,但我强烈建议使用一些文本文件(或任何其他独立源)而不是数据库。首先,在每次后续运行中重新创建测试数据库,并且在测试会话期间您可能最终会得到空路径文件。另外,从同一配置配置的东西读取配置就像鸡蛋问题一样。
答案 1 :(得分:1)
这种方法不起作用,因为在编译期间依赖于数据库。因此,为了定义路由,您需要编译CarType,然后通过调用start_link
来启动存储库。
虽然Elixir足够聪明,可以将这些依赖关系排除在外,但它显示出一种危险的耦合程度。例如,如果添加新的CarType,则需要重新编译代码。由于在数据库中添加了新类型的汽车,因此部署新代码感觉很尴尬。
相反,我会按:car_type
嵌套路线并始终动态获取车型:
scope "/cars/:car_type" do
resources "/cars", CarController
end
然后你在插件中获取:car_type
并将其存储在连接中。