Skip to content

Instantly share code, notes, and snippets.

@insignia
Created September 17, 2012 18:27
Show Gist options
  • Save insignia/3738919 to your computer and use it in GitHub Desktop.
Save insignia/3738919 to your computer and use it in GitHub Desktop.
Implementing a Twitter like system for companies notifications.
{{#user}}
<div class="lefted gravatar-box">
<a href="#tweets/users/{{id}}">
<img alt="{{full_name}} avatar" src="http://gravatar.com/avatar/{{email_md5}}.png?s=30" title="{{full_name}}">
</a>
</div>
{{/user}}
<div class="lefted">
{{{decorated_status}}}<br/>
<small><abbr class="timeago" title="{{created_at}}">{{created_at}}</abbr></small>
</div>
= template_include_tag '/tweets/tweet'
= hidden_field_tag 'current_user_json_info', current_user_json_info
#twitter-sidebar.sidebar
.right-module.block
%h3 Team Notifications
%ul.activity-items
%li.wat-cf
= form_tag '', :id => 'tweet-form' do
= text_field_tag 'new-status', '', :id => 'new-tweet', :placeholder => 'Compose a new notification...'
%li#waiting-tweets.hidden.wat-cf
%ul#tweets-list.activity-items
class Tweet < ActiveRecord::Base
belongs_to :company
belongs_to :user
validates :status, :presence => true
scope :company, lambda {|company| where(:company_id => company.id) }
scope :by_date, order('created_at DESC')
before_save :set_company_id
protected
def set_company_id
self.company_id = user.company_id
end
end
class TweetPresenter
def initialize(tweet)
@tweet = tweet
end
def as_json(*)
{
:status => @tweet.status,
:user_id => @tweet.user_id,
:created_at => @tweet.created_at && @tweet.created_at.getutc.iso8601,
:user => {
:id => @tweet.user.to_param,
:full_name => @tweet.user.full_name,
:email_md5 => @tweet.user.email_md5
}
}
end
end
require 'spec_helper'
describe Tweet do
subject { Tweet.new }
describe 'validations' do
it { should validate_presence_of(:status) }
end
describe 'callbacks' do
it 'stores company_id from the user associated to the tweet' do
user = Factory.create(:user)
subject.status = 'This is a tweet'
subject.user_id = user.id
subject.save
subject.company_id.should eql(user.company_id)
end
end
end
class TweetsController < InheritedResources::Base
actions :index, :create
respond_to :js
before_filter :set_default_params, :only => :create
def index
index! do |format|
format.js do
render :json =>
collection.reverse.map{|tweet| TweetPresenter.new(tweet)}
end
end
end
def create
create! do |format|
format.js do
render :json => resource
end
end
end
end
window.twitter =
views: {}
models: {}
collections: {}
class twitter.Helpers
@timeago: ->
$("abbr.timeago").timeago()
@add_counter_on_title: (cnt) ->
@strip_counter_on_title()
document.title = "(#{cnt}) #{document.title}"
@strip_counter_on_title: ->
current_title = document.title
document.title = current_title.replace(/^\(\d+\)\s/, '')
@new_tweets_text: (cnt) ->
if cnt > 1
"#{cnt} new notifications."
else
"#{cnt} new notification."
class twitter.models.Tweet extends Backbone.Model
status: ->
@get('status')
created_at: ->
@get('created_at') || ISODateString(new Date())
user: ->
@get('user')
decorated_status: ->
@status().replace /(^|\s)#(\w*[a-zA-Z_]+\w*)/g, (t) ->
"#{t[0]}<b>#{t.trim()}</b>"
class twitter.collections.Tweets extends Backbone.Collection
model: twitter.models.Tweet
url: '/tweets'
class twitter.views.Tweet extends Backbone.View
tagName: 'li'
initialize: (options) ->
super
# Esta clase no debería ser agregada, pero hay que modificar el CSS
# para que lo estilos que tiene asociados se apliquen de todos modos.
@$el.addClass('wat-cf')
@template = $('#tweets-tweet-template').html()
render: ->
@$el.html(Mustache.to_html(@template, @model))
@
class twitter.views.App extends Backbone.View
el: '#twitter-sidebar'
events:
'submit #tweet-form': 'create_tweet'
'click #waiting-tweets': 'discover_hidden_tweets'
initialize: ->
@input = @$('#new-tweet')
@waiting_tweets = @$('#waiting-tweets')
@tweets_list = @$('#tweets-list')
twitter.models.Tweet.defaultUserInfo = JSON.parse($('#current_user_json_info').val())
@tweets = new twitter.collections.Tweets()
@tweets.on 'add', @new_tweet, @
@tweets.on 'reset', @add_all, @
@tweets.fetch()
add_one: (tweet, options = {}) ->
view = new twitter.views.Tweet
model: tweet
className: options['className']
@tweets_list.prepend(view.render().el)
unless options['batch']
twitter.Helpers.timeago()
add_all: ->
@tweets_list.html('')
iterator = (tweet) ->
@add_one(tweet, batch: true)
@tweets.each iterator, @
twitter.Helpers.timeago()
new_tweet: (tweet) ->
@discover_hidden_tweets()
@add_one(tweet)
@input.val('')
pusher.pushNewTweet(tweet)
create_tweet: (event) ->
event.preventDefault()
event.stopPropagation()
status = @input.val().trim()
if status != ''
new_attributes =
status: status
user: twitter.models.Tweet.defaultUserInfo
@tweets.create new_attributes, {wait: true}
discover_hidden_tweets: (event) ->
@tweets_list.find('li.new').removeClass('new')
@tweets_list.find('li.hidden').removeClass('hidden').addClass('new')
@waiting_tweets.hide()
twitter.Helpers.strip_counter_on_title()
@tweets_list.find('li.new').effect("highlight", {}, 3000);
receive_tweet_broadcast: (tweet) ->
@add_one(new twitter.models.Tweet(tweet), {className: 'hidden'})
@waiting_tweets.show()
cnt = @tweets_list.find('li.hidden').length
@waiting_tweets.html(twitter.Helpers.new_tweets_text(cnt))
twitter.Helpers.add_counter_on_title(cnt)
$ ->
window.twitterApp = new twitter.views.App()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment