I have the following code in a Rails partial being used in some mailers but am not happy with my solution and have the feeling this is far from optimal.
I have an email which
From my mailer:
def the_email_i_am_sending(user, inquiry, params = {})
get_variables(inquiry) #This also provides access to my `@user` object
@contact_name = [params[:guest_last_name].to_s, " ", params[:guest_first_name].to_s].join
I always have @user
but on occasion a specific partner will call our API with additional params of [:guest_last_name]
and [:guest_first_name]
as defined above. This allows me to define @contact_name
as a separate instance variable.
When this is .present?
ie not nil, I want to render @contact_name
in a field on the email rather than the @user.login
that would pull from our DB.
My mailer view then uses the following code to decide which partial it will render.
<% if @contact_name.present? %>
<%= render 'meet_your_guest_v3', tujia_guest: @contact_name %>
<% else %>
<%= render 'meet_your_guest_v3' %>
<% end %>
My solution is then to utilise this code in the partial being rendered in the mailer. It seems a little verbose but I am unsure about the correct usage of local_assigns.has_key?
<% if local_assigns.has_key?(:partner_guest) %>
<%= partner_guest %> <p>(via our partner</p>
<% else %>
<%= @user.login %>
<% end %>
Is there a better way?
You should definitely follow the advice from @Jon regarding dealing with params in your controller/mailer. Additionally you should just pass @contact_name every time to the underlying partial, regardless if it is present or not, then check only where you want to render it, if it is present. This way you would skip one conditional:
#email_view.html.erb
render 'meet_your_guest_v3', parnter_guest: @contact_name
_contact_name.html.erb
<% partner_guest.present? %>
...
A further step could be using a special decorator object, which would deal with the presentation logick. It would check wether contact_name was provided from outside or from the model and render the desired html tag for the contact_name (or it could just return it as string). See following pseudocode using the draper gem:
class MyController < ApplicationController
def send_mail
@user = User.find(...).decorate(
contact_name: [params[:guest_last_name].to_s, " ", params[:guest_first_name].to_s].join
)
MyMailer.the_email_i_am_sending(@user)
end
end
class MyMailer < ApplicationMailer
def the_email_i_am_sending(user)
@user = user
mail(to: ..., subject: ...)
end
end
class UserDecorator < Draper::Decorator
def contact_name_tag
if (contact_name.present?)
h.content_tag(:div, contact_name)
else
h.content_tag(:div, user_name)
end
end
end
#email_view.html.erb
<%= @user.contact_name_tag %>
However if the presentation logic isn't very complicated, going with a couple conditionals and perhaps extracting them into basic rails helpers is fine and using a presenter may be an overkill
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.