Eric Luo Eric Luo - 1 year ago 61
Ruby Question

How to attach dynamic file content in email

I want to attach a dynamic file in my email. I have the following code:

attachments["#{@company}likelist.xls"] ="#{Rails.root}/app/views/products/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
table to XLS, however, the attachment sent is empty as no Ruby code is executed.
only reads static files.

looks like this:

<table border="1">
<th><%= t ('')%></th>
<th><%= t ('product_table.code')%></th>
<% @like_list.each do |key, value| %>
<% value.each do |t| %>

Is there any way I can attach a dynamic file in Rails 4?

Answer Source

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 = ""
    from = ""
    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)


  def build_table(data)
    opts =
    template ="#{Rails.root}/app/views/products/like_list.xls.erb"))
    template.result(opts.instance_eval { binding })

# template

    <% data.each do |k, v| %>
        <td><%= k %></td>
        <td><%= v %></td>
    <% end %>

And the result in letter_opener:


Attachment opened in libre office


Hope that helps and feel free to ask some additional questions.


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

  • creates some struct with key-value pairs
  • creates new template
  • executes binding object in context of template and assigns key-value pairs to the template.

You could refer to this SO post for more details

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download