Skip to content

Commit 12eb19b

Browse files
committed
Threaded private messages, replies and some code refactoring.
1 parent dcf9d86 commit 12eb19b

26 files changed

+143
-51
lines changed

app/controllers/messages_controller.rb

+17
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ class MessagesController < ApplicationController
77

88
has_scope :p, :default => 1
99

10+
before_filter :hide_sidebar, :only => [:show_private_message]
11+
before_filter :ensure_ownership, :only => [:show_private_message, :reply_private_message]
12+
1013
def create
1114
resource = parent.add_comment(current_user, params[:message][:content])
1215

@@ -15,4 +18,18 @@ def create
1518
format.html { redirect_to :back }
1619
end
1720
end
21+
22+
def show_private_message
23+
@topic = Message.topics.find(params[:id])
24+
end
25+
26+
def reply_private_message
27+
@topic = Message.topics.find(params[:id])
28+
result = current_user.reply_private_message(@topic, params[:message][:content])
29+
30+
respond_to do |format|
31+
format.json { render :json => result }
32+
format.html { redirect_to :back }
33+
end
34+
end
1835
end

app/controllers/users_controller.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ class UsersController < ApplicationController
33

44
has_scope :page, :default => 1
55

6-
before_filter :hide_sidebar, :only => [:show, :messages]
6+
before_filter :hide_sidebar, :only => [:show, :message_inboxes]
77

88
def home
99
@micro_posts = resource.followed_micro_posts.page(params[:p])
@@ -13,7 +13,7 @@ def show
1313
@micro_posts = resource.micro_posts.page(params[:p])
1414
end
1515

16-
def messages
16+
def message_inboxes
1717
@messages = case params[:type].try(:to_sym)
1818
when :sent_messages then current_user.sent_messages
1919
when :archived_messages then current_user.archived_messages

app/models/message.rb

+7-2
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,17 @@ class Message < ActiveRecord::Base
33
belongs_to :user, :counter_cache => :messages_count
44
belongs_to :target, :polymorphic => true, :counter_cache => :comments_count
55

6+
belongs_to :topic, :class_name => 'Message', :foreign_key => 'topic_id'
7+
has_many :replies, :class_name => 'Message', :foreign_key => 'topic_id'
8+
69
validates :content, :presence => true,
710
:length => { :maximum => 140 }
811

912
scope :default_order, order('created_at DESC')
10-
scope :public, where(:is_private => false)
11-
scope :private, where(:is_private => true)
13+
scope :topics, where { topic_id == nil }
14+
scope :replies, where { topic_id != nil }
15+
scope :public_only, where(:is_private => false)
16+
scope :private_only, where(:is_private => true)
1217
scope :read, where(:is_read => true)
1318
scope :unread, where(:is_read => false)
1419
scope :archived, where(:is_archived => true)

app/models/user.rb

+13-3
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,11 @@ class User < ActiveRecord::Base
5252
before_save :email_nomarlisation
5353

5454
def incoming_messages
55-
comments.private
55+
comments.private_only.topics
5656
end
5757

5858
def outgoing_messages
59-
messages.on_users.private
59+
messages.on_users.private_only.topics
6060
end
6161

6262
def inbox_messages
@@ -108,14 +108,24 @@ def has_new_messages?
108108
end
109109

110110
def send_private_message(target_user, content, extras = {})
111-
messages.create({
111+
messages.create!({
112112
:content => content,
113113
:is_private => true,
114114
:target_id => target_user.id,
115115
:target_type => 'User'
116116
}.merge(extras)) && reload
117117
end
118118

119+
def reply_private_message(topic, content, extras = {})
120+
messages.create!({
121+
:content => content,
122+
:is_private => true,
123+
:target_id => topic.user.id,
124+
:target_type => 'User',
125+
:topic_id => topic.id
126+
}.merge(extras)) && reload
127+
end
128+
119129
def add_micro_post(content)
120130
unless content.blank?
121131
messages.create(:content => content) && reload

app/views/layouts/userbars/_topnav.html.slim

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ h3
55
= link_to t('label.edit'), edit_registration_path(current_user)
66
' ) |
77
- if current_user.has_new_messages?
8-
= link_to "#{pluralize(current_user.inbox_messages.unread.count, t('label.new_message'))}!", my_messages_path(:inbox_messages), :class => 'new'
8+
= link_to "#{pluralize(current_user.inbox_messages.unread.count, t('label.new_message'))}!", my_message_inbox_path(:inbox_messages), :class => 'new'
99
- else
10-
= link_to "#{t('label.messages')} (#{current_user.inbox_messages.count})", my_messages_path(:inbox_messages)
10+
= link_to "#{t('label.messages')} (#{current_user.inbox_messages.count})", my_message_inbox_path(:inbox_messages)
1111
' |
1212
= link_to t('label.sign_out'), destroy_user_session_path

app/views/messages/_index.html.slim

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
- if collection.any?
22
ul#messages
33
- collection.each do |resource|
4-
li.message= render 'messages/show', :resource => resource
4+
li.message= render 'messages/show', :resource => resource, :meta => meta
55
= show_pagination collection, :param_name => :p

app/views/messages/_show.html.slim

+6-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,9 @@ hr
55
.message_meta
66
=' link_to resource.user.name, username_path(resource.user.username)
77
= time_ago(resource.created_at)
8-
.message_content= resource.content
8+
.message_content
9+
- if meta[:linkable]
10+
= link_to resource.content, my_private_message_path(resource)
11+
- else
12+
= resource.content
13+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.grid_3
2+
= render 'users/message_inboxes'
3+
.grid_9
4+
ul#messages
5+
li.message= render 'show', :resource => @topic, :meta => {}
6+
7+
- @topic.replies.each do |reply|
8+
li.message= render 'show', :resource => reply, :meta => {}
9+
br
10+
= render 'new', :url => my_private_message_path(@topic)
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
= render 'messages/new', :url => startup_comments_path(resource)
2-
= render 'messages/index', :collection => resource.comments.page(params[:p])
2+
= render 'messages/index', :collection => resource.comments.page(params[:p]), :meta => {}

app/views/startups/_mini_profile.html.slim

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
= render 'shared/editable', :edit_target => '#profile_details'
33

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

app/views/users/_index.html.slim

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
ul.resource_list.user_list
22
- collection.each do |user|
3-
li.mini_profile data-target_link="profile_team/#{meta[:parent].try(:id)}" data-edit_target="#profile_team"
3+
li.mini_profile data-target_link="#{startup_profile_team_path(meta[:parent])}" data-edit_target="#profile_team"
44
- unless meta[:role_identifier]
55
hr
66

app/views/users/_message_inboxes.html.slim

+6-6
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
hr
44
h3= t('label.private_messages')
55
ul
6-
li= link_to_current t('label.inbox_messages'), my_messages_path(:inbox_messages)
7-
li= link_to_current t('label.sent_messages') , my_messages_path(:sent_messages)
8-
li= link_to_current t('label.archived_messages') , my_messages_path(:archived_messages)
6+
li= link_to_current t('label.inbox_messages'), my_message_inbox_path(:inbox_messages)
7+
li= link_to_current t('label.sent_messages') , my_message_inbox_path(:sent_messages)
8+
li= link_to_current t('label.archived_messages') , my_message_inbox_path(:archived_messages)
99
hr
1010
h3= t('label.startup_proposals')
1111
ul
12-
li= link_to_current t('label.inbox_proposals') , my_messages_path(:inbox_proposals)
13-
li= link_to_current t('label.sent_proposals') , my_messages_path(:sent_proposals)
14-
li= link_to_current t('label.archived_proposals') , my_messages_path(:archived_proposals)
12+
li= link_to_current t('label.inbox_proposals') , my_message_inbox_path(:inbox_proposals)
13+
li= link_to_current t('label.sent_proposals') , my_message_inbox_path(:sent_proposals)
14+
li= link_to_current t('label.archived_proposals') , my_message_inbox_path(:archived_proposals)

app/views/users/home.html.slim

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
= render 'messages/new', :url => my_micro_posts_path
2-
= render 'messages/index', :collection => @micro_posts
2+
= render 'messages/index', :collection => @micro_posts, :meta => {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.grid_3
2+
= render 'message_inboxes'
3+
.grid_9
4+
= render 'messages/index', :collection => @messages, :meta => { :linkable => true }

app/views/users/messages.html.slim

-4
This file was deleted.

app/views/users/show.html.slim

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
= render 'users/invested_in', :user => resource if resource.is_investor?
55

66
.grid_6
7-
= render 'messages/index', :collection => @micro_posts
7+
= render 'messages/index', :collection => @micro_posts, :meta => {}

config/routes.rb

+13-8
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,20 @@
2121
end
2222
end
2323

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

26-
match 'my/profile' => 'users#show', :via => :get
27-
match 'my/home' => 'users#home', :via => :get
28-
match 'my/messages(/:type)' => 'users#messages', :via => :get, :as => :my_messages
29-
match 'my/micro_posts' => 'users#add_micro_post', :via => :post
27+
match 'u/:username' => 'users#show', :via => :get, :as => :username
3028

31-
match 'my/follow/:target_id' => 'users#follow_target', :via => :post, :as => :follow_target
32-
match 'my/unfollow/:target_id' => 'users#unfollow_target', :via => :post, :as => :unfollow_target
29+
match 'my/profile' => 'users#show', :via => :get
30+
match 'my/home' => 'users#home', :via => :get
31+
match 'my/private_messages/:id' => 'messages#show_private_message', :via => :get, :as => :my_private_message
32+
match 'my/private_messages/:id' => 'messages#reply_private_message', :via => :post, :as => :my_private_message
33+
match 'my/message_inboxes(/:type)' => 'users#message_inboxes', :via => :get, :as => :my_message_inbox
34+
match 'my/micro_posts' => 'users#add_micro_post', :via => :post
35+
36+
match 'my/follow/:target_id' => 'users#follow_target', :via => :post, :as => :follow_target
37+
match 'my/unfollow/:target_id' => 'users#unfollow_target', :via => :post, :as => :unfollow_target
3338

3439
# The priority is based upon order of creation:
3540
# first created -> highest priority.
@@ -86,5 +91,5 @@
8691

8792
# This is a legacy wild controller route that's not recommended for RESTful applications.
8893
# Note: This route will make all actions in every controller accessible via GET requests.
89-
match ':controller(/:action(/:id(.:format)))'
94+
# match ':controller(/:action(/:id(.:format)))'
9095
end

db/migrate/20110525132902_create_messages.rb

+2
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ def change
99
t.string :target_type
1010
t.integer :user_id
1111
t.integer :proposal_id
12+
t.integer :topic_id
1213
t.timestamps
1314
end
1415

1516
add_index :messages, :user_id
17+
add_index :messages, :topic_id
1618
add_index :messages, [:user_id, :proposal_id]
1719
add_index :messages, [:is_private, :target_type, :target_id], :name => :comments_by_type
1820
add_index :messages, [:is_read, :is_private, :target_type, :target_id], :name => :comments_by_type_by_read

db/schema.rb

+2
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,14 @@
3232
t.string "target_type"
3333
t.integer "user_id"
3434
t.integer "proposal_id"
35+
t.integer "topic_id"
3536
t.datetime "created_at"
3637
t.datetime "updated_at"
3738
end
3839

3940
add_index "messages", ["is_private", "target_type", "target_id"], :name => "comments_by_type"
4041
add_index "messages", ["is_read", "is_private", "target_type", "target_id"], :name => "comments_by_type_by_read"
42+
add_index "messages", ["topic_id"], :name => "index_messages_on_topic_id"
4143
add_index "messages", ["user_id", "is_private", "is_archived", "proposal_id"], :name => "comments_by_archived_by_proposal"
4244
add_index "messages", ["user_id", "is_private", "target_type", "target_id"], :name => "comments_by_type_by_user"
4345
add_index "messages", ["user_id", "proposal_id"], :name => "index_messages_on_user_id_and_proposal_id"

db/seeds_for_dev.rb

+10-5
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@
4141
startup.confirm_user(u)
4242

4343
2.times { startup.submit_proposal(User.investors.sample, Proposal.make.attributes, 'draft') }
44-
startup.submit_proposal(User.investors.sample, Proposal.make.attributes, 'submitted', Faker::Lorem.sentences * ' ')
45-
startup.submit_proposal(user, Proposal.make.attributes, 'submitted', Faker::Lorem.sentences * ' ') if rand(5) == 0
44+
startup.submit_proposal(User.investors.sample, Proposal.make.attributes, 'submitted', Faker::Lorem.sentence)
45+
startup.submit_proposal(user, Proposal.make.attributes, 'submitted', Faker::Lorem.sentence) if rand(5) == 0
4646
if rand(10) == 0
47-
startup.submit_proposal(user, Proposal.make.attributes, 'submitted', Faker::Lorem.sentences * ' ')
47+
startup.submit_proposal(user, Proposal.make.attributes, 'submitted', Faker::Lorem.sentence)
4848
Message.last.mark_as_archived!
4949
end
5050
end
@@ -63,15 +63,20 @@
6363

6464
(5 + rand(5)).times do
6565
User.order('RAND()').each do |u|
66-
u.add_micro_post(Faker::Lorem.sentences * ' ')
66+
u.add_micro_post(Faker::Lorem.sentence)
6767
end
6868
end
6969

7070
# private messages
7171

7272
User.all.each do |u|
7373
20.times do
74-
u.send_private_message(User.order('RAND()').first, Faker::Lorem.sentences * ' ')
74+
target_user = User.order('RAND()').first
75+
u.send_private_message(target_user, Faker::Lorem.sentence)
76+
(2 + rand(2)).times do
77+
rand(2).times { target_user.reply_private_message(Message.topics.last, Faker::Lorem.sentence) }
78+
rand(2).times { u.reply_private_message(Message.topics.last, Faker::Lorem.sentence) }
79+
end
7580
end
7681

7782
u.sent_messages.order('RAND()').limit(5).each { |msg| msg.mark_as_read! }

spec/controllers/entrepreneurs_controller_spec.rb

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
require 'spec_helper'
22

33
describe EntrepreneursController do
4-
it_behaves_like "ensure_ownership"
54
include_context "inherited_resources"
65

76
let(:current_user) { User.make! }

spec/controllers/messages_controller_spec.rb

+23
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,27 @@
2424
startup.comments.first.content.should == 'hello world'
2525
end
2626
end
27+
28+
context "private messages" do
29+
let(:target_user) { User.make! }
30+
31+
before do
32+
current_user.send_private_message(target_user, 'Hello there!')
33+
end
34+
35+
it "shows a topic" do
36+
get :show_private_message, :id => 1
37+
38+
assigns(:topic).should == Message.topics.find(1)
39+
end
40+
41+
it "replies to a topic" do
42+
post :reply_private_message, :id => 1, :message => { :content => 'Yes dear!' }
43+
44+
topic = Message.topics.find(1)
45+
46+
assigns(:topic).should == topic
47+
topic.replies.first.content.should == 'Yes dear!'
48+
end
49+
end
2750
end

spec/controllers/users_controller_spec.rb

+7-7
Original file line numberDiff line numberDiff line change
@@ -23,43 +23,43 @@
2323

2424
context "messages" do
2525
it "shows inbox messages by default" do
26-
get :messages
26+
get :message_inboxes
2727

2828
assigns(:messages).should == current_user.inbox_messages
2929
end
3030

3131
it "shows inbox messages" do
32-
get :messages, :type => :inbox
32+
get :message_inboxes, :type => :inbox
3333

3434
assigns(:messages).should == current_user.inbox_messages
3535
end
3636

3737
it "shows sent messages" do
38-
get :messages, :type => :sent_messages
38+
get :message_inboxes, :type => :sent_messages
3939

4040
assigns(:messages).should == current_user.sent_messages
4141
end
4242

4343
it "shows archived messages" do
44-
get :messages, :type => :archived_messages
44+
get :message_inboxes, :type => :archived_messages
4545

4646
assigns(:messages).should == current_user.archived_messages
4747
end
4848

4949
it "shows new proposals" do
50-
get :messages, :type => :inbox_proposals
50+
get :message_inboxes, :type => :inbox_proposals
5151

5252
assigns(:messages).should == current_user.inbox_proposals
5353
end
5454

5555
it "shows sent proposals" do
56-
get :messages, :type => :sent_proposals
56+
get :message_inboxes, :type => :sent_proposals
5757

5858
assigns(:messages).should == current_user.sent_proposals
5959
end
6060

6161
it "shows archived proposals" do
62-
get :messages, :type => :archived_proposals
62+
get :message_inboxes, :type => :archived_proposals
6363

6464
assigns(:messages).should == current_user.archived_proposals
6565
end

0 commit comments

Comments
 (0)