Tanmay Das Tanmay Das - 7 months ago 16
HTML Question

Refresh a div containing a helper function and a javascript function automatically in rails

I want to notify the user if there is a new mail -> so I created a new

<div>
in which I call a helper function and display the notification using notify js function. It is working correctly as is BUT if I try to run it say every 3 min. it doesn't respond... please provide some guidance.... thanks in advance.

MY CODE:


div in application.html.erb containing the partial for the div


<div class="recentHashMailNotify" ><%= render partial: 'layouts/recentHashMailNotify' %></div>



The JS function to load the controller


<script type="text/javascript">
$(document).ready(function() {setInterval(function() {
$('.recentHashMailNotify').load('/application_controller/recentHashMailNotify');
}, 2000);
});
</script>



The action in the controller


def recentHashMailNotify
render :partial => "layouts/recentHashMailNotify"


end


The partial for the div


<% @recent = notifyHash %>
<% if @recent.any? %>
<% @recent.each do |elem| %>
<script type="text/javascript">
$(document).ready(function(){
$.notify({
icon: 'pe-7s-science',
message: "<%= elem %>"
},{
type: 'info',
delay: 0,
placement:{
from: 'bottom',
align: 'right'
}
});
});
</script>
<% end %>
<%end%>



The notifyHash function


def notifyHash

@imap = Net::IMAP.new(.....)
@imap.login(......)

@imap.select 'folder'

@recent = Array.new

count =0
@imap.uid_search(["RECENT"]).each do |uid|
header = @imap.uid_fetch(uid, "ENVELOPE")[0].attr["ENVELOPE"]
sub = header.subject
count += 1
@recent.push(sub) if sub.include? "#"
end

@recent.push "You have got #{count} new mail" if count != 0

@imap.logout
@imap.disconnect

return @recent
end

trh trh
Answer

There might be a better way to do this. Create a js that has a setTimeout for your interval time, then call a function to do an ajax request and fetch your new messages. Return the new messages as json and process each one through notify, then at the end of the function, reset your timer. Note that in this example it's refreshing every 15 seconds, which is far too quickly and would be annoying :)

Your js might look something like

$(document).ready(function() {
  setTimeout(updateNotifications, 15000);
  function updateNotifications() {
    $.ajax({
      url:"/check-messages",
      dataType: "json",
      success:function(msgs) {
        $.each(msgs, function (key, data) {
          $.notify({
            icon: 'pe-7s-science',
            message: data
          },{
            type: 'info',
            delay: 0,
            placement:{
              from: 'bottom',
              align: 'right'
            }
          });
        });
      }
    });
    setTimeout(updateNotifications, 15000);
  };
});

You'll need to create a route in config/routes.rb

get "/check-messages", to: "users#get_messages"

Then the "helper" method that you have in application_controller.rb, move it to users_controller.rb (it's not Rails-esque to point a route to application_controller and can break things).

@imap = Net::IMAP.new(.....)
@imap.login(......)

@imap.select 'folder'

@recent = Array.new

count =0
@imap.uid_search(["RECENT"]).each do |uid|
      header = @imap.uid_fetch(uid, "ENVELOPE")[0].attr["ENVELOPE"]
      sub = header.subject 
      count += 1
      @recent.push(sub) if sub.include? "#"
end

@recent.push "You have got #{count} new mail" if count != 0

@imap.logout
@imap.disconnect

respond_to do |format|
  format.json { render json: @recent.to_json }
end

Also, @imap is an instance variable and unless you need it available in your views, you might move it to a local (remove the @ sign)