I know I could define instance variables e.g:
def user_register(username, email)
#username = username
#email = email
mail(:to => email, :subject => "Welcome!", :template_name => "reg_#{I18n.locale}")
end
But, is there a way to use local variables instead, just like passing :locals to partials?
As ronalchn pointed out, it's the render that has :locals, not the mail method. So, you need a direct access to the render method in order to pass the locals.
You can give a block to the mail and that way gain access to the render method, something like this:
mail(to: "your_mail#example.com", subject: "Test passing locals to view from mailer") do |format|
format.html {
render locals: { recipient_name: "John D." }
}
end
And now you should be able to use "Hello <%= recipient_name %>"
All options available in the mail method can be found at http://api.rubyonrails.org/classes/ActionMailer/Base.html#method-i-mail.
We know that render has a :locals option. However we can see that there is no :locals option available for mail. Therefore, no, there is no better way than to use instance variables (unless you want to use something hideous like globals or persistent database objects - don't do this).
Instance variables are what you are meant to use.
In Rails 5, you simply have to define instance variables using # in your method. You no longer have access to the locals property for this purpose.
class UserMailer < ApplicationMailer
def welcome_email(user_id:, to_email:, user_full_name:, token:)
# Mail template variables
#user = User.find_by(id: user_id)
#token = token
mail(:to => to_email,
:subject => MAILER_SUBJECTS_WELCOME,
:template_path => "user_mailer",
:template_name => "welcome_email")
end
end
Then you can just access them in your email template using <%= #user %> and <%= #token %>
You can actually use the locals option with mail, it's just a bit confusing and inconsistent as to how.
Once you use :locals you can then access these locals in the mail template using instance variables, e.g.
:locals => { :name => 'Jane' }
and then in the template
Dear <%= #name %>,
Related
I would like to use an instance or variable like below in the mailer subject.
So I would like to get the user name or some other user detail in the subject, I tried several thing but I receive an error every time. I can't find documentation about this either.
mail(:to => "test#gmail, :subject => "current_user.name") or "<%= current_user.name %>"
class PositionMailer < ActionMailer::Base
default from: "test#gmail.com"
layout 'mailer'
def general_message(position, barge_name)
#position = position
#barge_name = barge_name
mail(:to => "1234#gmail.com, :subject => "#{barge_name}")
end
end
controller
def create
#position = Position.new(position_params)
if #position.save!
redirect_to #position
PositionMailer.general_message(#position, #barge_name).deliver
To pass a variable inside quotes you need to do it like this "#{variable.value}
:subject => "#{current_user.name}"
should do it if it has access to current_user
You will have to pass current_user to the mailer along with the position value.
So wherever you are calling that from add current_user, probably looks something like this.
PositionMailer.general_message(position, current_user).deliver
I would like to send what is normally a view as the body of an email.
Whats the simplest way to do this?
eg: I have pages/reports.html.erb and I want to send the page that you'd see if you visited that path as the body of an email.
Is there some way to take the html that is rendered and assign it to the body variable of an email?
Additionally, I'd like to include the PDF version as an attachment. (I'm using wicked_pdf)
def reports
#email = params[:email]
#something here?
respond_to do |format|
format.html
format.pdf do
render :pdf => "usage_report"
end
end
end
note: I'm using rails 3.1 with mongoid 2 for the DB and sendgrid on heroku if that helps
EDIT: What I ended up doing:
replace #something here? with:
email_obj = {}
email_obj.to = params[:email]
email_obj.from = 'reports#company.com'
email_obj.subject = 'Report'
email_obj.body = render_to_string(:template => "pages/reports", :layout => false)
ReportsMailer.deliver_report(email_obj).deliver
and in the mailer class mailers/reports_mailer.rb
class ReportsMailer < ActionMailer::Base
default from: "from#example.com"
def deliver_report(email)
#email = email
mail( :to => #email.to,
:subject => #email.subject,
:from => #email.from)
end
end
and in reports_mailer/deliver_report.html.erb
<%= render :inline => #email.body %>
The rails mailer views are stored in a sub folder in views by the name of the mailer just like controller views. It is hard to say if this will work completely for you not knowing what the view/controller for that method looks like but what you could do is take the rendering for that page and turn it into a partial which you can then render in both the controller view and the mailer view as such:
given a partial: _my_partial.html.erb
within the views:
render "my_partial"
Using the partial you can even pass any variable that would be necessary for the view to be rendered to it with:
render "my_partial", :variable => variable
Update:
This may be of interest as well: Rendering a Rails view to string for email
I am a Rails noob and have a problem sending an email from a show page. There are several contact form tutorials out there but I cannot find one where I send an email from a page like a 'show' page. I have big errors in my routes I believe. In the model I state that Users have several Promotions and on the promotions show page I want to allow the current_user to send an email to #user.
here is app/mailers/quote_mailer.rb
class QuoteMailer < ActionMailer::Base
default :from => "tim#example.com"
def quote_mail(promotion)
#user = user
mail(:to => user.email, :subject => "You have an inquiry homeboy!")
end
end
In promotions_controller I put this action which I think might be wrong:
def quotedeliver
QuoteMailer.quote_mail.deliver
flash[:notice] = 'report sent!'
redirect_to root_path # or wherever
end
Here is the form that I use to send the email (the :url is probably wrong but I dont know how it should look)
<%= form_for quote_mail, :url => quotedeliver_promotion_path(promotion), :html => {:method => :put } do |f| %>
<%= f.text_area :body %>
<%= f.submit %>
<% end %>
I would love some help with this. I cannot find anything like it on stackoverflow, I have been trying for days. Thank you!
You are probably missing the route in config/routes.rb
you can define it like
post '/quotedeliver_promotion' => 'promotions#quotedeliver', :as => quotedeliver_promotion
Note that quotedeliver has to be rewritten quote_deliver to follow ruby syntax conventions. When you call
QuoteMailer.quote_mail.deliver
You are not giving the parameter, so try this
QuoteMailer.quote_mail(current_user).deliver
And change your method with
def quote_mail(user)
mail ....
end
and you are all good
There are some excellent screen casts (through Railscasts) regarding sending e-mail http://railscasts.com/?tag_id=28.
One last thing, do not attach your mail sending method to a show action (if you are doing currently), the reason is show action is only for view something and users might be refreshing that page, So if you attach a mailer to that, mails might go out for each refresh.
def quote_mail(promotion)
#user = user
mail(:to => user.email, :subject => "You have an inquiry homeboy!")
end
from where you are access user variable, it should be promotion i think.
I've just updated to Rails 2.3.11. In an earlier version I could write the following
render :file=>'console/users/show.html.erb', :locals => {:#user => #users.first}
which no longer works, instead I need to write
render :file=>'console/users/show.html.erb', :locals => {:user => #users.first}
which means to access the user in the file I would use 'user' but in the file I would like to use the instance variable #user as this same show file is called from the controller and passes #user
Any tips?
Thanks
Set #user before calling render:
#user = #users.first
render :file=>'console/users/show.html.erb'
The :locals option should only be used if you are passing local variables through.
I am trying to use an existing partial in an actionmailer template, something like..
My merchant_offer.txt.html.erb
<%= render :partial => "offers/offer", :locals => {:offer => #offer} %>
Notifier.rb (my mailer class):
def merchant_offer(offer)
subject "New Offer from #{offer.merchant.name}"
from "xxx#gmail.com"
recipients xxx#
sent_on Time.now
body :offer => offer
end
The offer partial in in another view folder called offers
But it throws a missing tempalate error.
Is there a way to re-use existing view partial in in mailer tempalates?
Thanks
You should be able to render partial from mailer templates.
I believe the error is in your merchant_offer view. Try renaming 'merchant_offer.txt.html.erb' to 'merchant_offer.html.erb'