Private messages with Faye and Rails

2019-03-30 16:52发布

问题:

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:

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