Search code examples
ruby-on-railsrubyjsonruby-on-rails-4faye

Rails controller action result in Faye


I have a rails application with Faye gem. My rails application is divided into two engines. One of the engines has a controller. This controller contains a method called Index that can get data from the database. This method uses a JSON view with a help of jbuilder gem.

So the question is whenever a user subscribes to the faye channel, I would like to push the result of this controller method through this channel to the user with JSON format. How can I do this?

Here is my source code:

#/faye.ru

require 'faye'
Faye::WebSocket.load_adapter('thin')
app = Faye::RackAdapter.new(:mount => '/faye', :timeout => 25)
run app



#/engines/restaurant/app/controllers/restaurant/menu_controller.rb

class Restaurant::MenuController < RestaurantController

  def index
    @categories = Category.where("status" => true)
  end

end



#/engines/restaurant/app/views/restaurant/menu/index.json.jbuilder

json.categories @categories do |category|
  json.id category.id
  json.name category.name
  json.image category.image.url
end



#/config/routes.rb

Rails.application.routes.draw do

  root 'restaurant/home#index'

  mount Restaurant::Engine => '/', as: 'restaurant'
end

Solution

  • I advice you to use gem private_pub to work with faye (it's very simple just look at this). With private_pub you can touch your action in connection callback in js code. Simple example (how to connect and config private_pub - look at cast or at gem's github page):

    Create action in any your controller for subscribtion (for example)

    class YourController < ApplicationController
      def subscription
        @subscription = nil
        # channel_id is your identificator of channel
        @subscription = PrivatePub.subscription(channel: "/channel/#{channel_id}") 
        render json: @subscription.to_json(root: false)
      end
    end
    

    In your js (if you use jquery):

    $.getJSON('/controller_path/subscription', function (data) {
      // you can call your action here to load any data you want
      $.getJSON('your action', function(data) { 
        //your code here 
      });
      PrivatePub.sign(data);
      PrivatePub.subscribe(data.channel, function(data, channel) {
        // your code here to process data from faye
      });
    });