Rails4.0.0.beta1 + ActionController::Live + JavaScript EventSource

* [Is it live? | Tenderlovemaking](http://tenderlovemaking.com/2012/07/30/is-it-live.html)
* [tenderlove/reloader · GitHub](https://github.com/tenderlove/reloader)

----

app/controllers/progress_controller.rb

```rb
require 'reloader/sse'

class ProgressController < ApplicationController
  include ActionController::Live

  def index
    # SSE expects the `text/event-stream` content type
    response.headers['Content-Type'] = 'text/event-stream'

    sse = Reloader::SSE.new(response.stream)

    begin
      total = 0

      (0..100).step(10).each{ |i|
        puts "[ #{i} ]"
        sse.write( "#{Time.now.strftime("%Y/%m/%d %H:%M:%S")}" + " - #{i}" )
        total += i
        sleep( rand(1..3) )
      }

      puts "[ total : #{total} ]"

      sse.write( "#{Time.now.strftime("%Y/%m/%d %H:%M:%S")}" + " - #{total}", event: 'refresh' )

      # 接続終了送信
#      sse.write("stream_end")
    rescue IOError
      # When the client disconnects, we'll get an IOError on write
    ensure
      sse.close
    end
  end

  def show
  end
end
```

lib/reloader/sse.rb

```rb
require 'json'

module Reloader
  class SSE
    def initialize io
      @io = io
    end

    def write object, options = {}
      options.each do |k,v|
        @io.write "#{k}: #{v}\n"
      end
#      @io.write "data: #{JSON.dump(object)}\n\n"
      @io.write "data: #{object}\n\n"
    end

    def close
      @io.close
    end
  end
end
```

app/views/progress/show.html.erb

```html
<h1>progress#show</h1>

<h3>Total</h3>

<div id="refresh"></div>

<hr />

<h3>Progress</h3>

<div id="progress"></div>

<script type="text/javascript">
  jQuery(document).ready(function() {
    setTimeout(function() {
      // 接続開始
      var source = new EventSource('/progress/index');

      // サーバー側イベントの共通ハンドラを定義
      function eventLogger(event){
        $("#progress").prepend(event.data + "<br>");

        // 接続終了判定
        if (event.data == 'stream_end') { source.close() };
      }

      // messageイベントのハンドラを設定
      source.onmessage = eventLogger;
    }, 10);
  });
</script>

<script type="text/javascript">
  jQuery(document).ready(function() {
    setTimeout(function() {
      var source = new EventSource('/progress/index');
      source.addEventListener('refresh', function(e) {
        $("#refresh").prepend(event.data + "<br>");
        // window.location.reload();

        // 接続終了判定
        if (event.data == 'stream_end') { source.close() };
      });
    }, 20);
  });
</script>
```

config/routes.rb

```rb
  get 'progress/index'
  get 'progress/show'
```

Gemfile

```rb
gem "puma"
```

```
bundle install
```

```
rails s puma
```

http://0.0.0.0:3000/progress/show

### on Heroku

config/environments/production.rb

```rb
  # Disable Rails's static asset server (Apache or nginx will already do this).
#  config.serve_static_assets = false
```

Procfile

```
web: bundle exec rails s puma -p $PORT -e $RACK_ENV
```

```
git init && git add . && git commit -m "First commit"
```

```
heroku create rails4sample
```

```
git push heroku master
```

http://rails4sample.herokuapp.com/progress/show

----

* [shu0115/rails4sample · GitHub](https://github.com/shu0115/rails4sample)