Rails: Rendering Dynamic SVG Images in respond_to

SVG is a vector image described in XML. This post shows how to to render SVG images inline with Rails.

This can be used, for example, in an html img tag to generate charts, icons and other dynamic graphics.

1. Register a new MIME type for the SVG response

# config/initializers/mime_types.rb
Mime::Type.register "image/svg+xml", :svg

2. Register a route to view your generated SVG

# config/routes.rb
get "icons/generate" => "icons#generate", format: :svg

3. Generate your SVG

Here I'm generating the SVG inline, but it could come from anywhere (e.g. model.as_svg).

Be sure to include the xml namespace (xmlns) in the svg tag, otherwise browsers just render the content as XML. This caught me out for a little while.

class IconsController < ApplicationController
  def generate
    svg = '<svg width="300px" height="300px" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>'
  end
end

4. Add your Respond Block

In your controller, add a respond to block, render the SVG.

def generate
# ...svg = ...

  respond_to do |format|
    format.svg { render inline: svg}
  end
end

To view the generated SVG, start the server and visit http://localhost:3000/icons/generate.svg