When Rails introduced remote:true option for links (AJAX requests) I changed my view on how to handle javascript on my websites. I'm playing with streaming in Rails 4.1 (ActionController::Live) and I realized that a similar solution is needed for handling server events (EventSource).
Case:
Solution:
Let's forget about live updates for a moment and imagine I would add a form above the list where I could write a tweet and post it to the server (POST /tweets) with <form ... remote:true>. In this case the create.js action view will execute a javascript code (that I would define) for adding a new tweet to the list (as described here:
http://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html#reporting-an-issue). The logic for live updates should be very similar. The "only difference" in this case is that the create.js action is executed multiple times without refreshing the page.
I built the server events logic similar to railscasts episode 401. When a new tweet is created send the create.js code to $redis channel, the content is sent to a client over /server_events controller-action and the code is evaluate with jquery.
# SERVER
GET /server_events
def server_events
response.headers["Content-Type"] = "text/event-stream"
redis = Redis.new
redis.psubscribe("tweets.create") do |on|
on.pmessage do |pattern, event, data|
response.stream.write("id: #{Time.now.to_i}\n")
response.stream.write("event: #{event}\n")
response.stream.write("data: #{data}\n\n")
end
end
rescue IOError
ensure
redis.quit
response.stream.close
end
POST /tweets
def create
...
$redis.publish("tweets.create", render_to_string("tweets/create.js", layout: false, item: @tweet).to_json)
...
end
# CLIENT
sse = new EventSource('/server_events')
sse.addEventListener 'tweets.create', (e) ->
$.globalEval($.parseJSON(e.data))
What do you think? Suggestions?