Лучшие практики ActionMailer: вызов метода в модели или в контроллере? - PullRequest
21 голосов
/ 03 февраля 2009

Отправка электронного письма обычно вызывается после действия с моделью, но само электронное письмо является операцией просмотра. Я ищу, как вы думаете о том, какие вопросы нужно задать себе, чтобы определить, куда поместить вызов метода action mailer.

Я видел / использовал их:

  • В модельном методе - плохая связь связанных, но отдельных проблем?
  • В обратном вызове в модели (например, after_save) - наилучшее разделение, насколько я могу судить, исходя из моего текущего уровня знаний.
  • В действии контроллера - просто чувствует себя не так, но есть ли ситуации, в которых это было бы самым разумным способом структурировать код?

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

Ответы [ 4 ]

14 голосов
/ 24 сентября 2012

Поздний ответ, но я хочу рационализировать тему:

Обычно в веб-приложении вы хотите отправлять электронные письма либо в качестве прямой реакции на клиента. Или как фоновое задание, если мы говорим о рассылке / уведомлении.

Модель в основном представляет собой хранилище данных. Его логика должна включать обработку данных / связь с обработкой хранения данных. Поэтому вставлять логику, которая к ней не относится, немного сложно, а в большинстве случаев неправильно. Давайте рассмотрим пример: пользователь регистрирует аккаунт и должен получить подтверждение по электронной почте. В этом случае можно сказать, что подтверждение по электронной почте является прямым следствием создания новой учетной записи. Теперь вместо того, чтобы делать это в веб-приложении, попробуйте создать пользователя в консоли. Звучит неправильно, чтобы вызвать обратный вызов в этом случае, верно? Итак, опция обратного вызова поцарапана. Должны ли мы еще написать метод в модели? Что ж, если это прямое влияние действий / ввода пользователя, то оно должно оставаться в этом рабочем процессе. Я написал бы это в контроллере после того, как пользователь был успешно создан. Непосредственно. В любом случае, репликация этой логики в модели, вызываемой в контроллере, добавляет ненужную модульность и зависимость модели Active Record от Action Mailer. Попробуйте рассмотреть возможность совместного использования модели во многих приложениях, в которых некоторые из них не хотят использовать Action Mailer. По указанным причинам я придерживаюсь мнения, что почтовые вызовы должны быть там, где они имеют смысл, и обычно модель , а не это место. Попробуйте привести примеры, где это можно сделать.

4 голосов
/ 04 февраля 2009

Ну, зависит.

Я использовал все эти варианты и ваше мнение о том, «почему я должен поместить это куда?» это хорошо.

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

Иногда вы просто запускаете отчет; Там нет обновления ничего. В этом случае у меня обычно есть ресурс с действием index, который отправляет отчет.

Если почтовый ящик не имеет отношения к изменяемой модели, я мог бы увидеть его в обратном вызове. Я делаю это не очень часто. Я бы с большей вероятностью все же включил это в модель. Я сделал это, но не очень часто.

1 голос
/ 16 октября 2014

Я знаю, что это было давно, но лучшие практики никогда не умирают, верно? :)

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

Следовательно, по моему мнению, самый логичный способ отправить это:

  • в фоновом режиме (используя Sidekiq или delayed_job )
  • в методе обратного вызова: «эй, это действие успешно выполнено, может быть, мы можем рассказать миру сейчас?»

Проблема в Rails заключается в том, что обратных вызовов не так много (как, например, в JS): лично я считаю грязным иметь такой код:

after_save :callback

def callback
  if test_that_is_true_once_in_the_objects_life
    Mailer.send_email()
  end
end

Итак, если вы действительно хотите мыслить как программист , идея будет заключаться в том, чтобы настроить некоторую систему обратного вызова в вашем приложении.

Например.

def run_with_callback(action, callback_name)
  if send(action)
    delay.send(callback_name)
  end
end

Или даже создание системы событий в вашем приложении было бы достойным решением.

Но, в конце концов, эти решения довольно дорогие по времени, поэтому люди в конечном итоге пишут его после действия

def activate
  [...]
  user.save
  Mailer.send_mail
  respond_to 
  [...]
end

, который является наиболее близким способом к обратному вызову в синхронном программировании и приводит к тому, что Mailers вызывает везде (в Model и Controller).

0 голосов
/ 20 февраля 2018

Существует несколько причин, по которым контроллеры являются хорошим местом для почтовых программ:

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