crewmate/crewmate

View on GitHub
app/models/activity.rb

Summary

Maintainability
A
1 hr
Test Coverage
# -*- encoding : utf-8 -*-
class Activity < ActiveRecord::Base

  belongs_to :target, :polymorphic => true
  belongs_to :comment_target, :polymorphic => true
  belongs_to :user
  belongs_to :project

  scope :for_task_lists, lambda{ where("target_type = 'TaskList' OR target_type = 'Task' OR comment_target_type = 'TaskList' OR comment_target_type = 'Task'") }
  scope :for_conversations, lambda{ where("target_type = 'Conversation' OR comment_target_type = 'Conversation'") }
  scope :for_tasks, where("target_type = ? OR comment_target_type = ?", "Task", "Task" )
  scope :in_targets, lambda {|targets| where ["target_id IN (?) OR comment_target_id IN (?)", *(Array(targets).collect(&:id)*2)] }
  scope :latest, lambda{ limit_per_page.by_id }
  scope :in_projects, lambda { |projects| where(:project_id => Array(projects).collect(&:id)) }
  scope :limit_per_page, lambda{ limit(Teambox.config.activities_per_page) }
  scope :by_id, lambda{ order('id DESC') }
  scope :by_updated, lambda{ order('updated_at DESC') }
  scope :threads, lambda{ where("target_type != 'Comment'") }
  scope :before, lambda { |activity_id| where("id < ?", activity_id) }
  scope :after, lambda { |activity_id| where("id > ?", activity_id) }
  scope :from_user, lambda { |user| where(:user_id => user.id) }

  def self.log(project,target,action,creator_id)
    project_id = project.try(:id)
    return if project.try(:is_importing)

    if target.is_a? Comment
      comment_target_type = target.target_type
      comment_target_id = target.target_id
      # touch activity related to that comment's thread
      Activity.where(:target_type => comment_target_type, :target_id => comment_target_id).last.try(:touch)
    end

    activity = Activity.new(
      :project_id => project_id,
      :target => target,
      :action => action,
      :user_id => creator_id,
      :comment_target_type => comment_target_type,
      :comment_target_id => comment_target_id)
    activity.created_at = target.try(:created_at) || nil
    activity.save

    activity
  end

  def refs_thread_comments
    if target.respond_to? :first_comment
      [target.first_comment] + target.recent_comments
    else
      []
    end
  end

  def refs_comment_target
    if comment_target.respond_to? :first_comment
      [comment_target,
       comment_target.first_comment,
       comment_target.user,
       comment_target.first_comment.try(:user)] +
       comment_target.recent_comments +
       comment_target.recent_comments.map(&:user)
    else
      [comment_target]
    end
  end

  def action_comment_type
    i = "#{action}#{target_type}"
    i +="#{comment_target_type}" if comment_target_type
    i.underscore
  end


  def action_type
    i = "#{action}#{target_type}"
    i.underscore
  end

  def action_type?(current_type)
    i = "#{action}#{target_type.singular_class_name}"
    i.underscore
    i == current_type
  end

  def target
    @target ||= target_id ? Kernel.const_get(target_type).find_with_deleted(target_id) : nil
  end

  def comment_target
    @comment_target ||= comment_target_id ? Kernel.const_get(comment_target_type).find_with_deleted(comment_target_id) : nil
  end

  def user
    target.user
  end

  def posted_date
    target.created_at
  end

  def downcase_type
    target.type.to_s.downcase
  end

  def user
    @user ||= user_id ? User.with_deleted.find_by_id(user_id) : nil
  end

  def thread
    @thread ||= if target.is_a?(Comment)
      comment_target
    else
      target
    end || project
  end

  def thread_id
    target_type == 'Comment' ? "#{comment_target_type}_#{comment_target_id}" : "#{target_type}_#{target_id}"
  end

  def self.for_projects(projects)
    in_projects(projects).limit_per_page.by_updated
  end

  def to_xml(options = {})
    options[:indent] ||= 2
    xml = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
    xml.instruct! unless options[:skip_instruct]

    xml.activity :id => id do
      xml.tag! 'action', action
      xml.tag! 'created-at', created_at.to_s(:db)
      xml.tag! 'updated-at', updated_at.to_s(:db)

      xml.user :id => user_id do
        xml.tag! 'username',   user.login
        xml.tag! 'first-name', user.first_name
        xml.tag! 'last-name',  user.last_name
        xml.tag! 'avatar-url', user.avatar_or_gravatar_url(:thumb)
      end

      xml.project :id => project_id do
        xml.tag! 'name',       project.name
        xml.tag! 'permalink',  project.permalink
      end

      xml.target :id => target.id do
        xml.tag! 'type', target.class
        target.to_xml(options.merge({ :skip_instruct => true }))
      end if target
    end
  end

  def to_api_hash(options = {})
    base = {
      :id => id,
      :action => action,
      :created_at => created_at.to_s(:api_time),
      :updated_at => updated_at.to_s(:api_time),
      :user_id => user_id,
      :project_id => project_id,
      :target_id => target_id,
      :target_type => target_type
    }

    base[:type] = self.class.to_s if options[:emit_type]

    if Array(options[:include]).include? :project
      base[:project] = {:name => project.name, :permalink => project.permalink}
    end

    if Array(options[:include]).include? :target
      base[:target] = target.to_api_hash
    end

    if Array(options[:include]).include? :user
      base[:user] = {
        :username => user.login,
        :first_name => user.first_name,
        :last_name => user.last_name,
        :avatar_url => user.avatar_or_gravatar_url(:thumb)
      }
    end

    base
  end

end