<commit_before>class Invitation < ActiveRecord::Base

  class InvitationCancelled < StandardError
  end

  class InvitationAlreadyUsed < StandardError
  end

  extend FriendlyId
  friendly_id :token
  belongs_to :inviter, class_name: User
  belongs_to :accepted_by, class_name: User
  belongs_to :invitable, polymorphic: true
  belongs_to :canceller, class_name: User

  validates_presence_of :invitable, :intent
  validates_inclusion_of :invitable_type, :in => ['Group', 'Discussion']
  validates_inclusion_of :intent, :in => ['start_group', 'join_group', 'join_discussion']
  before_save :ensure_token_is_present

  scope :not_cancelled,  -> { where(cancelled_at: nil) }
  scope :pending, -> { not_cancelled.where(accepted_at: nil) }


  def recipient_first_name
    recipient_name.split(' ').first
  end

  def inviter_name
    inviter.name
  end

  def group
    case invitable_type
    when 'Group'
      invitable
    when 'Discussion'
      invitable.group
    end
  end

  def invitable_name
    case invitable_type
    when 'Group'
      invitable.name
    when 'Discussion'
      invitable.title
    end
  end

  def group_request_admin_name
    if invitable_type == 'Group'
      invitable.group_request.admin_name
    end
  end

  def cancel!(args)
    self.canceller = args[:canceller]
    self.cancelled_at = DateTime.now
    self.save!
  end

  def cancelled?
    cancelled_at.present?
  end

  def accepted?
    accepted_by.present?
  end

  def to_start_group?
    intent == 'start_group'
  end

  def to_join_group?
    intent == 'join_group'
  end

  def to_join_discussion?
    intent == 'join_discussion'
  end

  def invitations_remaining<commit_msg>check for invitable blank<commit_after>class Invitation < ActiveRecord::Base

  class InvitationCancelled < StandardError
  end

  class InvitationAlreadyUsed < StandardError
  end

  extend FriendlyId
  friendly_id :token
  belongs_to :inviter, class_name: User
  belongs_to :accepted_by, class_name: User
  belongs_to :invitable, polymorphic: true
  belongs_to :canceller, class_name: User

  validates_presence_of :invitable, :intent
  validates_inclusion_of :invitable_type, :in => ['Group', 'Discussion']
  validates_inclusion_of :intent, :in => ['start_group', 'join_group', 'join_discussion']
  before_save :ensure_token_is_present

  scope :not_cancelled,  -> { where(cancelled_at: nil) }
  scope :pending, -> { not_cancelled.where(accepted_at: nil) }


  def recipient_first_name
    recipient_name.split(' ').first
  end

  def inviter_name
    inviter.name
  end

  def group
    case invitable_type
    when 'Group'
      invitable
    when 'Discussion'
      invitable.group
    end
  end

  def invitable_name
    case invitable_type
    when 'Group'
      invitable.name
    when 'Discussion'
      invitable.title
    end
  end

  def group_request_admin_name
    if invitable_type == 'Group'
      invitable.group_request.admin_name
    end
  end

  def cancel!(args)
    self.canceller = args[:canceller]
    self.cancelled_at = DateTime.now
    self.save!
  end

  def cancelled?
    if invitable.blank?
      Measurement.increment('invitation_to_deleted_invitable')
      true
    else
      cancelled_at.present?
    end
  end

  def accepted?
    accepted_by.present?
  end

  def to_start_group?
    intent == 'start_group'
  end

  def to_join_group?
    intent == 'join_group'
  end

  def to_join_discussion?
    intent == 'join_discussion'
  end

  def invitations_remaining
{'fraction_non_alphanumeric': 0.07630290814857472, 'fraction_numerical': 0.0, 'mean_word_length': 3.4768041237113403, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6925283', 'n_tokens_mistral': 1195, 'n_tokens_neox': 1154, 'n_words': 266}