Comments(EmbeddedDocument) can be localized
[shapado:shapado.git] / app / models / answer.rb
1 class Answer
2   include MongoMapper::Document
3   include MongoMapperExt::Filter
4   include Support::Versionable
5   include Support::Voteable
6   include Shapado::Models::GeoCommon
7   timestamps!
8
9   key :_id, String
10
11   key :body, String, :required => true
12   key :language, String, :default => "en", :index => true
13   key :flags_count, Integer, :default => 0
14   key :banned, Boolean, :default => false, :index => true
15   key :wiki, Boolean, :default => false
16   key :anonymous, Boolean, :default => false, :index => true
17
18   key :user_id, String, :index => true
19   belongs_to :user
20
21   key :updated_by_id, String
22   belongs_to :updated_by, :class_name => "User"
23
24   key :question_id, String, :index => true
25   belongs_to :question
26
27   has_many :flags
28
29   has_many :comments, :order => "created_at asc"
30
31   validates_presence_of :user_id
32   validates_presence_of :question_id
33
34   versionable_keys :body
35   filterable_keys :body
36
37   validate :disallow_spam
38   validate :check_unique_answer, :if => lambda { |a| (!a.group.forum && !a.disable_limits?) }
39
40   before_destroy :unsolve_question
41
42   def ban
43     self.collection.update({:_id => self.id}, {:$set => {:banned => true}})
44   end
45
46   def self.ban(ids)
47     ids.each do |id|
48       self.collection.update({:_id => id}, {:$set => {:banned => true}})
49     end
50   end
51
52   def can_be_deleted_by?(user)
53     ok = (self.user_id == user.id && user.can_delete_own_comments_on?(self.group)) || user.mod_of?(self.group)
54     if !ok && user.can_delete_comments_on_own_questions_on?(self.group) && (q = self.question)
55       ok = (q.user_id == user.id)
56     end
57
58     ok
59   end
60
61   def check_unique_answer
62     check_answer = Answer.first(:question_id => self.question_id,
63                                :user_id => self.user_id)
64
65     if !check_answer.nil? && check_answer.id != self.id
66       self.errors.add(:limitation, "Your can only post one answer by question.")
67       return false
68     end
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
96   def ban
97     self.question.answer_removed!
98     unsolve_question
99     self.set({:banned => true})
100   end
101
102   def self.ban(ids)
103     self.find_each(:_id.in => ids, :select => [:question_id]) do |answer|
104       answer.ban
105     end
106   end
107
108   def to_html
109     RDiscount.new(self.body).to_html
110   end
111
112   def disable_limits?
113     self.user.present? && self.user.can_post_whithout_limits_on?(self.group)
114   end
115
116   def disallow_spam
117     if new? && !disable_limits?
118       eq_answer = Answer.first({:body => self.body,
119                                   :question_id => self.question_id,
120                                   :group_id => self.group_id
121                                 })
122
123       last_answer  = Answer.first(:user_id => self.user_id,
124                                    :question_id => self.question_id,
125                                    :group_id => self.group_id,
126                                    :order => "created_at desc")
127
128       valid = (eq_answer.nil? || eq_answer.id == self.id) &&
129               ((last_answer.nil?) || (Time.now - last_answer.created_at) > 20)
130       if !valid
131         self.errors.add(:body, "Your answer is duplicate.")
132       end
133     end
134   end
135
136   protected
137   def unsolve_question
138     if !self.question.nil? && self.question.answer_id == self.id
139       self.question.set({:answer_id => nil, :accepted => false})
140     end
141   end
142 end