call method from activemailer view - ruby-on-rails

Is there a way to call a method from the actionMailer html file the same way a view can call to a method in a controller?
ActionMailer:
class ModelEmailerMailer < ActionMailer::Base
helper :application
layout 'model_email'
def user_mailer(user)
...
mail(to: user.formatted_email, subject: "email subject")
end
def function_call(user_info)
....
return modified_user_info
end
helper_method :function_call
ActionMailer View file 'model_email':
...
user.each do |a|
modified_user_info = function_call(a)
end
...
right now I don't even get an error message. I get an empty email with the correct subject, but no body.
EDIT 1: If I can't place the function in the actionmailer, can I create and link a separate controller to the view?

Related

access "self" from view after sending mail (ruby on rails)

After a user signs up (Devise RegistrationController), I want to send them a welcome email.
Inside my User model, I created a function:
def send_welcome_email
UserMailer.welcome(self).deliver
end
Then I've added after_create :send_welcome_email
Inside the email view, I need to access variables.
<p><span><strong>Hi <%= self.name %>,</strong></span></p>
Returns an error:
undefined method `name' for #<#<Class:0x00007fa7d18e13b0>:0x00007fa7e4025358>
It makes sense that this would result in the error above, but I'm not sure how I can access variables from the model (that was just created).
I was following this asnwer: https://stackoverflow.com/a/17480095/9200273
Welcome method:
def welcome(user)
mail(
to: user.email,
subject: 'Welcome to Site!',
from: "support#site.com"
)
end
You can pass objects to the Mailer class using the with method like this:
UserMailer.with(user: self).welcome.deliver
Inside the UserMailer class:
def welcome_email
#user = params[:user]
...
end
In the view:
<%= #user.name %>
Reference: https://guides.rubyonrails.org/action_mailer_basics.html

Action Mailer 'undefined method `[]' for nil:NilClass'

Im getting an error when trying to send an email. Not to sure why but here is my code in my controller and mailer
Here is my controller code below
class Invitation::InvitesController < ApplicationController
def invite_provider
#patient = Patient.find_by_id(invite_params[:invitable_id])
recipient = params[:email]
InviteMailer.provider_invite(recipient).deliver_now
flash[:success] = "An email has been sent to"
redirect_back(fallback_location: root_path)
end
end
Here is my mailer code
class InviteMailer < ApplicationMailer
def provider_invite(recipient)
#recipient = recipient
mail(
to: recipient[:email],
subject: I18n.t('provider_invite_subject')
)
end
end
At the call to mail, in the to option, you're basically sending params[:email][:email]. I don't think that's what you want.
recipient = params[:email]
and then
to: recipient[:email],
You have called InviteMailer.provider_invite(recipient) where recipient is email inside controller.
You can change in controller,
InviteMailer.provider_invite(email: recipient)
and then,
class InviteMailer < ApplicationMailer
def provider_invite(attr)
#recipient = attr[:email]
mail(
to: #recipient,
subject: I18n.t('provider_invite_subject')
)
end
end
And error is due to your params o not have email key, so recipient is nil passed through controller

Mailer result as String?

In our custom sales app our users are able to send emails based on text partials they choose. We need to record the sent mails in an activity model. How do I get the mailer result as a string in order to save it?
Instead of calling the deliver method to send the mail, you can capture the email message by calling to_s. For example, if you have a mailer:
class MyMailer < ActionMailer::Base
default :from => "sender#me.com"
def my_email
mail(:to => "destination#you.com", :subject => "Mail Subject")
end
end
you would do
mail_content = MyMailer.my_email.to_s
May be you can using a mail observer like in the following example :
class MailObserver
def self.delivered_email(message)
test = Activty.create do |activity|
# etc.
end
end
end
Find here

Rails: Use URL Helper in Observer

I have an observer which looks like this:
class CommentObserver < ActiveRecord::Observer
include ActionView::Helpers::UrlHelper
def after_create(comment)
message = "#{link_to comment.user.full_name, user_path(comment.user)} commented on #{link_to 'your photo',photo_path(comment.photo)} of #{comment.photo.location(:min)}"
Notification.create(:user=>comment.photo.user,:message=>message)
end
end
Basically all I'm using it to do is create a simple notification message for a certain user when someone posts a comment on one of their photos.
This fails with an error message:
NoMethodError (undefined method `link_to' for #<CommentObserver:0x00000102fe9810>):
I would have expected including ActionView::Helpers::UrlHelper would solve that, but it seems to have no effect.
So, how can I include the URL helper in my observer, or else render this some other way? I would happily move the "message view" into a partial or something, but an observer has no associated views to move this to...
Why aren't you building the message when it's rendered out to the page and then caching it using something like this?
<% cache do %>
<%= render user.notifications %>
<% end %>
This would save you having to do a hack in the observer and would be more "standards compliant" in Rails.
To handle this type of thing, I made an AbstractController to generate the body of the email, then I pass that in as a variable to the mailer class:
class AbstractEmailController < AbstractController::Base
include AbstractController::Rendering
include AbstractController::Layouts
include AbstractController::Helpers
include AbstractController::Translation
include AbstractController::AssetPaths
include Rails.application.routes.url_helpers
include ActionView::Helpers::AssetTagHelper
# Uncomment if you want to use helpers
# defined in ApplicationHelper in your views
# helper ApplicationHelper
# Make sure your controller can find views
self.view_paths = "app/views"
self.assets_dir = '/app/public'
# You can define custom helper methods to be used in views here
# helper_method :current_admin
# def current_admin; nil; end
# for the requester to know that the acceptance email was sent
def generate_comment_notification(comment, host = ENV['RAILS_SERVER'])
render :partial => "photos/comment_notification", :locals => { :comment => comment, :host => host }
end
end
In my observer:
def after_create(comment)
email_body = AbstractEmailController.new.generate_comment_notification(comment)
MyMailer.new(comment.id, email_body)
end
So, it turns out this cannot be done for the same reason you can't use link_to in a mailer view. The observer has no information about the current request, and therefore cannot use the link helpers. You have to do it a different way.

Invoke action to send email in ruby on rails

I am attempting to send an email to the present borrower of a book. I've created an ActionMailer called ReturnRequestMailer which has a method called please_return.
class ReturnRequestMailer < ActionMailer::Base
def please_return(book_loan)
subject 'Book Return Request'
recipients book_loan.person.email
from 'andrew.steele#west.cmu.edu'
sent_on Time.now
body :book_loan => book_loan
end
end
I am attempting to call this method from an action inside of my BooksController
def request_return
#book = Book.find(params[:id])
ReturnRequestMailer.please_return(#book.current_loan)
end
Which I invoke from my books index with the following link_to (ignoring for the time being that doing this in this manner probably isn't the smartest permanent solution).
<%= link_to 'Request Return', {:action => 'request_return' , :id => book} %>
Everything links up correctly but I get a NoMethodError in BooksController#request_return stating that it cannot find the method please_return for ReturnRequestMailer. What is going on that is preventing the please_return method from being visible to the BooksController?
add a 'deliver_' in front of your method so it will be :
def request_return
#book = Book.find(params[:id])
ReturnRequestMailer.deliver_please_return(#book.current_loan)
end
You don't need to define 'deliver_please_return' method, The method_missing method in ActionMailer will know to call please_return.
The Mailer in rails is usually used like this:
class ReturnRequestMailer < ActionMailer::Base
def please_return(book_loan)
subject 'Book Return Request'
recipients book_loan.person.email
from 'andrew.steele#west.cmu.edu'
sent_on Time.now
body :book_loan => book_loan
end
end
Then in the controller out deliver_ in front of the method name and call it as a class Method:
def request_return
#book = Book.find(params[:id])
NewsletterMailer.deliver_please_return(#book.current_loan)
end
Looking at your code it looks like the please_return method has been called as a class method, but you have defined it as an instance method. (for more detail on this see To use self. or not.. in Rails )
class ReturnRequestMailer < ActionMailer::Base
def self.please_return(book_loan)
...
should fix it.
Note this won't actual make it send the email, but will stop the NoMethodFound error.
As nasmorn states, you need to call ReturnRequestMailer.deliver_please_return to have the mail delivered.

Resources