SysMO-DB/seek

View on GitHub
lib/subscribable.rb

Summary

Maintainability
B
5 hrs
Test Coverage
module Subscribable
  def self.included klass
    klass.class_eval do
      has_many :subscriptions, :as => :subscribable, :dependent => :destroy, :autosave => true, :before_add => proc {|item, sub| sub.subscribable = item} #,:required_access_to_owner => false,
      after_create :set_subscription_job if self.subscribable?
      after_update :update_subscription_job_if_study_or_assay if self.subscribable?
      extend ClassMethods
    end
  end

  def current_users_subscription
    subscriptions.detect { |ss| ss.person == User.current_user.person }
  end

  def subscribed? person=User.current_user.person
    !subscriptions.detect{|sub| sub.person == person}.nil?
  end

  def subscribed= subscribed
    if subscribed
      subscribe
    else
      unsubscribe
    end
  end

  def subscribe person=User.current_user.person
    subscriptions << Subscription.new(:person => person) unless subscribed?(person)
  end

  def unsubscribe person=User.current_user.person
    subscriptions.detect{|sub| sub.person == person}.try(:destroy)
  end

  def send_immediate_subscriptions activity_log

    if Seek::Config.email_enabled && subscribers_are_notified_of?(activity_log.action)
      subscriptions.each do |subscription|
        if !subscription.person.user.nil? && subscription.person.receive_notifications? && subscription.immediately? && can_view?(subscription.person.user)
          SubMailer.send_immediate_subscription(subscription.person, activity_log).deliver
        end
      end
    end
    
  end

  def subscribers_are_notified_of? action
    self.class.subscribers_are_notified_of? action
  end

  def set_default_subscriptions projects
    unless projects.empty?
      Person.scoped(:include => :project_subscriptions).each do |person|
        project_subscriptions = person.project_subscriptions
        project_subscriptions.each do |ps|
          if projects.include? ps.project
            subscriptions.create(:person => person, :project_subscription_id => ps.id) if !ps.unsubscribed_types.include?(self.class.name) && !self.subscribed?(person)
            #also build subscriptions for studies and assays associating with this investigation
            if self.kind_of?(Investigation)
              self.studies.each do |study|
                study.subscriptions << Subscription.create(:person => person, :project_subscription_id => ps.id) if !study.subscribed?(person)
              end
              self.assays.each do |assay|
                assay.subscriptions << Subscription.create(:person => person, :project_subscription_id => ps.id) if !assay.subscribed?(person)
              end
            end
          end
        end
      end
    end
  end

  def remove_subscriptions projects
    unless projects.empty?
      project_subscription_ids = projects.collect{|project| project.project_subscriptions}.flatten.collect(&:id)
      subscriptions = Subscription.where(['subscribable_type=? AND subscribable_id=? AND project_subscription_id IN (?)', self.class.name, self.id, project_subscription_ids])
      #remove also subcriptions for studies and assays association with this investigation
      if self.kind_of?(Investigation)
        study_ids = self.studies.collect(&:id)
        assay_ids = self.assays.collect(&:id)
        subscriptions |= Subscription.where(['subscribable_type=? AND subscribable_id IN (?) AND project_subscription_id IN (?)', 'Study', study_ids, project_subscription_ids])
        subscriptions |= Subscription.where(['subscribable_type=? AND subscribable_id IN (?) AND project_subscription_id IN (?)', 'Assay', assay_ids, project_subscription_ids])
      end
      subscriptions.each{|s| s.destroy}
    end
  end

  def set_subscription_job
      project_ids = ( Seek::Config.project_hierarchy_enabled)?  self.projects_and_descendants.map(&:id) : self.projects.collect(&:id)
      SetSubscriptionsForItemJob.create_job(self.class.name, self.id, project_ids)
  end

  def update_subscription_job_if_study_or_assay
    if self.kind_of?(Study) && self.investigation_id_changed?
      #update subscriptions for study
      old_investigation_id = self.investigation_id_was
      old_investigation = Investigation.find_by_id old_investigation_id
      project_ids_to_remove = old_investigation.nil? ? [] : old_investigation.projects.collect(&:id)
      project_ids_to_add = self.investigation.projects.collect(&:id)
      update_subscriptions_for self, project_ids_to_add, project_ids_to_remove
      #update subscriptions for assays associated with this study
      self.assays.each do |assay|
        update_subscriptions_for assay, project_ids_to_add, project_ids_to_remove
      end
    elsif self.kind_of?(Assay) && self.study_id_changed?
      old_study_id = self.study_id_was
      old_study = Study.find_by_id old_study_id
      project_ids_to_remove = old_study.nil? ? [] : old_study.projects.collect(&:id)
      project_ids_to_add = self.study.projects.collect(&:id)
      update_subscriptions_for self, project_ids_to_add, project_ids_to_remove
    end
  end

  module ClassMethods
    def subscribers_are_notified_of? action
      action=="create" || action == "update"
    end
  end

  private

  def update_subscriptions_for item, project_ids_to_add, project_ids_to_remove
    SetSubscriptionsForItemJob.create_job(item.class.name, item.id, project_ids_to_add)
    RemoveSubscriptionsForItemJob.create_job(item.class.name, item.id, project_ids_to_remove)
  end
end

ActiveRecord::Base.class_eval do
  def self.subscribable?
    include? Subscribable
  end

  def subscribable?
    self.class.subscribable?
  end
end