From 02422fc5489f708f43651aebe12389c6655c08f5 Mon Sep 17 00:00:00 2001 From: viditchitkara Date: Mon, 12 Aug 2019 10:14:47 +0530 Subject: [PATCH 1/2] added a few comments to the newly added actioncable logic --- app/assets/javascripts/channels/concurrent_editing.js | 8 ++++++-- app/assets/javascripts/mapknitter/Map.js | 3 +++ app/channels/concurrent_editing_channel.rb | 4 ++++ app/controllers/images_controller.rb | 2 +- app/models/map.rb | 1 + 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/channels/concurrent_editing.js b/app/assets/javascripts/channels/concurrent_editing.js index 079c7933e..e36d1115b 100644 --- a/app/assets/javascripts/channels/concurrent_editing.js +++ b/app/assets/javascripts/channels/concurrent_editing.js @@ -1,12 +1,12 @@ +/* Handles all the frontend interactions with action cable and the server. */ + App.concurrent_editing = App.cable.subscriptions.create("ConcurrentEditingChannel", { connected: function() { // Called when the subscription is ready for use on the server - console.log("Connected"); }, disconnected: function() { // Called when the subscription has been terminated by the server - console.log("bye"); }, received: function(data) { @@ -15,6 +15,10 @@ App.concurrent_editing = App.cable.subscriptions.create("ConcurrentEditingChanne }, speak: function(changes) { + /* Called when an image is updated from Map.js ('saveImage' function). + * This function calls concurrent_editing_channel.rb's 'sync' method + * which is responsible for broadcasting the updated warpables + * to all the user's connected to the concurrent_editing channel. */ return this.perform("sync", { changes: changes }); diff --git a/app/assets/javascripts/mapknitter/Map.js b/app/assets/javascripts/mapknitter/Map.js index b7058dc39..3bdccc8f6 100644 --- a/app/assets/javascripts/mapknitter/Map.js +++ b/app/assets/javascripts/mapknitter/Map.js @@ -388,6 +388,9 @@ MapKnitter.Map = MapKnitter.Class.extend({ if (this.editing._mode !== "lock") { e.stopPropagation(); } }, + /* Called by the concurrent_editing.js channel's 'received' function (app/assets/javascripts/channels/concurrent_editing.js). + * It recieves a list of updated warpables,i.e. list of images with updated corner points. The aim of writing this function + * is to reposition the updated images onto the map on every connected browser (via the ActionCable). */ synchronizeData: function(warpables) { var layers = []; map.eachLayer(function(l) {layers.push(l)}); diff --git a/app/channels/concurrent_editing_channel.rb b/app/channels/concurrent_editing_channel.rb index c3a58a43b..79991c3b1 100644 --- a/app/channels/concurrent_editing_channel.rb +++ b/app/channels/concurrent_editing_channel.rb @@ -1,5 +1,8 @@ class ConcurrentEditingChannel < ApplicationCable::Channel + # This class handles the server side logic of the actioncable communication. + def subscribed + # Called first to connect user to the channel. stream_from "concurrent_editing_channel" end @@ -8,6 +11,7 @@ def unsubscribed end def sync(changes) + # Responsible for broadcasting the updated warpables or simply images to the user's connected on this channel. ActionCable.server.broadcast 'concurrent_editing_channel', changes end end diff --git a/app/controllers/images_controller.rb b/app/controllers/images_controller.rb index 00f6771a9..3f6aecc2a 100644 --- a/app/controllers/images_controller.rb +++ b/app/controllers/images_controller.rb @@ -92,7 +92,7 @@ def update @warpable.locked = params[:locked] @warpable.cm_per_pixel = @warpable.get_cm_per_pixel @warpable.save - data = @warpable.map.fetch_map_data + data = @warpable.map.fetch_map_data # Get the updated warpable data render json: data render html: 'success' else diff --git a/app/models/map.rb b/app/models/map.rb index 9da67ac91..ab001ff16 100755 --- a/app/models/map.rb +++ b/app/models/map.rb @@ -275,6 +275,7 @@ def add_tag(tagname, user) end def fetch_map_data + # fetches a list of updated warpables along with their corners in a json format. data = warpables data.to_json end From 7dc38de5fa64d0afeaefb69c79e2f11bc3bf84e5 Mon Sep 17 00:00:00 2001 From: viditchitkara Date: Mon, 12 Aug 2019 23:00:39 +0530 Subject: [PATCH 2/2] added a new SYNCHRONOUS_EDITING.md file for the synch editing feature docs --- SYNCHRONOUS_EDITING.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 SYNCHRONOUS_EDITING.md diff --git a/SYNCHRONOUS_EDITING.md b/SYNCHRONOUS_EDITING.md new file mode 100644 index 000000000..66819275f --- /dev/null +++ b/SYNCHRONOUS_EDITING.md @@ -0,0 +1,30 @@ +The new synchronous editing feature +=================================== + +With the introduction of ActionCable to our system, it has been possible +to do perform real-time tasks quite easily. We have used rail's default +action cable to make a _concurrent_editing_channel.rb_ in the _app/channels_ folder, +to handle all the incoming requests and consists of all the business +logic as well. At the frontend we have, _app/javascripts/channels/concurrent_editing.js_ which +handles the logic at the browser or the frontend. + +## Flow of the feature: + +1. When the map is updated, the _speak_ method of _concurrent_editing.js_ is called which requests +the _sync_ method of _concurrent_editing_channel.rb_ to broadcast the updated data to +the connected users. + +2. The broadcasted data is finally caught by the _received_ function of _app/javascripts/channels/concurrent_editing.js_ + +3. Finally the _received_ function calls the _synchronizeData_ function to update + all the fresh data on the map. + + +## Testing: + +1. The _action-cable-testing_ gem is used for the feature's testing. It has some really +cool testing functionality which was required for our use case. + +2. Currently we have separate tests written for connection related features and channel +specific features. The relevant files are test/channels/concurrent_editing_channel_test.rb and +test/channels/connection_test.rb \ No newline at end of file