【问题标题】:Ecto preload if not nil如果不是 nil,则 Ecto 预加载
【发布时间】:2019-04-15 15:58:53
【问题描述】:

凤凰n00b在这里。

如果模型存在,我需要预加载关联。我写道:

model = Repo.get(Model, id)
|> Repo.preload([:asso1, :asso2, :asso3])

但是如果没有找到模型,它就会失败,因为Repo.preload 不能忍受接收 nil 作为第一个参数:

protocol Ecto.Queryable 没有为 nil 实现,给定的模块不存在。该协议适用于:Ecto.Query、Atom、Ecto.SubQuery、Tuple、BitString

凤凰实现这一目标的方法是什么?

我找到了一个

model = if model = Repo.get(Model, id) do
  Repo.preload(model, [:asso1, :asso2, :asso3])
end

丑。

谢谢

【问题讨论】:

  • 您的初始解决方案应该可以正常工作。如果您查看Ecto.Repo.Preload/3 docs,您会发现它采用nil 作为参数。你确定你传递了一个现有的Model 吗?您的错误似乎表明您像这样调用Repo.get...Repo.get(nil, id)。 (> 给定的模块不存在)
  • 你说得对,我不知道我是怎么弄糊涂的,但 MyApp.Repo.get(Vae.User, -1) |> MyApp.Repo.preload(:association) 有效 :)
  • 很高兴你能成功

标签: elixir phoenix-framework


【解决方案1】:

我刚刚尝试过:用相应的关联替换 Model 和 assoc,它可以工作。

model = Repo.get(Model, id)
|> Repo.preload([:asso1, :asso2, :asso3])

我建议你在Query 中尝试preload/3

model = Repo.one(from m in Model, where: [id: ^id], preload: [:assoc1, :assoc2])

【讨论】:

    【解决方案2】:

    我想我会:

    case Repo.get(Model, id) do
      nil -> {:error, :not_found}
      model -> {:ok, model |> Repo.preload([:asso1, :asso2, :asso3])}
    end
    

    并将其粘贴在应用程序其他部分使用的某些功能后面。话虽如此,我认为这更重要的是您的项目/团队的风格是否一致。

    【讨论】:

    • 好的,感谢您的解决方案。如果没有其他可用的,我会做类似的事情。没有任何safe_preload 方法,在nil 上什么都不做?另一个case这里是另一个级别的缩进...
    【解决方案3】:

    它发生了

    model = Repo.get(Model, id)
    |> Repo.preload([:asso1, :asso2, :asso3])
    

    即使modelnil 也有效。关于Model 模块的导入,我一定犯了一个错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多