Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Repo module in my model file

In my Tag model code

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

Above code caused a error below.

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

Can I fix the error ?

The Tag model is nested tag model.

Tag can has parent tag.


Finaly code is below. This is work fine.

In model

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

In controller

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))
  //
  // ...
like image 712
2YY Avatar asked Nov 27 '15 16:11

2YY


1 Answers

You can't use the Repo variable as it isn't available in this module. You will need to alias it:

alias MyApp.Repo

In controllers this is handled for you in web.ex which gets called in your module with:

use MyApp.Web, :controller

However, I strongly suggest that you avoid using Repo in your model. Your models are meant to be pure, this means that they should not have side effects. Calling a function in your model should always have the same output for a particular input (idempotence).

In this example you could change the implementation of the function to:

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

You can call Repo.all in your controller and pass the tags through to the function.

If you have more complex behaviour, consider creating a TagService module which uses the function as well as calling the Repo.all

like image 116
Gazler Avatar answered Oct 18 '22 13:10

Gazler