【问题标题】:ecto_fixtures, preload associationsecto_fixtures,预加载关联
【发布时间】:2018-11-23 20:12:01
【问题描述】:

我在测试我的 Elixir/Phoenix 应用程序时尝试使用 ecto_fixtures (https://github.com/DockYard/ecto_fixtures)。我面临的挑战是我需要预加载关联,但我无法控制从夹具文件创建模型的过程。当我得到给定夹具的结果模型时,它的关联模型尚未加载。我喜欢它们被预加载并准备好迎接黄金时段。

目前,当我这样定义我的灯具时,

在文件 basic_models.exs 中:

basic_models model: MyApp.BasicModel, repo: MyApp.Repo do
  basic_model_one do
    name("A Fake Name")

    other_model(fixtures(:other_models).other_model.email)
  end
end

在文件 other_models.exs 中:

other_models model: MyApp.OtherModel, repo: MyApp.Repo do
  other_model do
    email("fake@email.com")
  end
end

当然,我的测试上面有一个标签,如下所示:

@tag fixtures: ["basic_models"]
test "a test", %{data: data} do 
  some code
end

在测试中,data.basic_models.basic_model_one.other_model 的值为 #Ecto.Association.NotLoaded<association :other_model is not loaded>

我看不到任何预加载该关联的方法,理想情况下,我不会玩游戏来优化我的灯具数据。也许是预加载关联的选项。

谢谢!

【问题讨论】:

    标签: elixir ecto


    【解决方案1】:

    有几种解决方案可以实现这一点。

    你可以像这样声明一个fixture:

    def basic_model_fixture(attrs \\ %{}, preload \\ []) do
      assoc = %{other_model: other_model_fixture()}
      {:ok, basic_model} =
        attrs
        |> Enum.into(%{
          name: "some name",
          other_model_id: assoc.other_model.id
          })
        |> MyApp.BasicModel.create_basic_model()
    
      basic_model
      |> Map.merge(for p <- preload, assoc[p], into: %{}, do: {p, assoc[p]})
    
    end
    

    使用第二个参数preload,您可以选择要预加载的关系。

    preload 参数中的每个键都会将 assoc 映射的关联键合并到您的最终灯具 (basic_model)

    在您的测试文件中,您可以添加预加载信息:

    basic_model = basic_model_fixture(%{}, [:other_model])
    

    要合成,您可以使用此宏来实现此行为。

    defmodule MyApp.UtilFixture do
      defmacro merge_preload(origin, preload, assoc) do
        quote do
          unquote(origin) |>
            Map.merge(for p <- unquote(preload), unquote(assoc)[p], into: %{}, do: {p, unquote(assoc)[p]})
        end
      end
    end
    

    并在你所有的装置中使用它。

    def basic_model_fixture(attrs \\ %{}, preload \\ []) do
      assoc = %{other_model: other_model_fixture()}
      {:ok, basic_model} =
        attrs
        |> Enum.into(%{
          name: "some name",
          other_model_id: assoc.other_model.id
          })
        |> MyApp.BasicModel.create_basic_model()
    
      MyApp.UtilFixture.merge_preload(basic_model, preload, assoc)
    
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-29
      • 2021-01-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多