public
Description: The open source social networking platform in Ruby on Rails from the author of RailsSpace
Homepage: http://insoshi.com
Clone URL: git://github.com/insoshi/insoshi.git
insoshi / app / models / connection.rb
100644 137 lines (117 sloc) 3.999 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# == Schema Information
# Schema version: 28
#
# Table name: connections
#
# id :integer(11) not null, primary key
# person_id :integer(11)
# contact_id :integer(11)
# status :integer(11)
# accepted_at :datetime
# created_at :datetime
# updated_at :datetime
#
 
class Connection < ActiveRecord::Base
  extend ActivityLogger
  extend PreferencesHelper
  
  belongs_to :person
  belongs_to :contact, :class_name => "Person", :foreign_key => "contact_id"
  has_many :activities, :foreign_key => "item_id", :dependent => :destroy
  validates_presence_of :person_id, :contact_id
  
  # Status codes.
  ACCEPTED = 0
  REQUESTED = 1
  PENDING = 2
  
  # Accept a connection request (instance method).
  # Each connection is really two rows, so delegate this method
  # to Connection.accept to wrap the whole thing in a transaction.
  def accept
    Connection.accept(person_id, contact_id)
  end
  
  def breakup
    Connection.breakup(person_id, contact_id)
  end
  
  class << self
  
    # Return true if the persons are (possibly pending) connections.
    def exists?(person, contact)
      not conn(person, contact).nil?
    end
    
    alias exist? exists?
  
    # Make a pending connection request.
    def request(person, contact, send_mail = nil)
      if send_mail.nil?
        send_mail = global_prefs.email_notifications? &&
                    contact.connection_notifications?
      end
      if person == contact or Connection.exists?(person, contact)
        nil
      else
        transaction do
          create(:person => person, :contact => contact, :status => PENDING)
          create(:person => contact, :contact => person, :status => REQUESTED)
        end
        if send_mail
          # The order here is important: the mail is sent *to* the contact,
          # so the connection should be from the contact's point of view.
          connection = conn(contact, person)
          PersonMailer.deliver_connection_request(connection)
        end
        true
      end
    end
  
    # Accept a connection request.
    def accept(person, contact)
      transaction do
        accepted_at = Time.now
        accept_one_side(person, contact, accepted_at)
        accept_one_side(contact, person, accepted_at)
      end
      # Exclude the first admin to prevent everyone's feed from
      # filling up with new registrants.
      unless [person, contact].include?(Person.find_first_admin)
        log_activity(conn(person, contact))
      end
    end
    
    def connect(person, contact, send_mail = nil)
      transaction do
        request(person, contact, send_mail)
        accept(person, contact)
      end
      conn(person, contact)
    end
  
    # Delete a connection or cancel a pending request.
    def breakup(person, contact)
      transaction do
        destroy(conn(person, contact))
        destroy(conn(contact, person))
      end
    end
  
    # Return a connection based on the person and contact.
    def conn(person, contact)
      find_by_person_id_and_contact_id(person, contact)
    end
    
    def accepted?(person, contact)
      conn(person, contact).status == ACCEPTED
    end
    
    def connected?(person, contact)
      exist?(person, contact) and accepted?(person, contact)
    end
    
    def pending?(person, contact)
      exist?(person, contact) and conn(contact,person).status == PENDING
    end
  end
  
  private
  
  class << self
    # Update the db with one side of an accepted connection request.
    def accept_one_side(person, contact, accepted_at)
      conn = conn(person, contact)
      conn.update_attributes!(:status => ACCEPTED,
                              :accepted_at => accepted_at)
    end
  
    def log_activity(conn)
      activity = Activity.create!(:item => conn, :person => conn.person)
      add_activities(:activity => activity, :person => conn.person)
      add_activities(:activity => activity, :person => conn.contact)
    end
  end
end