如何在我的模型文件中使用Repo模块

时间:2015-11-27 16:59:08

标签: elixir phoenix-framework ecto

在我的标记模型代码

schema "tags" do
  field :name, :string
  field :parent, :integer # parent tag id
  timestamps
end

def add_error_when_not_exists_tag_id(changeset, params) do
  tags = Repo.all(Tag)
  is_exists_tag_id = Enum.reduce(tags, fn(x, acc) -> acc || (x.id === params.parent) end)
  if is_exists_tag_id, do: changeset, else: add_error(changeset, :parent, "not exists parent!")
end

以上代码导致以下错误。

(UndefinedFunctionError) undefined function: Repo.all/1 (module Repo is not available)

我可以修复错误吗?

标记模型是嵌套标记模型。

标签可以有父标签。

最终代码如下。这很好。

在模型中

def add_error_when_not_exists_tag_id(changeset, params, tags) do
  is_exists_tag_id = Enum.reduce(tags, false, fn(x, acc) -> acc || (Integer.to_string(x.id) === params["parent"]) end)
  if is_exists_tag_id, do: changeset, else: add_error(changeset, :parent, "The tag is not exists.")
end

在控制器中

def create(conn, %{"tag" => tag_params}) do
  changeset = Tag.changeset(%Tag{}, tag_params)
  |> Tag.add_error_when_not_exists_tag_id(tag_params, Repo.all(Tag))
  //
  // ...

1 个答案:

答案 0 :(得分:20)

您无法使用Repo变量,因为此模块中无法使用该变量。你需要别名:

alias MyApp.Repo

在控制器中,这将在web.ex中为您处理,在您的模块中调用:

use MyApp.Web, :controller

但是,强烈建议您避免在模型中使用Repo。你的模型是纯粹的,这意味着它们不应该有副作用。调用模型中的函数应始终为特定输入(幂等)提供相同的输出。

在此示例中,您可以将函数的实现更改为:

def add_error_when_not_exists_tag_id(changeset, params, tags) do
  is_exists_tag_id = Enum.reduce(tags, fn(x, acc) -> acc || (x.id === params.parent) end)
  if is_exists_tag_id, do: changeset, else: add_error(changeset, :parent, "not exists parent!")
end

您可以在控制器中调用Repo.all并将标签传递给该功能。

如果您有更复杂的行为,请考虑创建一个TagService模块,该模块使用该功能并调用Repo.all