Skip to content

Commit 2ed6093

Browse files
committed
Working chat app with jQuery tabs and Backbone. Adds a small chat posting box
Signed-off-by: Akash Manohar J <akash@akash.im>
1 parent 6d0f370 commit 2ed6093

File tree

11 files changed

+115
-16
lines changed

11 files changed

+115
-16
lines changed

app/assets/javascripts/application.js

+1
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@
1717
//= require lib/backbone
1818
//= require backbone/kandan
1919
//= require_tree .
20+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
class Kandan.Broadcasters.FayeBroadcaster
2+
3+
constructor: ()->
4+
@faye_client = new Faye.Client("/remote/faye")
5+
@faye_client.disable('websocket')
6+
auth_extension = {
7+
outgoing: (message, callback)->
8+
if message.channel == "/meta/subscribe"
9+
# TODO move fetching auth token to a helper
10+
message['ext'] = {auth_token: $.data(document, 'current_user').auth_token}
11+
callback(message)
12+
}
13+
@faye_client.addExtension(auth_extension)
14+
15+
subscribe: (channel)->
16+
console.log "Subscribing to #{channel}"
17+
@faye_client.subscribe channel, (data)=>
18+
console.log data.user.first_name, "says", data.content

app/assets/javascripts/backbone/kandan.js.coffee

+32-4
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,40 @@ window.Kandan =
1010
Collections: {}
1111
Views: {}
1212
Routers: {}
13+
Broadcasters: {}
1314
init: ->
14-
# new Kandan.Routers.Main()
1515
# Backbone.history.start({pushState: true})
16-
chat_area = new Kandan.Views.ChatArea()
17-
$('.container').html(chat_area.render().el)
18-
# $('.container').append(chat_box)
16+
channels = new Kandan.Collections.Channels()
17+
channels.fetch({success: ()=>
18+
19+
chat_area = new Kandan.Views.ChatArea({channels: channels})
20+
$('.container').html(chat_area.render().el)
21+
22+
chatbox = new Kandan.Views.Chatbox()
23+
$('.container').append(chatbox.render().el)
24+
25+
# TODO move this to a helper
26+
# can also be done by checking the active tab in the post event in the Chatbox view
27+
$('#channels').tabs({
28+
select: (event, ui)->
29+
channel_id = $("#channels .ui-tabs-panel").eq("#{ui.index}").data('channel_id')
30+
console.log "set channelID to", channel_id
31+
# TODO move setting current channel ID to a seperate helper
32+
$('.chatbox').data('active_channel_id', channel_id)
33+
})
34+
35+
# TODO move broadcast subscription to a helper
36+
# TODO change this to use the broadcaster from the settings
37+
# TODO set as global to debug. remove later.
38+
window.broadcaster = new Kandan.Broadcasters.FayeBroadcaster()
39+
for channel in channels.models
40+
window.broadcaster.subscribe "/channels/#{channel.get('id')}"
41+
42+
# TODO move this to a helper
43+
$('.chatbox').data('active_channel_id',
44+
$("#channels .ui-tabs-panel").eq($('#channels').tabs('option', 'selected')).data('channel_id'))
45+
})
46+
1947

2048
$(document).ready ->
2149
Kandan.init()

app/assets/javascripts/backbone/views/chatarea.js.coffee

+4-9
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,11 @@ class Kandan.Views.ChatArea extends Backbone.View
33
template: JST['chatarea']
44
# className: 'channels'
55

6-
initialize: ()->
7-
@channels = new Kandan.Collections.Channels()
86

97
render: ->
10-
@channels.fetch({success: ()=>
11-
$(@el).html(@template({channels: @channels}))
12-
for channel in @channels.models
13-
view = new Kandan.Views.ListActivities({channel: channel})
14-
$(@el).append(view.render().el)
15-
$('#channels').tabs()
16-
})
8+
$(@el).html(@template({channels: @options.channels}))
9+
for channel in @options.channels.models
10+
view = new Kandan.Views.ListActivities({channel: channel})
11+
$(@el).append(view.render().el)
1712
$(@el).attr('id', 'channels')
1813
@
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
class Kandan.Views.Chatbox extends Backbone.View
2+
3+
template: JST['chatbox']
4+
tagName: 'div'
5+
className: 'chatbox-area'
6+
7+
events:
8+
"keypress .chatbox": 'postMessage'
9+
10+
postMessage: (event)->
11+
12+
if event.keyCode== 13
13+
$chatbox = $(".chatbox")
14+
activity = new Kandan.Models.Activity({
15+
'content': $chatbox.val(),
16+
'action': 'message',
17+
'channel_id': $chatbox.data('active_channel_id')
18+
})
19+
20+
activity.save({success: ()->
21+
console.log "posted! enjoy your day"
22+
})
23+
24+
25+
render: ()->
26+
$(@el).html(@template())
27+
@

app/assets/javascripts/backbone/views/list_activities.js.coffee

+1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ class Kandan.Views.ListActivities extends Backbone.View
77
activity_view = new Kandan.Views.Activity({activity: activity})
88
$(@el).append(activity_view.render().el)
99
$(@el).attr('id', "channels-#{@options.channel.get('id')}")
10+
$(@el).data('channel_id', @options.channel.get('id'))
1011
@

app/assets/templates/chatbox.jst.eco

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<input type="text" class="chatbox"/>

app/controllers/activities_controller.rb

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ def index
1010

1111
def create
1212
@activity = Channel.find(params[:channel_id]).activities.build(params[:activity])
13+
@activity.user_id = current_user.id if @activity.action == "message"
1314
if @activity.save
1415
respond_to do |format|
1516
format.json { render :json => @activity, :status => :created }

app/models/activity_observer.rb

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
class ActivityObserver < ActiveRecord::Observer
22

33
def after_save(activity)
4-
faye_channel = "/channels/#{activity.channel.to_param}/messages"
5-
Kandan::Config.broadcaster.broadcast(faye_channel, activity.attributes)
4+
faye_channel = "/channels/#{activity.channel.to_param}"
5+
# TODO move this to a rabl template
6+
broadcast_data = activity.attributes.merge({:user => activity.user.attributes})
7+
Kandan::Config.broadcaster.broadcast(faye_channel, broadcast_data)
68
end
79
end

config.ru

+23
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,35 @@
33
require ::File.expand_path('../config/environment', __FILE__)
44
require 'faye'
55

6+
# TODO move this to the lib dir
7+
class DeviseAuth
8+
def incoming(message, callback)
9+
if message['channel'] == "/meta/subscribe"
10+
auth_token = message['ext']['auth_token']
11+
user = User.find_by_authentication_token(auth_token)
12+
if user
13+
return callback.call(message)
14+
else
15+
message['error'] = "Invalid auth token"
16+
end
17+
end
18+
puts "Message: #{message.inspect}"
19+
callback.call(message)
20+
end
21+
22+
#TODO disable publishing by users
23+
end
24+
25+
626
faye_server = Faye::RackAdapter.new(:mount => "/faye", :timeout => 5)
27+
faye_server.add_extension(DeviseAuth.new)
728

829
# TODO send pull request to faye to get this fixed
930
# by adding a rack_prefix option
1031
# which should then make the faye server object available
1132
# via the get_client() method on the server
1233

34+
1335
FAYE_CLIENT = faye_server.get_client
1436

1537
faye_server.bind(:subscribe) do |client_id|
@@ -18,6 +40,7 @@ end
1840

1941
faye_server.bind(:disconnect) do |client_id|
2042
puts "DISCONNECT #{client_id}"
43+
User
2144
end
2245

2346
run Rack::URLMap.new({

lib/broadcasters/faye.rb

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ class Faye
33
class << self
44
def broadcast(channel, message)
55
# NOTE FAYE_CLIENT is set in the config.ru file due to the faye bug
6-
if defined?(FAYE_CLIENT) && (not FAYE_CLIENT.nil?)
6+
puts "CHECKING TO BEGIN BROADCAST"
7+
if defined?(FAYE_CLIENT)
8+
puts "BROADCASTING... to #{channel}"
79
FAYE_CLIENT.publish channel, message
810
else
911
puts "OOPS! FAYE_CLIENT is not defined"

0 commit comments

Comments
 (0)