app/models/activity.rb
class Activity < ActiveRecord::Base
include Extender::Achievements
NOT_UNDO = 0
UNDO = 1
has_many :activity_points
accepts_nested_attributes_for :activity_points
belongs_to :activityable, :polymorphic => true
belongs_to :activityable_thr, :foreign_key => :activityable_id, :class_name => "Thr"
belongs_to :user
belongs_to :badge
belongs_to :tag
attr_protected # accessible all atrrs
scope :activityable_object, lambda {|o| where(:activityable_id=>o.id,:activityable_type=>o.class.to_s) }
scope :not_undo, where(:undo=> NOT_UNDO)
scope :flagged, where(:name=> 'flag')
scope :close_reported, where(:name=> 'close')
scope :flagged_or_close, where(:name => ['close','flag'])
scope :favs, where(:name => "fav",:undo=> NOT_UNDO)
scope :votes, where("name LIKE ? AND undo=?","%vote%",NOT_UNDO)
scope :votes_for_thrs_and_ans, where(:name => ["vote_up","vote_down"],:activityable_type => ['An','Thr'],:undo=> NOT_UNDO)
scope :votes_up, where("name LIKE ? AND undo=?","%vote_up%",NOT_UNDO)
scope :votes_down, where("name LIKE ? AND undo=?","%vote_down%",NOT_UNDO)
scope :answers, where(:name=>'create',:undo=> NOT_UNDO,:activityable_type=>'An')
scope :public_activities, where("name NOT IN (?) AND undo=?",['day_activity','update_user'],NOT_UNDO)
scope :created_today, where("CAST(created_at + interval '? seconds' AS date) = CAST(? AS date)", Time.zone.utc_offset, Time.now)
scope :flagged_today, flagged.where("CAST(created_at + interval '? seconds' AS date) = CAST(? AS date)", Time.zone.utc_offset, Time.now)
validate :check_flagging_and_closing, :if => :flagging_or_closing?
after_save :set_activity_at_for_activityable
def build_points(hash)
if hash[:user_id]
if points_receiver(hash[:user_id])
if ActivityPoint.not_undo.where(:user_id=>hash[:user_id]).
created_today.sum(:value) >= APP_REPUTATION['max_rep_by_up_votes']
hash[:value] = 0
end
end
else
hash[:user_id] = self.user_id
end
self.activity_points.build(hash)
end
def points_receiver(user_id)
# ten user_id ktory nie jest tworca activity, jest otrzymujacym punkty
self.user_id != user_id
end
def answer_created?
name == 'create' && activityable_type == 'An'
end
def answer_resolved?
name == 'an_resolved'
end
def comment_created?
name == 'create' && activityable_type == 'Comment'
end
def vote_expired?
self.created_at <= Time.now - APP_VOTING_CONFIG['days_to_cancel_vote'].days
end
def undo_activity
self.undo = UNDO
self.undo_at = Time.now
self.activity_points.each do |points|
points.update_attributes(:undo => ActivityPoint::UNDO)
end
self.save(:validate=>false)
end
def name_humanized
unless self.name.empty?
if self.activityable
I18n.t("activities.names.#{self.name}_#{self.activityable.class.name.downcase}")
else
I18n.t("activities.names.#{self.name}")
end
end
end
private
def flagging?
self.name == 'flag'
end
def closing?
self.name == 'close'
end
def flagging_or_closing?
self.name == 'flag' || self.name == 'close'
end
def check_flagging_and_closing
if flagging?
if self.user.activities.flagged_today.count > APP_VOTING_CONFIG['max_flag_par_day']
errors.add(:base,:too_many_reports)
end
end
if flagging? && activity = self.activityable.activities.flagged.where(:user_id=>self.user_id).first
errors.add(:base,:already_reported,:content=>activity.extra)
end
if closing? && self.activityable.activities.close_reported.where(:user_id=>self.user_id).first
errors.add(:base,:closed_question)
end
if self.extra.blank?
errors.add(:base,:report_reason)
end
end
def set_activity_for(o)
o.activity_at = Time.now
o.save(:validate => false)
end
def set_activity_for_thr(thr)
thr.last_activity_user_id = user_id
thr.last_activity_id = id
set_activity_for(thr)
# if there was activity in thr since last visit send to all subscribers except activity caller
# REMEBER! to check the last_view field when using delayed_job or resque background job
if subscriptions = Subscription.joins(:subscribable_thr).
where("subscriptions.user_id <> ? AND thrs.id=?",user_id,thr.id).
where("subscriptions.last_view < thrs.activity_at")
subscriptions.each do |sub|
# jesli zaznaczyl ze chce otrzymywac i rzeczywiscie zostala taka akcja wykonana to
if (sub.user.user_setting.notify_answers==1 && answer_created?) ||
(sub.user.user_setting.notify_comments==1 && comment_created?) ||
(sub.user.user_setting.notify_answer_resolved==1 && answer_resolved?)
p "send mail to #{sub.user.name}"
Mailer.notify_thr_activity(sub.user,thr).deliver
else
p 'not sending because user uncheck subscription or there was undefined action'
end
end
end
end
def set_activity_at_for_activityable
if ['create','delete','revise','an_resolved','an_unresolved','close'].include? name
if activityable.class == Thr
set_activity_for_thr(activityable)
elsif activityable.class == An
set_activity_for(activityable)
set_activity_for_thr(activityable.thr)
elsif activityable.class == Comment
# p 'add activity for comment'
set_activity_for(activityable) # for comment
if activityable.commentable.class == Thr
# p 'add comment for question'
set_activity_for_thr(activityable.commentable) # for question
elsif activityable.commentable.class == An
# p 'add comment for question and answers'
set_activity_for(activityable.commentable) # for answer
set_activity_for_thr(activityable.commentable.thr) # for question
end
end
end
end
end