Comment utiliser mes assistants de vue dans mes vues ActionMailer?

227

Je souhaite utiliser les méthodes que j'ai définies app/helpers/annotations_helper.rbdans mes vues ReportMailer ( app/views/report_mailer/usage_report.text.html.erb). Comment puis-je faire cela?

Sur la base de ce guide, il semble que la add_template_helper(helper_module)méthode puisse faire ce que je veux, mais je ne sais pas comment l'utiliser.

(BTW, y a-t-il une raison pour laquelle vous avez accès à un ensemble différent d'aides dans les vues des expéditeurs?

Tom Lehman
la source

Réponses:

324

Dans la classe de messagerie que vous utilisez pour gérer vos e-mails:

class ReportMailer < ActionMailer::Base
  add_template_helper(AnnotationsHelper)

  ...
end
Mark Connell
la source
4
Ne fonctionne pas pour moi dans ce cas (Rails 3.2.8): J'ai une méthode définie dans ApplicationController et j'en fais un assistant par helper_method: my_helper_wannabe, mais la méthode "my_helper_wannabe" n'est pas disponible dans mailer.
Giang Nguyen
Voir la réponse de Duke ci-dessous pour savoir comment gérer Rails 3.
Chris Peters
Fonctionne dans Rails 3.2.11
Jan
1
Je pensais que ceux-ci étaient censés être automatiquement inclus dans Rails 4? guides.rubyonrails.org/…
gabeodess
6
Ceci est une réponse ancienne mais juste pour dire que cela a fonctionné dans Rails 5.2
Archonic
158

Dans Rails 3, utilisez simplement la méthode d'assistance en haut de votre classe ActionMailer:

helper :mail   # loads app/helpers/mail_helper.rb & includes MailHelper

Je viens de passer dans un bloc, car je n'en ai besoin que dans le seul Mailer:

helper do
  def host_url_for(url_path)
    root_url.chop + url_path
  end
end

(assurez-vous de définir config.action_mailer.default_url_options.)

(et si vous utilisez url_for, assurez-vous de transmettre: only_path => false)

Duc
la source
3
Cela fonctionne, mais il est gênant de spécifier à nouveau les assistants déjà définis dans ApplicationController pour les classes ActionMailer individuelles. ActionMailer étend ActionController afin qu'ils proviennent d'une hiérarchie commune. Plus d'un commentaire sur Rails que votre solution ...
robbie613
3
Et si l'assistant est dans un espace de noms, vous pouvez le fairehelper :'namespace/mail'
Jonathon Batson
si l'assistant est dans un espace de noms, il accepte également juste une chaîne (au lieu d'un symbole)helper 'namespace/mail'
Pwnrar
2
Fonctionne sur Rails 5.2!
RousseauAlexandre
28

Pour tous les expéditeurs dans Rails 3 (configuration de l'aide "application"):

# config/application.rb:
...
config.to_prepare do
  ActionMailer::Base.helper "application"
end
Edison Machado
la source
La meilleure réponse pour les partiels de messagerie partagés. Merci!
Alexey Shein
2
PAS vrai - helper :applicationfonctionne très bien dans Rails 4.2.1.
steakchaser
Fonctionne très bien, même pour ses propres modèles d'e-mail devise. helper :applicationne fonctionne pas dans ce cas.
Sven R.
1
ne fonctionne pas pour 4.2.5.1 - include ApplicationHelpera fonctionné
daslicious
23

Pour Ruby on Rails 4, j'ai dû faire 2 choses:

(1) Comme Duke l'a déjà dit, si l'aide que vous souhaitez ajouter est UsersHelperpar exemple, alors ajoutez

helper :users

à la ActionMailerclasse dérivée (par exemple app/mailers/user_mailer.rb)

(2) Après cela, j'ai eu une nouvelle erreur:

ActionView::Template::Error (Missing host to link to! Please provide the :host
parameter, set default_url_options[:host], or set :only_path to true)

Pour résoudre ce problème, ajoutez la ligne

config.action_mailer.default_url_options = { :host => 'localhost' }

à chacun des config/environments/*.rbfichiers. Pour config/environments/production.rb, remplacez localhostpar un hôte plus approprié pour les URL générées par l'aide à la production.


Q: Pour le numéro 2, pourquoi la vue de messagerie a-t-elle besoin de ces informations et les vues normales non?

R: Parce que les vues régulières n'ont pas besoin de connaître host, car tous les liens générés sont servis depuis l'hôte vers lequel ils se connectent. Les liens qui apparaissent dans les e-mails ne sont pas servis à partir du même hôte (sauf si vous vous connectez à hotmail.comou gmail.com, etc.)

Mat
la source
Et les noms composés? User::ComposedHelper
Cyril Duchon-Doris
20

Vous pouvez simplement ajouter votre mailer

helper :application

ou l'aide dont vous avez besoin

user1136228
la source
4
ceci est un doublon d'une réponse antérieure - @Shevaun
robbie613
1
Fonctionne sur Rails 5.2!
RousseauAlexandre
17

(C'est une vieille question mais Rails a évolué, donc je partage ce qui fonctionne pour moi dans Rails 5.2.)

En règle générale, vous souhaiterez peut-être utiliser un assistant d'affichage personnalisé pour afficher la ligne d'objet d'un e-mail ainsi que le code HTML. Dans le cas où l'assistant de vue se trouve dans app / helpers / application_helper.rb comme suit:

module ApplicationHelper

  def mydate(time, timezone)
    time.in_time_zone(timezone).strftime("%A %-d %B %Y")
  end

end

Je peux créer une ligne d'objet et un modèle d'e-mail dynamiques qui utilisent tous deux l'aide, mais je dois dire à Rails d'utiliser explicitement ApplicationHelper dans apps / mailer / user_mailer.rb de deux manières différentes, comme vous pouvez le voir dans les deuxième et troisième lignes ici :

class UserMailer < ApplicationMailer

  include ApplicationHelper  # This enables me to use mydate in the subject line
  helper :application  # This enables me to use mydate in the email template (party_thanks.html.erb)

  def party_thanks
    @party = params[:party]
    mail(to: '[email protected]',
    subject: "Thanks for coming on #{mydate(@party.created_at, @party.timezone)}")
  end

end

Je dois mentionner que ces deux lignes fonctionnent tout aussi bien, alors choisissez l'une ou l'autre:

helper :application

add_template_helper(ApplicationHelper)

FWIW, le modèle d'e-mail à app / views / user_mailer / party_thanks.html.erb ressemble à ceci:

<p>
  Thanks for coming on <%= mydate(@party.created_at, @party.timezone) %>
</p>

Et le contrôleur app / controller / party_controller.rb ressemble à ceci

class PartyController < ApplicationController
  ...
  def create
    ...
    UserMailer.with(party: @party).party_thanks.deliver_later
    ...
  end
end

Je dois être d'accord avec OP (@Tom Lehman) et @gabeodess que tout cela semble assez compliqué compte tenu de https://guides.rubyonrails.org/action_mailer_basics.html#using-action-mailer-helpers alors peut-être que je manque quelque chose .. .

MSC
la source
5

dans mon cas pour Rails4, j'aime ça:

# app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
  add_template_helper ApplicationHelper
  ...
end

et

# app/mailers/user_mailer.rb
class AccountMailer < ApplicationMailer
  def some_method(x, y)
  end
end

afin que vous n'ayez pas à spécifier add_template_helperpartout.

Yoshi
la source