Reputation: 118
I want to attach a dynamic file in my email. I have the following code:
attachments["#{@company}likelist.xls"] = File.read("#{Rails.root}/app/views/products/like_list.xls.erb")
like_list.xls.erb
is a dynamic HTML table created by iterating a variable in Ruby. I used respond_to format.xls
to convert the like_list.html.erb
table to XLS, however, the attachment sent is empty as no Ruby code is executed. File.read
only reads static files.
like_list.xls.erb
looks like this:
<table border="1">
<thead>
<tr>
<th><%= t ('product_table.name')%></th>
<th><%= t ('product_table.code')%></th>
</tr>
</thead>
<tbody>
<% @like_list.each do |key, value| %>
<% value.each do |t| %>
<tr>
<td><%=t.code%></td>
<td><%=key%></td>
...
Is there any way I can attach a dynamic file in Rails 4?
Upvotes: 2
Views: 587
Reputation: 2464
I assume that's because you sending just a template. But you should construct a table first.
I don't know what data type is your @like_list
is, but let's say it is a Hash.
In that case you should build your attachment. Here is just an example that shows the basic approach:
# mailer
def table_deliver
to = "[email protected]"
from = "[email protected]"
subject = "Foo"
@company = "Ggl"
@like_list = { foo: 1,
bar: 2,
baz: 3 }
attachments["#{@company}likelist.xls"] = build_table(@like_list)
@body = "Mail body"
mail(to: to, from: from, subject: subject)
end
private
def build_table(data)
opts = OpenStruct.new(data)
template = ERB.new(File.read("#{Rails.root}/app/views/products/like_list.xls.erb"))
template.result(opts.instance_eval { binding })
end
# template
<table>
<thead>
<th>foo</th>
<th>bar</th>
</thead>
<tbody>
<% data.each do |k, v| %>
<tr>
<td><%= k %></td>
<td><%= v %></td>
</tr>
<% end %>
</tbody>
</table>
And the result in letter_opener:
Attachment opened in libre office
Hope that helps and feel free to ask some additional questions.
UPDATE
First you create an OpenStruct from your Hash params. Then create a new ERB class instance.
result
is a method of ERB class, that applies params to existing template.
binding
is an object that provides access to the instance methods and variables that are owned by another object.
More info here
instance_eval
is a Object method that evaluates a string containing Ruby source code, or the given block, within the context of the receiver (obj).
More info here
So, that code do the following
binding
object in context of template and assigns key-value pairs to the template.You could refer to this SO post for more details
Upvotes: 1