1

I'm making a simple rails (3.2.11) demo that only i will be accessing. I have the following:

1) a Rails scaffold named Food

2) an android device that can call in to a custom route/controller that will then create a new Food. (Food.create...).

So, on my computer's browser, I load up http://myapp.com, which is hosting the rails app. Immediately, it loads up all foods because it's rendering foods#index. However, the moment i create a new Food by calling in from my android device, the browser page (on my computer) is still showing the old list of foods, even though the database knows there's a new food. (because at this point i still haven't refreshed the page)

How do i add a "listener/observer" to refresh the page automatically, when the database changes for the Food table? is this possible?

i'm NOT looking for <meta http-equiv="refresh" content="5"> as I would like to leave my computer's browser on for the entire 30 min demo.

=================

also, i haven't used rails in over 3 years, so if you are kind enough to answer, please explain it so that a beginner would understand? (explicit details are preferred)

David T.
  • 22,301
  • 23
  • 71
  • 123

3 Answers3

1

Have a look at EventSource or WebSockets for realtime development . There are also other alternatives like long polling. However, if you are adding a new food from the same page, you could easily catch that event and refresh the data.

plalx
  • 42,889
  • 6
  • 74
  • 90
  • would you be willing to explain with a little bit more detail? more specifically, how i can do it with rails or js? – David T. Aug 19 '13 at 04:51
  • @DavidT. There are plenty of examples on the web already. Have a look at https://github.com/DanKnox/websocket-rails perhaps. – plalx Aug 20 '13 at 16:33
1

I would suggest taking a look at Faye. There's an excellent Railscast about it that goes into detail about how exactly to get it set up.

jvperrin
  • 3,368
  • 1
  • 23
  • 33
1

In the past, a common option would be to use Juggernaut to push data from servers to clients. It was used even before websockets became widely used, but it has been recently deprecated in favor of HTML5 Server-Sent-Events (SSE). To use SSE, you would apply a client side listener like so:

var source = new EventSource('/stream');
source.addEventListener('message', function(e) {
  console.log('Received a message:', e.data);

  //fetch new data with AJAX, or reload
  location.reload();
});

Server side, there are many ways to send events. Using Cramp, sending an event is done like so (taken from documentation):

class TimeAction < Cramp::Action
  self.transport = :sse
  #set the transport to Server-Sent Event

  on_start :send_latest_time
  periodic_timer :send_latest_time, :every => 2

  def send_latest_time
    data = {'time' => Time.now.to_i}.to_json
    render data
  end
end

If you're using Sinatra, your code would look like this:

get '/stream', :provides => 'text/event-stream' do
  stream :keep_open do |out|
    connections << out
    out.callback { connections.delete(out) }
  end
end

Server sent events are supported in mostly any browser, except for Internet Explorer and Opera Mini, but there are a few fallbacks/polyfill libraries such as the one here or here (jQuery solution). Unlike websockets, they still use the HTTP protocol, but keep in mind that they are one-way, while websockets can be used for multidirectional communication. If you're curious about the differences between SSE and websockets, see here.

Community
  • 1
  • 1
hexacyanide
  • 88,222
  • 31
  • 159
  • 162