-
Notifications
You must be signed in to change notification settings - Fork 211
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
action cable setup #805
action cable setup #805
Changes from all commits
9b0487e
3b7b2bf
10d42f4
c7af515
826745f
6e8e33b
53d8aad
193f553
454cf2f
852d5f9
8fd235d
a158e77
35aa34f
2610522
4040bc3
e231418
55baec4
4904217
53084a1
add9f16
87deccd
2432805
2f9f6eb
a389a97
54b5ef7
fdcd38a
9191cf6
d0bdd43
855089a
d07cd13
f271a84
fe95fc8
53bd5ab
a522eaa
3b2274a
ac8e40c
f002ad0
1464157
b033cc5
e568fbe
7779a96
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
passenger: passenger start | ||
puma: puma -C config/puma.rb | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// | ||
//= require action_cable | ||
//= require_self | ||
//= require_tree ./channels | ||
|
||
(function() { | ||
this.App || (this.App = {}); | ||
|
||
App.cable = ActionCable.createConsumer(); | ||
|
||
}).call(this); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/* 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 | ||
}, | ||
|
||
disconnected: function() { | ||
// Called when the subscription has been terminated by the server | ||
}, | ||
|
||
received: function(data) { | ||
// Called when there's incoming data on the websocket for this channel | ||
window.mapKnitter.synchronizeData(data.changes); | ||
}, | ||
|
||
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 | ||
}); | ||
} | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -386,6 +386,32 @@ 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) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The updation corresponding to each change will happen with the help of this function. This function gets all the necessary information related to the warpables on the map (which are broadcasted my the server on the concurrent_editing_channel) |
||
var layers = []; | ||
map.eachLayer(function(l) {layers.push(l)}); | ||
alaxalves marked this conversation as resolved.
Show resolved
Hide resolved
|
||
layers = layers.filter(image => (image._url!=undefined || image._url!=null)); | ||
warpables.forEach(function(warpable) { | ||
corners = []; | ||
warpable.nodes.forEach(function(node) { | ||
corners.push(L.latLng(node.lat, node.lon)); | ||
}); | ||
|
||
x = corners[2]; | ||
y = corners [3]; | ||
corners [2] = y; | ||
corners [3] = x; | ||
|
||
console.log(corners); | ||
|
||
layer = layers.filter(l => l._url==warpable.srcmedium)[0]; | ||
layer.setCorners(corners); | ||
}); | ||
}, | ||
|
||
saveImageIfChanged: function () { | ||
var img = this, | ||
edit = img.editing; | ||
|
@@ -424,6 +450,9 @@ MapKnitter.Map = MapKnitter.Class.extend({ | |
beforeSend: function (e) { | ||
$('.mk-save').removeClass('fa-check-circle fa-times-circle fa-green fa-red').addClass('fa-spinner fa-spin') | ||
}, | ||
success: function(data) { | ||
App.concurrent_editing.speak(data); | ||
}, | ||
complete: function (e) { | ||
$('.mk-save').removeClass('fa-spinner fa-spin').addClass('fa-check-circle fa-green') | ||
}, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
module ApplicationCable | ||
class Channel < ActionCable::Channel::Base | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
module ApplicationCable | ||
class Connection < ActionCable::Connection::Base | ||
identified_by :current_user | ||
|
||
def connect | ||
self.current_user = find_verified_user | ||
end | ||
|
||
private | ||
|
||
def find_verified_user | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This handles the authentication part. |
||
User.find(cookies.signed["user_id"]) | ||
rescue ActiveRecord::RecordNotFound | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
reject_unauthorized_connection | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
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 | ||
|
||
def unsubscribed | ||
# Any cleanup needed when channel is 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ViditChitkara Is this the proper puma command or are there any other flags needed?