first_or_create эквивалент в экто - PullRequest
1 голос
/ 21 января 2020

Настройка

A Феникс 1.4.11 Приложение с этим ресурсом:

mix phx.gen.html Institutions SchoolType school_types name

Проблема

Я хочу найти первый school_type с указанным именем. Если этого не существует, я хочу его создать. В ActiveRecord я бы использовал first_or_create.

У меня есть этот код, который работает. Но это выглядит не очень хорошо, и, вероятно, есть лучший, более чистый способ решения этой проблемы.

school_type_name = "Example"

if school_type_name != nil do
  query =
    from s in SchoolType,
      where: s.name == ^school_type_name,
      limit: 1

  case Repo.one(query) do
    nil ->
      {:ok, _school_type} =
        Institutions.create_school_type(%{
          name: school_type_name
        })

    _ ->
      nil
  end

  school_type = Repo.one(query)
end

Как мне решить эту проблему?

1 Ответ

1 голос
/ 21 января 2020

Как вы можете видеть из исходного кода, first_or_create выполняет два запроса к базе данных, если еще нет записи

# File activerecord/lib/active_record/relation.rb, line 103
def first_or_create(attributes = nil, &block) # :nodoc:
  first || create(attributes, &block)
end

Для имитации c этого поведения, вам следует избегать выполнения двух запросов для случая, когда запись уже существует.

school_type =
  case Repo.one(query) do
    nil ->
      {:ok, new} =
        Institutions.create_school_type(%{
          name: school_type_name
        })
      new

    found -> found # it’s already there!
  end
...