Как получить атрибут первой ассоциации has_many?

User has_many emails и Email имеет атрибут md5sum. Для данного пользователя @user я хочу отобразить изображение Gravatar в user#show.

Следующий код в шаблоне не работает:

<img src="http://www.gravatar.com/avatar/<%= @user.emails.first.md5sum %>" />

Как я могу получить md5sum из первых email для @user в шаблоне?

web/controllers/user_controller.ex

[...]
def show(conn, %{"id" => id}) do
  user = Repo.get!(User, id) |> Repo.preload([:emails])

  conn
  |> assign(:user, user)
  |> render("show.html")
end
[...]

web/models/user.ex

defmodule MyApp.User do
  use MyApp.Web, :model
  use Arc.Ecto.Model

  schema "users" do
    field :first_name, :string
    field :last_name, :string
    has_many :emails, MyApp.Email
[...]

web/models/email.ex

defmodule MyApp.Email do
  use MyApp.Web, :model

  schema "emails" do
    field :value, :string
    field :md5sum, :string
    belongs_to :user, MyApp.User
[...]

person wintermeyer    schedule 04.05.2016    source источник


Ответы (1)


emails будет списком адресов электронной почты, если таковые имеются.

Причина, по которой <img src="http://www.gravatar.com/avatar/<%= @user.emails.first.md5sum %>" /> не работает, заключается в том, что . используется для доступа к свойству на карте. emails — это список.

Вы можете использовать hd/1 для получения первый элемент списка:

<img src="http://www.gravatar.com/avatar/<%= hd(@user.emails).md5sum %>"  />

Это приведет к ошибке, если у пользователя нет связанных электронных писем.

Возможно, вам лучше определить функцию в своем представлении (или в другом модуле, который вы импортируете в свое представление):

def gravatar_url(user) do
  case user.emails do
    [email | _tail] -> "http://www.gravatar.com/avatar/#{email.md5sum}"
    _               -> "some-default-avatar"
  end
end

Затем вы можете использовать это в своем шаблоне:

<img src="<%= gravatar_url(@user) %>"  />
person Gazler    schedule 04.05.2016