The Pragmatic Studio

Integrate Elm with Rails

May 12, 2017

Rails 5 makes it easier to sprinkle bits of Elm into your Rails app, or even to go all in with Elm! Here’s a quick rundown of how to start using Elm with Rails:

  1. First, create a new Rails 5.1+ app using the --webpack option:

    rails new elm_on_rails --webpack=elm

    In addition to generating all the standard Rails files and setting up Webpack, this also runs elm package install which downloads and installs the Elm packages elm-lang/core, elm-lang/html, and elm-lang/virtual-dom.

  2. Now pop open an editor in the application directory and navigate to the app/javascript directory. You’ll find a generated Main.elm file that displays a “Hello Elm!” greeting. And in the app/javascript/packs directory you’ll find a hello_elm.js file that embeds the output of Main.elm in the HTML document:

    import Elm from './Main'
    document.addEventListener('DOMContentLoaded', () => {
      const target = document.createElement('div')
  3. You need a page to display the Elm output. Any page will do since hello_elm.js embeds the output in the current document. Just to get a quick win, create an app/views/application/index.html.erb file. In that file, use the javascript_pack_tag helper to import the hello_elm.js file:

    <%= javascript_pack_tag "hello_elm" %>

    Then add a default route in config/routes.rb to that page:

    get '/', to: 'application#index'
  4. Game time! Fire up the Rails server:

    rails s

    In development, you also need to run a Webpack Dev Server in a separate terminal so that Elm files are automatically compiled as you make changes:

  5. Browse over to http://localhost:3000 and you should see the “Hello Elm!” greeting.

Embed a Countdown Timer

To kick things up a notch and see another example, here’s how to integrate the Elm countdown timer we build in our free Integrating Elm course:

  1. Paste CountdownTimer.elm into the app/javascript directory.

  2. Then paste the following code into a file named countdown_timer.js in the app/javascript/packs directory:

    import Elm from './CountdownTimer'
    document.addEventListener('DOMContentLoaded', () => {
      const target = document.getElementById('countdown-timer')
      Elm.CountdownTimer.embed(target, {
        deadline: "May 30 2020 14:05:00"

    Notice that the CountdownTimer Elm app is embedded in the DOM element with the id of countdown-timer.

  3. Import countdown_timer.js in your app/views/application/index.html.erb file and add an element with the id of countdown-timer:

    <%= javascript_pack_tag "countdown_timer" %>
    <div id="countdown-timer"></div>
  4. The countdown timer relies on a touch of style, so paste the following CSS into the app/assets/stylesheets/timer.css file:

    .time-period {
      display: inline-block;
      margin: 3rem 5px;
    .time-period .amount {
      font-size: 300%;
      padding: 30px;
      border-radius: 4px;
      background: #ccc;
    .time-period .period {
      display: block;
      color: #7B7D7D;
      text-transform: uppercase;
      text-align: center;
  5. Reload and the timer should start ticking down! You might need to restart the Webpack Dev Server.

Bonus: Use Foreman

In development, you can sidestep having to run the Webpack Dev Server separately by using the foreman gem.

  1. Add the gem to your Gemfile:

    gem 'foreman'

    And install it:

    bundle install
  2. Then create a Procfile in the top-level application directory with the following two lines:

    web: ./bin/rails server
    webpack: ./bin/webpack-dev-server
  3. Now you can start the Rails server and the Webpack Dev Server in one fell swoop using:

    foreman start

It’s never been easier to integrate Elm into a Rails app, and it will likley only get smoother from here!

Build a complete Elm web app from scratch!

Quickly get up to speed with Elm and functional programming as you build a reactive web app step-by-step in our 3.5-hour Building Web Apps With Elm course.