diff --git a/app/models/mention.rb b/app/models/mention.rb
new file mode 100644
index 000000000..deb065b67
--- /dev/null
+++ b/app/models/mention.rb
@@ -0,0 +1,10 @@
+# Copyright (c) 2010, Diaspora Inc. This file is
+# licensed under the Affero General Public License version 3 or later. See
+# the COPYRIGHT file.
+
+class Mention < ActiveRecord::Base
+ belongs_to :post
+ belongs_to :person
+ validates_presence_of :post
+ validates_presence_of :person
+end
diff --git a/app/models/post.rb b/app/models/post.rb
index df2834370..98671c505 100644
--- a/app/models/post.rb
+++ b/app/models/post.rb
@@ -17,6 +17,7 @@ class Post < ActiveRecord::Base
has_many :comments, :order => 'created_at ASC', :dependent => :destroy
has_many :post_visibilities
has_many :aspects, :through => :post_visibilities
+ has_many :mentions, :dependent => :delete_all
belongs_to :person
cattr_reader :per_page
@@ -81,7 +82,7 @@ class Post < ActiveRecord::Base
else
user.add_post_to_aspects(local_post)
Rails.logger.info("event=receive payload_type=#{self.class} update=true status=complete sender=#{self.diaspora_handle} existing_post=#{local_post.id}")
- return local_post
+ return local_post
end
elsif !local_post
self.save
diff --git a/app/models/status_message.rb b/app/models/status_message.rb
index 9ee3c0e8c..dc500e0f9 100644
--- a/app/models/status_message.rb
+++ b/app/models/status_message.rb
@@ -43,17 +43,32 @@ class StatusMessage < Post
person = people.detect{ |p|
p.diaspora_handle == inner_captures.last
}
- person ? "#{ERB::Util.h(person.name)}" : inner_captures.first
+ person ? "#{ERB::Util.h(person.name)}" : ERB::Util.h(inner_captures.first)
end
form_message
end
def mentioned_people
+ if self.persisted?
+ create_mentions if self.mentions.empty?
+ self.mentions.includes(:person => :profile).map{ |mention| mention.person }
+ else
+ mentioned_people_from_string
+ end
+ end
+
+ def create_mentions
+ mentioned_people_from_string.each do |person|
+ self.mentions.create(:person => person)
+ end
+ end
+
+ def mentioned_people_from_string
regex = /@\{([^;]+); ([^\}]+)\}/
identifiers = self.raw_message.scan(regex).map do |match|
match.last
end
- Person.where(:diaspora_handle => identifiers)
+ identifiers.empty? ? [] : Person.where(:diaspora_handle => identifiers)
end
def to_activity
diff --git a/db/migrate/20110209204702_create_mentions.rb b/db/migrate/20110209204702_create_mentions.rb
new file mode 100644
index 000000000..d4bbbf39e
--- /dev/null
+++ b/db/migrate/20110209204702_create_mentions.rb
@@ -0,0 +1,15 @@
+class CreateMentions < ActiveRecord::Migration
+ def self.up
+ create_table :mentions do |t|
+ t.integer :post_id, :null => false
+ t.integer :person_id, :null => false
+ end
+ add_index :mentions, :post_id
+ add_index :mentions, :person_id
+ add_index :mentions, [:person_id, :post_id], :unique => true
+ end
+
+ def self.down
+ drop_table :mentions
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index c4fbefa11..3c0a97c16 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20110202015222) do
+ActiveRecord::Schema.define(:version => 20110209204702) do
create_table "aspect_memberships", :force => true do |t|
t.integer "aspect_id", :null => false
@@ -95,6 +95,15 @@ ActiveRecord::Schema.define(:version => 20110202015222) do
add_index "invitations", ["recipient_id"], :name => "index_invitations_on_recipient_id"
add_index "invitations", ["sender_id"], :name => "index_invitations_on_sender_id"
+ create_table "mentions", :force => true do |t|
+ t.integer "post_id", :null => false
+ t.integer "person_id", :null => false
+ end
+
+ add_index "mentions", ["person_id", "post_id"], :name => "index_mentions_on_person_id_and_post_id", :unique => true
+ add_index "mentions", ["person_id"], :name => "index_mentions_on_person_id"
+ add_index "mentions", ["post_id"], :name => "index_mentions_on_post_id"
+
create_table "mongo_aspect_memberships", :force => true do |t|
t.string "aspect_mongo_id"
t.string "contact_mongo_id"
diff --git a/spec/models/status_message_spec.rb b/spec/models/status_message_spec.rb
index acf455176..320b65086 100644
--- a/spec/models/status_message_spec.rb
+++ b/spec/models/status_message_spec.rb
@@ -73,8 +73,8 @@ STR
describe '#formatted_message' do
it 'adds the links in the formated message text' do
@sm.formatted_message.should == <<-STR
-#{link_to(@people[0].name, person_path(@people[0]))} can mention people like Raphael #{link_to(@people[1].name, person_path(@people[1]))}
-can mention people like Raphaellike Raphael #{link_to(@people[2].name, person_path(@people[2]))} can mention people like Raph
+#{link_to(@people[0].name, person_path(@people[0]), :class => 'mention')} can mention people like Raphael #{link_to(@people[1].name, person_path(@people[1]), :class => 'mention')}
+can mention people like Raphaellike Raphael #{link_to(@people[2].name, person_path(@people[2]), :class => 'mention')} can mention people like Raph
STR
end
it 'leaves the name of people that cannot be found' do
@@ -102,8 +102,33 @@ STR
end
end
- it 'extracts the mentioned people from the message' do
- @sm.mentioned_people.to_set.should == @people.to_set
+ describe '#mentioned_people_from_string' do
+ it 'extracts the mentioned people from the message' do
+ @sm.mentioned_people_from_string.to_set.should == @people.to_set
+ end
+ end
+ describe '#create_mentions' do
+ it 'creates a mention for everyone mentioned in the message' do
+ @sm.should_receive(:mentioned_people_from_string).and_return(@people)
+ @sm.mentions.delete_all
+ @sm.create_mentions
+ @sm.mentions(true).map{|m| m.person}.to_set.should == @people.to_set
+ end
+ end
+ describe '#mentioned_people' do
+ it 'calls create_mentions if there are no mentions in the db' do
+ @sm.mentions.delete_all
+ @sm.should_receive(:create_mentions)
+ @sm.mentioned_people
+ end
+ it 'returns the mentioned people' do
+ @sm.mentions.delete_all
+ @sm.mentioned_people.to_set.should == @people.to_set
+ end
+ it 'does not call create_mentions if there are mentions in the db' do
+ @sm.should_not_receive(:create_mentions)
+ @sm.mentioned_people
+ end
end
end
describe "XML" do