earlymarket/CoPosition

View on GitHub
app/models/approval.rb

Summary

Maintainability
A
0 mins
Test Coverage
class Approval < ApplicationRecord
  STATUSES = %w(developer-requested requested pending accepted complete)

  include PublicActivity::Common
  belongs_to :user
  belongs_to :approvable, polymorphic: true

  validates :status, inclusion: { in: STATUSES, message: "%{value} is not a valid status" }

  before_create do
    if approvable_type == "User" && user == approvable
      errors.add(:base, "Adding self")
      throw(:abort)
    elsif (approval = Approval.find_by(user: user, approvable: approvable, approvable_type: approvable_type))
      if approvable_type == "User"
        errors.add(:base, approval.status == "pending" ? "Friend request already sent" : "Friendship already exists")
      else
        errors.add(:base, "App already connected")
      end
      throw(:abort)
    end
  end

  def self.add_developer(user, developer)
    approval = Approval.link(user, developer, "Developer")
    if user.request_from?(developer) || approval.errors.empty?
      approval = Approval.accept(user, developer, "Developer")
    end
    approval
  end

  def self.add_friend(user, friend)
    approval = Approval.link(user, friend, "User")
    if user.request_from?(friend)
      approval = Approval.accept(user, friend, "User")
    elsif approval.errors.messages.blank?
      user.approve_devices(friend)
      friend.approve_devices(user)
      UserMailer.add_user_email(user, friend, false).deliver_now
      UserMailer.invite_sent_email(user, friend.email).deliver_now
    end
    approval
  end

  def self.link(user, approvable, approvable_type)
    if approvable_type == "Developer"
      Approval.create(user: user, approvable: approvable,
                      approvable_type: approvable_type, status: "developer-requested")
    else
      Approval.create(user: approvable, approvable: user,
                      approvable_type: approvable_type, status: "requested")
      Approval.create(user: user, approvable: approvable,
                      approvable_type: approvable_type, status: "pending")
    end
  end

  def self.accept(user, approvable, approvable_type)
    unless approvable_type == "Developer"
      accept_one_side(approvable, user, approvable_type)
      notify_request_sender(approvable, user)
    end
    accept_one_side(user, approvable, approvable_type)
  end

  def self.accept_one_side(user, approvable, approvable_type)
    approval = find_by(user_id: user.id, approvable_id: approvable.id, approvable_type: approvable_type)
    approval.approve!
    approval
  end

  def self.notify_request_sender(approvable, user)
    Firebase::Push.call(
      topic: approvable.id,
      content_available: true,
      notification: {
        body: "#{user.email} has accepted your friend request",
        title: "New Friend"
      }
    )
  end

  def approve!
    update(status: "accepted", approval_date: Time.current)
    user.approve_devices(approvable)
  end

  def complete!
    update(status: "complete", approval_date: Time.current)
    user.approve_devices(approvable)
  end
end