ActionCable - Part 2 - More Complex Example

#38 ActionCable - Part 2 - More Complex Example
7/17/2016

Summary

Extending the previous episode, we look into making a realtime poll application where users can get live feedback on voting.
4
view websockets render javascript rails 5:10 min

Summary

vote.html.erb

<legend>Vote</legend>

<% powers = [   ['Telekenisis', :telekenisis],   ['Mind Control', :mind_control],   ['Flying', :flying],   ['Invisibility', :invisibility],   ['Super Strength', :super_strength]] %> <%= simple_form_for :vote do |f| %>   <div class='form-group'>     <%= f.label :power, label: 'Which super power would you choose?', class: 'col-xs-4' %>     <div class='col-xs-8'>       <%= f.input_field :power, as: :radio_buttons, collection: powers %>     </div>   </div> <% end %> <legend>Results</legend> <div class='results'>   <% powers.each do |label, symbol| %>     <%= content_tag :div, class: symbol do %>       <span><%= label %></span>       <span class='count'>         <div class="progress">           <div class="progress-bar progress-bar-success" role="progressbar">0</div>         </div>       </span>     <% end %>   <% end %> </div>

vote.jsApp.vote = App.cable.subscriptions.create("VoteChannel", {
  connected: function() {
  },

  disconnected: function() {
  },

  received: function(data) {
    var power =  data['power'];
    var count = parseInt($('.' + power + ' .count').text());  
    if (data['method'] == 'add') {
      $('.results ' + '.' + power + ' .count .progress-bar').html(count + 1);
    } else if (data['method'] == 'subtract') {
      $('.results ' + '.' + power + ' .count .progress-bar').html(count - 1);
    }

    var total_count = 0;
    $('.count .progress-bar').each( function(){
      total_count = total_count + parseInt($(this).text());
    })

    $('.count .progress-bar').each( function(){
      $(this).css('width',parseInt($(this).text()) / total_count * 100 + '%');
    })
  },

  voted: function(power) {
    return this.perform('voted', { power: power });
  },

  reduce: function(power) {
    return this.perform('reduce', { power: power });
  }
});
vote_channel.rbclass VoteChannel < ApplicationCable::Channel
  def subscribed
    stream_from "vote"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end

  def voted(data)
    ActionCable.server.broadcast 'vote', power: data['power'], method: 'add'
  end

  def reduce(data)
    ActionCable.server.broadcast 'vote', power: data['power'], method: 'subtract'
  end
end
visitors.coffeevote = ->
  clicks = new Array
  $('input[type=radio]').change ->
    clicks.push @value
    App.vote.voted @value
    App.vote.reduce clicks[clicks.length - 2]

$(document).on 'turbolinks:load', vote
visitors.js// Javascript version of visitors.coffee
var vote = function(){
  var clicks = new Array();
  $('input[type=radio]').change(function() {
    clicks.push(this.value);
    App.vote.voted(this.value);
    App.vote.reduce(clicks[clicks.length - 2]);
  });
}
$(document).on('turbolinks:load', vote)