implemented activities tab
[shapado:piglops-shapado.git] / app / models / answer.rb
1 class Answer
2   include Mongoid::Document
3   include Mongoid::Timestamps
4   include MongoidExt::Filter
5   include MongoidExt::Random
6
7   include Support::Versionable
8   include Support::Voteable
9   include Shapado::Models::GeoCommon
10   include Shapado::Models::Trackable
11
12   track_activities :user, :question, :body, :language, :scope => [:group_id]
13
14   identity :type => String
15
16   field :body, :type => String, :required => true
17   field :language, :type =>  String, :default => "en"
18   index :language
19   field :flags_count, :type =>  Integer, :default => 0
20   field :banned, :type =>  Boolean, :default => false
21   index :banned
22   field :wiki, :type => Boolean, :default => false
23   field :anonymous, :type => Boolean, :default => false
24   index :anonymous
25   field :short_url, :type => String
26
27   field :rewarded, :type => Boolean, :default => false
28
29   field :favoriters_count, :type => Integer, :default => 0
30   references_and_referenced_in_many :favoriters, :class_name => "User"
31
32   referenced_in :group
33   index :group_id
34
35   referenced_in :user
36   index :user_id
37
38   referenced_in :updated_by, :class_name => "User"
39   referenced_in :original_question, :class_name => "Question"
40
41   referenced_in :question
42   index :question_id
43
44   embeds_many :flags, :as => "flaggable"
45   embeds_many :comments, :as => "commentable"
46
47   validates_presence_of :user_id
48   validates_presence_of :question_id
49
50   versionable_keys :body
51   filterable_keys :body
52
53   validate :disallow_spam
54   validate :check_unique_answer, :if => lambda { |a| (!a.group.forum && !a.disable_limits?) }
55
56   before_destroy :unsolve_question
57
58   def self.minimal
59     without(:_keywords, :flags, :votes, :versions)
60   end
61
62   def can_be_deleted_by?(user)
63     ok = (self.user_id == user.id && user.can_delete_own_comments_on?(self.group)) || user.mod_of?(self.group)
64     if !ok && user.can_delete_comments_on_own_questions_on?(self.group) && (q = self.question)
65       ok = (q.user_id == user.id)
66     end
67
68     ok
69   end
70
71   def on_add_vote(v, voter)
72     if v > 0
73       self.user.update_reputation(:answer_receives_up_vote, self.group)
74       voter.on_activity(:vote_up_answer, self.group)
75     else
76       self.user.update_reputation(:answer_receives_down_vote, self.group)
77       voter.on_activity(:vote_down_answer, self.group)
78     end
79   end
80
81   def on_remove_vote(v, voter)
82     if v > 0
83       self.user.update_reputation(:answer_undo_up_vote, self.group)
84       voter.on_activity(:undo_vote_up_answer, self.group)
85     else
86       self.user.update_reputation(:answer_undo_down_vote, self.group)
87       voter.on_activity(:undo_vote_down_answer, self.group)
88     end
89   end
90
91   def flagged!
92     self.increment(:flags_count => 1)
93   end
94
95   def ban
96     self.question.answer_removed!
97     unsolve_question
98     self.override({:banned => true})
99   end
100
101   def self.ban(ids)
102     self.where(:_id.in => ids).only(:question_id).each do |answer|
103       answer.ban
104     end
105   end
106
107   def unban
108     self.override(:banned => false)
109   end
110
111   def self.unban(ids, options = {})
112     self.override({:_id => {"$in" => ids}}.merge(options), {:banned => false})
113   end
114
115   def to_html
116     RDiscount.new(self.body).to_html
117   end
118
119   def disable_limits?
120     self.user.present? && self.user.can_post_whithout_limits_on?(self.group)
121   end
122
123   def check_unique_answer
124     if Answer.where(:question_id => self.question_id,
125                     :user_id => self.user_id,
126                     :_id.ne => self.id).count > 0
127       self.errors.add(:limitation, "Your can only post one answer by question.")
128       return false
129     end
130     return true
131   end
132
133   def disallow_spam
134     if new? && !disable_limits?
135       eq_answer = Answer.where({:body => self.body,
136                                   :question_id => self.question_id,
137                                   :group_id => self.group_id
138                                 }).first
139
140       last_answer  = Answer.where({:user_id => self.user_id,
141                                    :question_id => self.question_id,
142                                    :group_id => self.group_id}).order_by(:created_at.desc).first
143
144       valid = (eq_answer.nil? || eq_answer.id == self.id) &&
145               ((last_answer.nil?) || (Time.now - last_answer.created_at) > 20)
146       if !valid
147         self.errors.add(:body, "Your answer is duplicate.")
148       end
149       return valid
150     end
151   end
152
153   def add_favorite!(user)
154     unless favorite_for?(user)
155       self.push_uniq(:favoriter_ids => user.id)
156       self.increment(:favorites_count => 1)
157     end
158   end
159
160   def remove_favorite!(user)
161     if favorite_for?(user)
162       self.pull(:favoriter_ids => user.id)
163       self.decrement(:favorites_count => 1)
164     end
165   end
166
167   def favorite_for?(user)
168     self.favoriter_ids && self.favoriter_ids.include?(user.id)
169   end
170
171   protected
172   def unsolve_question
173     if !self.question.nil? && self.question.answer_id == self.id
174       self.question.override({:answer_id => nil, :accepted => false})
175     end
176   end
177 end