Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialDario Hunt
2,245 PointsRails javascript polling
I'm trying to implement javascript polling in my app but I'm running into a few problems. I'm pretty much following along with this railscasts. My problem is in trying to prepending any new data found. It prepends all of the data old and new and if there isn't any new data found it just prepends all of the old data. My other problem is that my setTimeout is only being called once, even after I try to keep it polling like they show in railscast. Below is my code. What am I doing wrong here?
polling.js
var InboxPoller;
InboxPoller = {
poll: function() {
return setTimeout(this.request, 5000);
},
request: function() {
return $.getScript($('.inbox_wrap').data('url'), {
after: function() {
$('.conversation').last().data('id')
}
});
}
};
$(function() {
if ($('.inbox_wrap').length > 0) {
return InboxPoller.poll();
}
});
polling.js.erb
$(".inbox_wrap").prepend("<%= escape_javascript(render @conversations, :locals => {:conversation => @conversation}) %>");
InboxPoller.poll();
conversations_controller.rb
class ConversationsController < ApplicationController
before_filter :authenticate_member!
helper_method :mailbox, :conversation
def index
@messages_count = current_member.mailbox.inbox({:read => false}).count
@conversations = current_member.mailbox.inbox.order('created_at desc').page(params[:page]).per_page(15)
end
def polling
@conversations = current_member.mailbox.inbox.where('conversation_id > ?', params[:after].to_i)
end
def show
@receipts = conversation.receipts_for(current_member).order('created_at desc').page(params[:page]).per_page(20)
render :action => :show
@receipts.mark_as_read
end
def create
recipient_emails = conversation_params(:recipients).split(',').take(14)
recipients = Member.where(user_name: recipient_emails).all
@conversation = current_member.send_message(recipients, *conversation_params(:body, :subject)).conversation
respond_to do |format|
format.html { redirect_to conversation_path(conversation) }
format.js
end
end
def reply
@receipts = conversation.receipts_for(current_member).order('created_at desc').page(params[:page]).per_page(20)
@receipt = current_member.reply_to_conversation(conversation, *message_params(:body, :subject))
respond_to do |format|
format.html { conversation_path(conversation) }
format.js
end
end
private
def mailbox
@mailbox ||= current_member.mailbox
end
def conversation
@conversation ||= mailbox.conversations.find(params[:id])
end
def conversation_params(*keys)
fetch_params(:conversation, *keys)
end
def message_params(*keys)
fetch_params(:message, *keys)
end
def fetch_params(key, *subkeys)
params[key].instance_eval do
case subkeys.size
when 0 then self
when 1 then self[subkeys.first]
else subkeys.map{|k| self[k] }
end
end
end
def check_current_subject_in_conversation
if !conversation.is_participant?(current_member)
redirect_to conversations_path
end
end
end
index.html.erb
<%= content_tag :div, class: "inbox_wrap", data: {url: polling_conversations_url} do %>
<%= render partial: "conversations/conversation", :collection => @conversations, :as => :conversation %>
<% end %>
_conversation.html.erb
<div id="conv_<%= conversation.id %>_<%= current_member.id %>" class="conversation" data-id="<%= conversation.id %>">
<div class="conv_body">
<%= conversation.last_message.body %>
</div>
<div class="conv_time">
<%= conversation.updated_at.localtime.strftime("%a, %m/%e %I:%M%P") %>
</div>
</div>
1 Answer
Brandon Barrette
20,485 PointsI'm going to take a stab at it. I've implemented polling as well for notifications. My guess is here:
def polling
@conversations = current_member.mailbox.inbox.where('conversation_id > ?', params[:after].to_i)
end
You are sending in some params "after". Are you sure that's making it through correctly? In your development log, do you see the call to rails execute properly?
My guess is the after params is not working properly. If your after function in javascript calls nil, then in your controller, you call params[:after].to_i, which turns to 0 (because nil.to_i = 0). Thus when you call conversation_id > 0, it returns everything. So I would investigate by sending just an integer into your JS after function first. Then seeing if it works (then you know it's not rails). If that's the case, then you can work on fixing the javascript to send the proper ID and set a condition to not ping the database if nil.
Hope that helps, if I've missed something, please add more to your question or explain what you've tried and I can try to help.