Отображение полного имени (имя фамилия) в индексе / показать шаблон

#elixir #phoenix-framework #ecto

#elixir #phoenix-framework #ecto

Вопрос:

Я новичок в Phoenix и Elixir, но я очень стараюсь его изучить. Это может быть глупо простой вопрос, но я не знаю, как отобразить полное имя автора книги на странице index / show книги.

Вот мой запрос в inventory / book.ex

 def get_author_full_name(author) do
  from b in "books",
  join: a in "authors",
  on: b.author_id == a.id,
  where: a.id == ^author,
  select: %{id: a.id, name: concat(a.first_name, ' ', a.last_name)}
end
  

Пользовательский SQL:

 defmodule CustomSQLFunctions do
  defmacro concat(left, mid, right) do
    quote do
      fragment("concat(?, ?, ?)", unquote(left), unquote(mid), unquote(right))
    end
  end
end
  

И в inventory.ex

 def display_author_full_name do
  Author
  |> Author.get_author_full_name()
  |> Repo.all()
end
  

В book_controller.ex

 plug :load_author_full_name when action in [:index, :show]
defp load_author_full_name(conn, _) do
  assign(conn, :books, Bookstore.Inventory.display_author_full_name ())
end
  

Я следовал инструкциям из книги Programming Phoenix 1.4, чтобы отобразить выпадающий список категорий с некоторыми небольшими изменениями в соответствии с моим случаем. Может кто-нибудь подсказать мне, как отобразить полное имя автора книги? Я не знаю, написал ли я соответствующий код обращения и что поместить на страницы просмотра и индексирования / показа.

Комментарии:

1. Просто чтобы уточнить: есть ли причина, по которой вы не хотите использовать отдельные переменные для имени и фамилии? Другими словами, почему бы просто не выполнить «конкатенацию» на уровне представления?

2. Также… Меня смущает ваша get_author_full_name/1 функция… Я не понимаю, почему вы присоединяетесь к books таблице, когда все, что вы хотите получить, это имя автора — я не думаю, что требуется какое-либо объединение. Имя функции вводит в заблуждение: вы извлекаете список авторов (или, возможно, список авторов, объединенных с данными книги). Вы могли бы просто положиться на preload опцию, чтобы избежать проблемы N 1 — предполагая, что у вас есть схемы для Book и Author , это может выглядеть так from(b in Book, preload: [:authors]) |> Repo.all()

3. Спасибо за ваш ответ! Я новичок в elixir и phoenix, и я подумал, что было бы неплохо сделать что-то «похожее» на то, что есть в книге. Я придумал что-то вроде: <% fullname = book.author.first_name <> " " <> book.author.last_name %> в index / show.html.eex, а затем: <td><%= fullname %></td> . Но я думаю, это не идеальное решение.

4. Здорово пробовать — вот как ты учишься! В этом случае вы также могли бы сделать <td><%= book.author.first_name %> <%= book.author.last_name %></td> . Однако будут случаи, когда вам нужно будет где-то применить некоторую бизнес-логику, чтобы последовательно изменять данные, прежде чем использовать их в представлении (например, что-то более сложное, чем конкатенация). Часто для этого используется выделенный модуль или функция — некоторые языки делают подобные вещи в «классах обслуживания»; Phoenix использует «контексты» как место, где такие манипуляции могут происходить до отправки данных в представление.

5. Я серьезно отнесся к вашему вопросу и попробовал закодировать его в представлении. Вот результат. У book_view.ex меня есть: def full_name(%Writers.Author{first_name: first_name, last_name: last_name}) do [first_name, last_name] |> Enum.reject(amp;(amp;1 == "")) |> Enum.join(" ") end и в index.html.eex: <td><%= full_name(book.author) %></td>