2015-04-27 3 views
8

Использует ли Phoenix Framework любые типы фильтров обратного вызова, например, найденные в Rails? Я знаю, что можно проверить набор изменений, но я ищу способы реализовать такие действия, как before_create, before_save и after_commit.Обратные вызовы Phoenix Framework

ответ

13

Ecto делает: https://hexdocs.pm/ecto/#!Ecto.Model.Callbacks.html

Они красивые отличаются от тех, Rails: они получают и должны вернуться и ревизии должны быть использованы для обеспечения согласованности данных (не использовать их для отправки по электронной почте, а что нет).

+0

страница говорит, что «Предупреждение: обратные вызовы Ecto устарели». Этот метод, вероятно, больше не рекомендуется – coderVishal

+0

Да, и они полностью удалены из Ecto 2.0. Вот сообщение в блоге, объясняющее некоторые решения: http://blog.plataformatec.com.br/2015/12/ecto-v1-1-released-and-ecto-v2-0-plans/ –

+1

Вот еще одна точка зрения (если вы родом из Rails): http://cloudless.pl/articles/ 11-model-callbacks-in-phoenix-ecto-and-rails –

11

Из Ecto 2.0 обратные вызовы были полностью удалены.

Итак, как обрабатывать обратные вызовы сейчас ?. Вот два способа:

Для обратных вызовов before_ вы можете использовать Changeset. Одна из причин обратных вызовов, которые были удалены из-за того, что многие разработчики полагались на обратные вызовы, во многих случаях, когда наборов изменений было бы достаточно. Так просто применить требуемую функцию к вашей ревизии,

def changeset(post, params \\ :empty) do 
    post 
    |> cast(params, @required_params, @optional_params) 
    |> validate_length(:title, min: 3) 
    |> validate_length(:metadata, min: 3) 
    |> implement_a_before_callback 
end 

def implement_a_before_callback(changeset) 
    #Apply required actions and return Changeset 
end 

Другим способу, заключается в операцию объединения несколько репо вместе с использованием Ecto.Multi. В документах

Ecto.Multi позволяет выполнять операции, которые должны выполняться совместно (в одной транзакции с базой данных), и дает возможность подвергать операции в очереди без их фактического выполнения. Каждой операции присваивается уникальное имя и будет идентифицировать его результат или поможет определить место сбоя в случае его возникновения. Итак, всякий раз, когда вы хотите, чтобы группа операций, связанных с данными, происходила сразу, вы могли использовать Multi, здесь могут быть заменены как обратные вызовы before_, так и after_.

Примером может быть

# In defmodule Service 
    def password_reset(account, params) do 
    Multi.new 
    |> Multi.update(:account, Account.password_reset_changeset(account, params)) 
    |> Multi.insert(:log, Log.password_reset_changeset(account, params)) 
    |> Multi.delete_all(:sessions, assoc(account, :sessions)) 
    end 

Выполнить это с помощью

result = Repo.transaction(Service.password_reset(account, params)) 

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

case result do 
    {:ok, %{account: account, log: log, sessions: sessions}} -> 
    # Operation was successful, perform actions like sending a mail 
    {:error, failed_operation, failed_value, changes_so_far} -> 
    # One of the operations failed. Raise error message 
end 

Источник:

+1

Вот так! Принятый ответ устарел. – LukeS