Search code examples
javascriptjqueryruby-on-railsajaxpolling

Ajax Partial Refresh by Polling in Rails 3, jQuery


Rails 3, JRuby

I recently took part in a quick crash course in jQuery that included a bit of ajax partial rendering. This got me thinking, could I use this to poll the Rails server using setInterval(), every x seconds to refresh a specific part of my page constantly?

The problem I'm having is how I could use the $.get() method to grab the url of the partial and reload it using load(). This is where the confusion starts- using Rails 3, I have a partial called "_microposts", rendered within a div with an 'id="gf" ' (gf meaning global feed). This happens on my Rails app homepage, so the url in this case would be "//localhost:8080/home" and not the url of the partial.

Here is my initial javascript/ jQuery

<script>
    $(document).ready(function() {      
        setInterval(function (e) {
            var url = $.get("<%= escape_javascript render :partial =>
               'microposts/micropost', :locals => {:microposts => @microposts }%>");

            $('#gf').html('loading...').load(url);          
        },10000);
    }); 
</script>

This looks wrong, and so far, just blanks out my _microposts partial after 10 seconds (so the setInterval is working, and it's definitely updating the correct area, just with a blank space!)

Edit: Thinking about my problem, I realised that this is similar to updating a partial from an event, such as clicking a button or something. The only real difference is the "event" that should trigger this the setInterval() function. So, my revised jQuery code is as follows:

<script>
    $(document).ready(function() {
        setInterval(function (e) {
            $('#gf').html("<%= escape_javascript render :partial =>
                'microposts/micropost', :locals => {:microposts => @microposts } %>")}, 
            10000);
    }); 
</script>

Unfortunately now, nothing seems to be happening from a user point of view, but the server is showing an ajax request every 10 seconds.

So why can't I poll for updates using ajax, and apply the changes to my _microposts partial? Is $.get the correct function to use in this case? What would the url for the load() method be when trying to re-load a partial?

Thanks,


Solution

  • Hopefully this will help anybody who wants to refresh a partial using ajax- especially if you're a beginner following Michael Hartl's tutorials to learn Ruby on Rails. Here's how I managed to solve my problem.

    Firstly, I created a separate .js.erb file in the micropost view folder called 'polling.js.erb' that will refresh the global feed partial.

    $('#gf').html("<%= escape_javascript render :partial =>
                                'microposts/micropost', :locals => {:microposts => @mps} %>"); 
    

    I needed to write a method in the micropost controller that will correspond with the above javascript- this essentially supplies the information needed to refresh the partial. It's basically a simplified version of my index method in the micropost controller and avoids executing the additional code that's not needed for the partial I want to refresh.

    def polling
        @mps = Micropost.all #add some paginate code if you wish
        @micropost = current_user.microposts.build(params[:micropost])                  
    end
    

    I then revised my javascript code, as I wanted to call the polling method every 5 seconds, loading the information specific to the current_user of my webapp.

    $(document).ready(function() {
        setInterval(function () {
                $.ajax('microposts/<%= current_user.id %>/polling');
        } , 5000);          
    }); 
    

    Finally, I updated my routes.rb file to allow a web browser to call my polling method, using a get request, without causing a routing error. I'm using a member do block because the request is passing the current_user id via the request.

    resources :microposts do
        member do
            post :polling
        end
    end