0

I have a table on my view which I wish to auto-refresh every 60s. I followed the answer to this question to achieve that. In my table, I am displaying data from the variable @available_posts_data below.

So I have a Javascript which does this:

(document).ready(function () {
    setInterval(refreshPartial, 60000);

});

function refreshPartial() {
  $.ajax({
    url: "posts/refresh_part"
 });
}

And then, in my Posts controller I have these methods:

def home    
  @posts = Post.order(:id)
  @available_posts_data = get_available_posts_data()
end

#method to refresh the tables of posts and the data.
def refresh_part
  #get updated data based on posts
  @available_posts_data = get_available_posts_data()
  respond_to do |format|
    format.js
  end
end

private 
def get_available_posts_data()
   #this method does something with @posts and returns an array of updated data.
   .
   .
   .
end

Now, with the above, after 60s and a refresh, I found that my table became EMPTY.

Turns out method get_available_posts_data() in refresh_part() was returning me an empty array because @post was empty! In order for it to work properly for me, I had to modify the refresh_part as below:

def refresh_part
  #re-query for the @post variable!
  @posts = Post.order(:id)
  @available_posts_data = get_available_posts_data()
  respond_to do |format|
    format.js
  end
end

Why did I need to re-set the instance variable @post? I was kind of expecting that the Ajax request to the posts/refresh_part url would be point back to the same instance of Post controller, and @posts should be ready for me to use since the home function would have already set it once.

It seems to be something simple that I am missing here... Would having @post to be class variable @@post be better in this case?

Community
  • 1
  • 1
evkwan
  • 693
  • 3
  • 9
  • 17

1 Answers1

0

You've misunderstood instance variables somewhat I think, they don't persist over multiple requests - each request to the Posts controller will create a new set of instance variables.

So, it does need to be set again but to remove duplication you could add a before filter:

class PostsController < ApplicationController
  before_action :find_post

  def home 
   #code
  end

  def refresh_part
   #code
  end

  private

  def get_available_posts_data()
   #code
  end

  def find_post
    @post = Post.order(:id)
  end

The @post would then be available in all functions in the controller. If you add more functions to the class but only want it for certain ones, you could do:

before_action :find_post, only: [:home, :refresh_part]
RichardAE
  • 2,945
  • 1
  • 17
  • 20
  • Hi, thanks for the confirmation. I'm still new with rails, and really thought that only one instance of a controller would be instantiated each time the app runs. – evkwan Feb 04 '16 at 17:42