Search code examples
ruby-on-railsruby-on-rails-4coffeescriptprivate-pubgritter

Using Private-pub with channels that have segment keys and coffeescript variant


I'm trying to replicate a push notification system similar to facebook's using private_pub. Ideally I would want to link this to show notifications using a gem such as gritter (other gem suggestions are welcome)

Whenever a certain action from a controller is called, I want to send a notification to all subscribers that are part of a specific id. As long you are logged in, you are subscribed to the channel, achieved by putting the subscribe_to in the layouts.

in the view:

<%= subscribe_to "/messages/#{@group_id}" %>

in the controller

PrivatePub.publish_to("/messages/#{@group_id}", "alert('test')")

this works just fine, however I would like to have something more sophisticated than an alert as a response (such as a gritter notification), so instead:

PrivatePub.publish_to("/messages/#{@group_id}", data: @some_data)

Following the tutorial, they use coffeescript for this. However, I cannot get the simple alert going (probably due to the id in the channel)

In this question, the OP was able to solve this using a js.erb view. But I can't get it to work.

disclaimer: my js and coffeescript knowledge is almost zero.

Any help is appreciated :)


EDIT

Some more info: I've a method in a controller that's part of a public API, and expects POST request. If everything is ok it sends out a JSON success response. Aside from this, the same method sends a notification to all users of a specific group.

I've actually managed to get this working, putting this in the controller:

callback method:

respond_to do |format|
    format.js #-> calls callback.js.erb
    #format.json { render json: {"success" => true}.to_json }
end

and putting the gritter stuff in my_api_controller/callback.js.erb:

<% publish_to "/messages/#{@group_id}" do %>
    <%= add_gritter(
    "Nova " + link_to("reserva", reservation_path(@r)) + " de #{@channel} para " + 
    link_to(@hostel_name, hostel_path(@hostel_id)),
    :title => "Nova reserva!",
    :sticky => true,
    :image => :notice
) %>
<% end %>

note: since the subscription to the channel is done in every view (through the layout), you can receive a notification on any page/view

My problem at the momento is, as you can guess, the JSON response. Since I cant render two responses, only the js.erb is called, but the JSON response is never sent


Solution

  • I was able to accomplish this by directly adding the gritter script in the publish_to method of Privat pub.

    In my controller:

    PrivatePub.publish_to 
      "/some/URI/#{entity.id}"
     ,"jQuery.gritter.add({
          image: '#{ActionController::Base.helpers.asset_path('notice.png')}'
        , sticky: true
        ,title:'#{t('some_title')}'
        , text: '#{t('some text'}' 
    });"
    
    render json: {"error"=>{"code"=>20,"msg"=>e.message},"success" => false}.to_json
    

    Basically, I was able to publish to PrivatePub witouth resorting to the html response, wich enabled me to return a JSON response as intended.