ryanb / private_pub

Handle pub/sub messaging through private channels in Rails using Faye.
MIT License
864 stars 228 forks source link

Allow alternative JavaScript callbacks #9

Closed BinaryMuse closed 13 years ago

BinaryMuse commented 13 years ago

This pull request attempts to resolve issue #1.

As specified in the readme changes, users can now specify a custom JavaScript callback to use by passing a :callback option to subscribe_to:

<%= subscribe_to "/messages/new", :callback => "process_message" %>

They can also publish arbitrary objects:

<% publish_to "/messages/new", :message => "Hello, world!", :from => "Ryan Bates" %>
# or
<% publish_to "/messages/new", @message %>

Passing a :callback to subscribe_to creates a new data attribute, data-callback. private_pub.js picks up on this, and executes the function specified there, with the data from Faye's callback as the parameter.

I'm not 100% sure if this is what you had in mind for this feature. I also thought about a custom renderer, e.g.

respond_to do |format|
  format.js { render :faye => @message }
end

but it wouldn't be, strictly speaking, a renderer, and this solution seemed simpler for now. Looking forward to feedback.

ryanb commented 13 years ago

Thanks for your work on this, I have some different ideas.

users can now specify a custom JavaScript callback to use by passing a :callback option to subscribe_to:

It shouldn't be necessary to pass a :callback option. A channel already has a name, we can use this.

and executes the function specified there

Using a function with a specific name limits how one works with JavaScript. If they have a more object oriented approach, requiring they define global functions isn't the best.

The easiest implementation would be to trigger an event which they can listen to, but the problem with this is that it will pass in an event object and not the data object directly.

Instead I think it should work how I show in issue #1 where there is a PrivatePub class which has a subscribe call. One can call this, pass in a channel name and callback function which gets triggered.

Another advantage of this is that we can build in wildcard functionality into the subscribe call such as /messages/*/update to listen to an update call on any message.

Update: instead of instantiating a new PrivatePub class it could just be a global function on PrivatePub.

PrivatePub.subscribe("/messages/new", function(data) {
  # ...
}
ryanb commented 13 years ago

Regarding the renderer idea, it's a cool idea but I don't think it fits since this isn't necessarily something we're returning to this one client. someone may also want to publish multiple times in one request. It will probably be common to combine publish_to with render :nothing => true if that's the behavior they want.

BinaryMuse commented 13 years ago

Excellent points. Is this more what you had in mind?

ryanb commented 13 years ago

Looks good, got this pulled in under one commit.