Skip to content

Commit

Permalink
Threaded private messages, replies and some code refactoring.
Browse files Browse the repository at this point in the history
  • Loading branch information
fredwu committed Jul 12, 2011
1 parent dcf9d86 commit 12eb19b
Show file tree
Hide file tree
Showing 26 changed files with 143 additions and 51 deletions.
17 changes: 17 additions & 0 deletions app/controllers/messages_controller.rb
Expand Up @@ -7,6 +7,9 @@ class MessagesController < ApplicationController

has_scope :p, :default => 1

before_filter :hide_sidebar, :only => [:show_private_message]
before_filter :ensure_ownership, :only => [:show_private_message, :reply_private_message]

def create
resource = parent.add_comment(current_user, params[:message][:content])

Expand All @@ -15,4 +18,18 @@ def create
format.html { redirect_to :back }
end
end

def show_private_message
@topic = Message.topics.find(params[:id])
end

def reply_private_message
@topic = Message.topics.find(params[:id])
result = current_user.reply_private_message(@topic, params[:message][:content])

respond_to do |format|
format.json { render :json => result }
format.html { redirect_to :back }
end
end
end
4 changes: 2 additions & 2 deletions app/controllers/users_controller.rb
Expand Up @@ -3,7 +3,7 @@ class UsersController < ApplicationController

has_scope :page, :default => 1

before_filter :hide_sidebar, :only => [:show, :messages]
before_filter :hide_sidebar, :only => [:show, :message_inboxes]

def home
@micro_posts = resource.followed_micro_posts.page(params[:p])
Expand All @@ -13,7 +13,7 @@ def show
@micro_posts = resource.micro_posts.page(params[:p])
end

def messages
def message_inboxes
@messages = case params[:type].try(:to_sym)
when :sent_messages then current_user.sent_messages
when :archived_messages then current_user.archived_messages
Expand Down
9 changes: 7 additions & 2 deletions app/models/message.rb
Expand Up @@ -3,12 +3,17 @@ class Message < ActiveRecord::Base
belongs_to :user, :counter_cache => :messages_count
belongs_to :target, :polymorphic => true, :counter_cache => :comments_count

belongs_to :topic, :class_name => 'Message', :foreign_key => 'topic_id'
has_many :replies, :class_name => 'Message', :foreign_key => 'topic_id'

validates :content, :presence => true,
:length => { :maximum => 140 }

scope :default_order, order('created_at DESC')
scope :public, where(:is_private => false)
scope :private, where(:is_private => true)
scope :topics, where { topic_id == nil }
scope :replies, where { topic_id != nil }
scope :public_only, where(:is_private => false)
scope :private_only, where(:is_private => true)
scope :read, where(:is_read => true)
scope :unread, where(:is_read => false)
scope :archived, where(:is_archived => true)
Expand Down
16 changes: 13 additions & 3 deletions app/models/user.rb
Expand Up @@ -52,11 +52,11 @@ class User < ActiveRecord::Base
before_save :email_nomarlisation

def incoming_messages
comments.private
comments.private_only.topics
end

def outgoing_messages
messages.on_users.private
messages.on_users.private_only.topics
end

def inbox_messages
Expand Down Expand Up @@ -108,14 +108,24 @@ def has_new_messages?
end

def send_private_message(target_user, content, extras = {})
messages.create({
messages.create!({
:content => content,
:is_private => true,
:target_id => target_user.id,
:target_type => 'User'
}.merge(extras)) && reload
end

def reply_private_message(topic, content, extras = {})
messages.create!({
:content => content,
:is_private => true,
:target_id => topic.user.id,
:target_type => 'User',
:topic_id => topic.id
}.merge(extras)) && reload
end

def add_micro_post(content)
unless content.blank?
messages.create(:content => content) && reload
Expand Down
4 changes: 2 additions & 2 deletions app/views/layouts/userbars/_topnav.html.slim
Expand Up @@ -5,8 +5,8 @@ h3
= link_to t('label.edit'), edit_registration_path(current_user)
' ) |
- if current_user.has_new_messages?
= link_to "#{pluralize(current_user.inbox_messages.unread.count, t('label.new_message'))}!", my_messages_path(:inbox_messages), :class => 'new'
= link_to "#{pluralize(current_user.inbox_messages.unread.count, t('label.new_message'))}!", my_message_inbox_path(:inbox_messages), :class => 'new'
- else
= link_to "#{t('label.messages')} (#{current_user.inbox_messages.count})", my_messages_path(:inbox_messages)
= link_to "#{t('label.messages')} (#{current_user.inbox_messages.count})", my_message_inbox_path(:inbox_messages)
' |
= link_to t('label.sign_out'), destroy_user_session_path
2 changes: 1 addition & 1 deletion app/views/messages/_index.html.slim
@@ -1,5 +1,5 @@
- if collection.any?
ul#messages
- collection.each do |resource|
li.message= render 'messages/show', :resource => resource
li.message= render 'messages/show', :resource => resource, :meta => meta
= show_pagination collection, :param_name => :p
7 changes: 6 additions & 1 deletion app/views/messages/_show.html.slim
Expand Up @@ -5,4 +5,9 @@ hr
.message_meta
=' link_to resource.user.name, username_path(resource.user.username)
= time_ago(resource.created_at)
.message_content= resource.content
.message_content
- if meta[:linkable]
= link_to resource.content, my_private_message_path(resource)
- else
= resource.content

10 changes: 10 additions & 0 deletions app/views/messages/show_private_message.html.slim
@@ -0,0 +1,10 @@
.grid_3
= render 'users/message_inboxes'
.grid_9
ul#messages
li.message= render 'show', :resource => @topic, :meta => {}

- @topic.replies.each do |reply|
li.message= render 'show', :resource => reply, :meta => {}
br
= render 'new', :url => my_private_message_path(@topic)
2 changes: 1 addition & 1 deletion app/views/startups/_comments.html.slim
@@ -1,2 +1,2 @@
= render 'messages/new', :url => startup_comments_path(resource)
= render 'messages/index', :collection => resource.comments.page(params[:p])
= render 'messages/index', :collection => resource.comments.page(params[:p]), :meta => {}
2 changes: 1 addition & 1 deletion app/views/startups/_mini_profile.html.slim
Expand Up @@ -2,7 +2,7 @@
= render 'shared/editable', :edit_target => '#profile_details'

.mini_profile.inline_edtiable_container
#profile_details data-target_link="profile_details/#{startup.id}"
#profile_details data-target_link="#{startup_profile_details_path(startup)}"
= render 'profile_details', :startup => startup
.clear

Expand Down
2 changes: 1 addition & 1 deletion app/views/users/_index.html.slim
@@ -1,6 +1,6 @@
ul.resource_list.user_list
- collection.each do |user|
li.mini_profile data-target_link="profile_team/#{meta[:parent].try(:id)}" data-edit_target="#profile_team"
li.mini_profile data-target_link="#{startup_profile_team_path(meta[:parent])}" data-edit_target="#profile_team"
- unless meta[:role_identifier]
hr

Expand Down
12 changes: 6 additions & 6 deletions app/views/users/_message_inboxes.html.slim
Expand Up @@ -3,12 +3,12 @@
hr
h3= t('label.private_messages')
ul
li= link_to_current t('label.inbox_messages'), my_messages_path(:inbox_messages)
li= link_to_current t('label.sent_messages') , my_messages_path(:sent_messages)
li= link_to_current t('label.archived_messages') , my_messages_path(:archived_messages)
li= link_to_current t('label.inbox_messages'), my_message_inbox_path(:inbox_messages)
li= link_to_current t('label.sent_messages') , my_message_inbox_path(:sent_messages)
li= link_to_current t('label.archived_messages') , my_message_inbox_path(:archived_messages)
hr
h3= t('label.startup_proposals')
ul
li= link_to_current t('label.inbox_proposals') , my_messages_path(:inbox_proposals)
li= link_to_current t('label.sent_proposals') , my_messages_path(:sent_proposals)
li= link_to_current t('label.archived_proposals') , my_messages_path(:archived_proposals)
li= link_to_current t('label.inbox_proposals') , my_message_inbox_path(:inbox_proposals)
li= link_to_current t('label.sent_proposals') , my_message_inbox_path(:sent_proposals)
li= link_to_current t('label.archived_proposals') , my_message_inbox_path(:archived_proposals)
2 changes: 1 addition & 1 deletion app/views/users/home.html.slim
@@ -1,2 +1,2 @@
= render 'messages/new', :url => my_micro_posts_path
= render 'messages/index', :collection => @micro_posts
= render 'messages/index', :collection => @micro_posts, :meta => {}
4 changes: 4 additions & 0 deletions app/views/users/message_inboxes.html.slim
@@ -0,0 +1,4 @@
.grid_3
= render 'message_inboxes'
.grid_9
= render 'messages/index', :collection => @messages, :meta => { :linkable => true }
4 changes: 0 additions & 4 deletions app/views/users/messages.html.slim

This file was deleted.

2 changes: 1 addition & 1 deletion app/views/users/show.html.slim
Expand Up @@ -4,4 +4,4 @@
= render 'users/invested_in', :user => resource if resource.is_investor?

.grid_6
= render 'messages/index', :collection => @micro_posts
= render 'messages/index', :collection => @micro_posts, :meta => {}
21 changes: 13 additions & 8 deletions config/routes.rb
Expand Up @@ -21,15 +21,20 @@
end
end

match 'u/:username' => 'users#show', :via => :get, :as => :username
match 'startups/profile_details/:id' => 'startups#profile_details', :via => :get, :as => :startup_profile_details
match 'startups/profile_team/:id' => 'startups#profile_team', :via => :get, :as => :startup_profile_team

match 'my/profile' => 'users#show', :via => :get
match 'my/home' => 'users#home', :via => :get
match 'my/messages(/:type)' => 'users#messages', :via => :get, :as => :my_messages
match 'my/micro_posts' => 'users#add_micro_post', :via => :post
match 'u/:username' => 'users#show', :via => :get, :as => :username

match 'my/follow/:target_id' => 'users#follow_target', :via => :post, :as => :follow_target
match 'my/unfollow/:target_id' => 'users#unfollow_target', :via => :post, :as => :unfollow_target
match 'my/profile' => 'users#show', :via => :get
match 'my/home' => 'users#home', :via => :get
match 'my/private_messages/:id' => 'messages#show_private_message', :via => :get, :as => :my_private_message
match 'my/private_messages/:id' => 'messages#reply_private_message', :via => :post, :as => :my_private_message
match 'my/message_inboxes(/:type)' => 'users#message_inboxes', :via => :get, :as => :my_message_inbox
match 'my/micro_posts' => 'users#add_micro_post', :via => :post

match 'my/follow/:target_id' => 'users#follow_target', :via => :post, :as => :follow_target
match 'my/unfollow/:target_id' => 'users#unfollow_target', :via => :post, :as => :unfollow_target

# The priority is based upon order of creation:
# first created -> highest priority.
Expand Down Expand Up @@ -86,5 +91,5 @@

# This is a legacy wild controller route that's not recommended for RESTful applications.
# Note: This route will make all actions in every controller accessible via GET requests.
match ':controller(/:action(/:id(.:format)))'
# match ':controller(/:action(/:id(.:format)))'
end
2 changes: 2 additions & 0 deletions db/migrate/20110525132902_create_messages.rb
Expand Up @@ -9,10 +9,12 @@ def change
t.string :target_type
t.integer :user_id
t.integer :proposal_id
t.integer :topic_id
t.timestamps
end

add_index :messages, :user_id
add_index :messages, :topic_id
add_index :messages, [:user_id, :proposal_id]
add_index :messages, [:is_private, :target_type, :target_id], :name => :comments_by_type
add_index :messages, [:is_read, :is_private, :target_type, :target_id], :name => :comments_by_type_by_read
Expand Down
2 changes: 2 additions & 0 deletions db/schema.rb
Expand Up @@ -32,12 +32,14 @@
t.string "target_type"
t.integer "user_id"
t.integer "proposal_id"
t.integer "topic_id"
t.datetime "created_at"
t.datetime "updated_at"
end

add_index "messages", ["is_private", "target_type", "target_id"], :name => "comments_by_type"
add_index "messages", ["is_read", "is_private", "target_type", "target_id"], :name => "comments_by_type_by_read"
add_index "messages", ["topic_id"], :name => "index_messages_on_topic_id"
add_index "messages", ["user_id", "is_private", "is_archived", "proposal_id"], :name => "comments_by_archived_by_proposal"
add_index "messages", ["user_id", "is_private", "target_type", "target_id"], :name => "comments_by_type_by_user"
add_index "messages", ["user_id", "proposal_id"], :name => "index_messages_on_user_id_and_proposal_id"
Expand Down
15 changes: 10 additions & 5 deletions db/seeds_for_dev.rb
Expand Up @@ -41,10 +41,10 @@
startup.confirm_user(u)

2.times { startup.submit_proposal(User.investors.sample, Proposal.make.attributes, 'draft') }
startup.submit_proposal(User.investors.sample, Proposal.make.attributes, 'submitted', Faker::Lorem.sentences * ' ')
startup.submit_proposal(user, Proposal.make.attributes, 'submitted', Faker::Lorem.sentences * ' ') if rand(5) == 0
startup.submit_proposal(User.investors.sample, Proposal.make.attributes, 'submitted', Faker::Lorem.sentence)
startup.submit_proposal(user, Proposal.make.attributes, 'submitted', Faker::Lorem.sentence) if rand(5) == 0
if rand(10) == 0
startup.submit_proposal(user, Proposal.make.attributes, 'submitted', Faker::Lorem.sentences * ' ')
startup.submit_proposal(user, Proposal.make.attributes, 'submitted', Faker::Lorem.sentence)
Message.last.mark_as_archived!
end
end
Expand All @@ -63,15 +63,20 @@

(5 + rand(5)).times do
User.order('RAND()').each do |u|
u.add_micro_post(Faker::Lorem.sentences * ' ')
u.add_micro_post(Faker::Lorem.sentence)
end
end

# private messages

User.all.each do |u|
20.times do
u.send_private_message(User.order('RAND()').first, Faker::Lorem.sentences * ' ')
target_user = User.order('RAND()').first
u.send_private_message(target_user, Faker::Lorem.sentence)
(2 + rand(2)).times do
rand(2).times { target_user.reply_private_message(Message.topics.last, Faker::Lorem.sentence) }
rand(2).times { u.reply_private_message(Message.topics.last, Faker::Lorem.sentence) }
end
end

u.sent_messages.order('RAND()').limit(5).each { |msg| msg.mark_as_read! }
Expand Down
1 change: 0 additions & 1 deletion spec/controllers/entrepreneurs_controller_spec.rb
@@ -1,7 +1,6 @@
require 'spec_helper'

describe EntrepreneursController do
it_behaves_like "ensure_ownership"
include_context "inherited_resources"

let(:current_user) { User.make! }
Expand Down
23 changes: 23 additions & 0 deletions spec/controllers/messages_controller_spec.rb
Expand Up @@ -24,4 +24,27 @@
startup.comments.first.content.should == 'hello world'
end
end

context "private messages" do
let(:target_user) { User.make! }

before do
current_user.send_private_message(target_user, 'Hello there!')
end

it "shows a topic" do
get :show_private_message, :id => 1

assigns(:topic).should == Message.topics.find(1)
end

it "replies to a topic" do
post :reply_private_message, :id => 1, :message => { :content => 'Yes dear!' }

topic = Message.topics.find(1)

assigns(:topic).should == topic
topic.replies.first.content.should == 'Yes dear!'
end
end
end
14 changes: 7 additions & 7 deletions spec/controllers/users_controller_spec.rb
Expand Up @@ -23,43 +23,43 @@

context "messages" do
it "shows inbox messages by default" do
get :messages
get :message_inboxes

assigns(:messages).should == current_user.inbox_messages
end

it "shows inbox messages" do
get :messages, :type => :inbox
get :message_inboxes, :type => :inbox

assigns(:messages).should == current_user.inbox_messages
end

it "shows sent messages" do
get :messages, :type => :sent_messages
get :message_inboxes, :type => :sent_messages

assigns(:messages).should == current_user.sent_messages
end

it "shows archived messages" do
get :messages, :type => :archived_messages
get :message_inboxes, :type => :archived_messages

assigns(:messages).should == current_user.archived_messages
end

it "shows new proposals" do
get :messages, :type => :inbox_proposals
get :message_inboxes, :type => :inbox_proposals

assigns(:messages).should == current_user.inbox_proposals
end

it "shows sent proposals" do
get :messages, :type => :sent_proposals
get :message_inboxes, :type => :sent_proposals

assigns(:messages).should == current_user.sent_proposals
end

it "shows archived proposals" do
get :messages, :type => :archived_proposals
get :message_inboxes, :type => :archived_proposals

assigns(:messages).should == current_user.archived_proposals
end
Expand Down

0 comments on commit 12eb19b

Please sign in to comment.