Rails pub/sub with faye

2020-05-19 09:06发布

问题:

In a Rails app I've used Faye (Rack adapter) for push notifications (for chat).

I want to use Faye for another use case (more push notifications) but I can't seem to figure it out.

In my app a model can be created from a background job so I want to refresh one of my views (say the index action) when the model gets created.

Like so:

app/models/post.rb

class Post
    include Mongoid::Document

    after_create :notify_subscribers

    private
    def notify_subscribers
        Faye::Client.publish("/posts")
    end
end

app/views/posts/index.html.erb

<%= subscribe_to(posts_url) do %>
   uhh what do I do here? ajax call to refresh the whole page??
<% end %>

So is publishing the notification directly from an after_create callback a good idea and when I get a message from the Faye server how to I go about implementing the "update"? Do I just do an AJAX call to reload the data from the server? That seems like it would be slow.

Further I want to use something similar for updates to the model (say a user added some comments or the author changed the content) so thrashing the DB all the time doesn't seem like a good plan...

回答1:

First of all, yes, publishing the notification with after_create is fine. What you should do in your notify_subscribers method is to publish all relevant information about the new post that you want to use in the client so that you don't have to make another unnecessary AJAX request when the notification is received.

So, for instance, if the title and content of the post are relevant for the user to see immediately after it gets created, you would do something like:

def notify_subscribers
  client = Faye::Client.new('http://localhost:3000/faye')
  client.publish("/posts/new", {
    'title' => self.title,
    'content' => self.content
  })
end

...and then, in the view, you would probably use jQuery to use the data about the new post which you receive from the server. Rails code won't help you here. E.g. you would do this (assuming you're using jQuery and have included faye.js in your header):

<script type="text/javascript">
$(function() {
  var client = new Faye.Client('http://localhost:3000/faye');
  client.subscribe("/posts/new", function(data) {
    /* do whatever you need with data */
  });
});
</script>

Finally, if somehow the information you want to transfer is too complex to transfer as part of the notification, or you already have existing AJAX processes for updating your view, you could just publish the post's ID and trigger an AJAX call with jQuery in the subscribe callback function. I'd recommend this only if necessary though.