Private messages with Faye and Rails

1.1k views Asked by At

I'm using the faye gem menitioned in the railscast allowing apps to push messages. Problem is it pushes messages to all chat clients that are open. I need them to be private. It's possible to get private messaging with faye but it's url based. For example all messages will be sent to site.com/foo. But, in my model the chat doesn't have a specific url. Because chat is just a collection of messages sent to you by that user.

So if you're logged in as adam site.com/messages/eve would allow you to talk to eve but for eve it's the reverse. site.com/messages/adam. So URL specific private chat is seemingly out of the question.

Any pointers?

messages_controller.rb ( triggering ajax )

def create
  @message = Message.new(message_params)
  @message.save
end 

create.js.erb ( calling a broadcast method )

<% broadcast params[:message][:username] do %>
  $(".text-wrap").append("<%= current_user.name %> <%= @message.body %></div>");
<% end %>

broadcast method ( posting to the faye server )

def broadcast(user, &block)
  channel = "/messages/#{user}"
  message = {:channel => channel, :data => capture(&block)}
  uri = URI.parse("http://localhost:9292/faye")
  Net::HTTP.post_form(uri, :message => message.to_json)
end

application.js ( faye server subscription to /messages/* )

$(function(){
    var faye = new Faye.Client('http://localhost:9292/faye');
    var subscription = faye.subscribe('/messages/*', function(message) {
        eval(message);
    });
});
1

There are 1 answers

0
Alain Goldman On BEST ANSWER

I solved it! The problem was that I had the subscribe function in application.js meaning it would run the subscribe javascript on each page. Instead what I did is at the bottom of the chat page view i subscribed to /messages/eve/adam. This is how I did that:

<script>  
  $(function(){
    var faye = new Faye.Client('http://localhost:9292/faye');
    var subscription = faye.subscribe('/messages/#{current_user.username}/#{@user.username}', function(message) {
      eval(message);
    });
  });
</script>

Then in the broadcast method I made sure to send the information to only the correct place.

def broadcast(user, &block)
  channel = "/messages/#{current_user.username}/#{user}"
  message = {:channel => channel, :data => capture(&block)}
  uri = URI.parse("http://localhost:9292/faye")
  Net::HTTP.post_form(uri, :message => message.to_json)
end