Module: Plutonium::Invites::Concerns::Invitable

Extended by:
ActiveSupport::Concern
Defined in:
lib/plutonium/invites/concerns/invitable.rb

Overview

Invitable allows any model to trigger invites and be notified on acceptance.

This pattern is useful when you have a profile or record that needs to invite a user and then connect itself to that user after acceptance.

Examples:

TenantProfile that invites users

class TenantProfile < ApplicationRecord
  include Plutonium::Resource::Record
  include Plutonium::Invites::Concerns::Invitable

  belongs_to :entity
  belongs_to :user, optional: true

  def on_invite_accepted(user)
    update!(user: user)
  end
end

Creating an invite from an invitable

tenant_profile.create_invite!(
  email: tenant_profile.email,
  entity: tenant_profile.entity,
  invited_by: current_user,
  role: :member,
  email_template: "tenant"
)

Instance Method Summary collapse

Instance Method Details

#can_invite_user?Boolean

Check if this invitable can receive an invitation.

Override this method to customize the logic. The default implementation returns true if no user is attached and no pending invite exists.

Returns:

  • (Boolean)

    true if invitation can be sent



81
82
83
# File 'lib/plutonium/invites/concerns/invitable.rb', line 81

def can_invite_user?
  !user.present? && !has_pending_invite?
end

#create_invite!(email:, entity:, invited_by:, role: nil, email_template: nil) ⇒ Object

Create an invite for this invitable.

If there’s already a pending invite for this invitable, it will be destroyed and replaced with a new one.

Parameters:

  • email (String)

    the email address to invite

  • entity (Object)

    the entity to join

  • invited_by (Object)

    the user creating the invite

  • role (Symbol, String) (defaults to: nil)

    the role to assign (default: nil, uses model default)

  • email_template (String, nil) (defaults to: nil)

    optional template type for email customization

Returns:

  • (Object)

    the created invite record



53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/plutonium/invites/concerns/invitable.rb', line 53

def create_invite!(email:, entity:, invited_by:, role: nil, email_template: nil)
  # Cancel any existing pending invite first (association is already scoped to pending)
  user_invite&.cancelled!

  attrs = {
    email: email,
    entity: entity,
    invited_by: invited_by,
    email_template: email_template
  }
  attrs[:role] = role if role.present?

  create_user_invite!(attrs)
end

#has_pending_invite?Boolean

Check if there’s an active pending invite.

Returns:

  • (Boolean)

    true if there’s a pending invite



71
72
73
# File 'lib/plutonium/invites/concerns/invitable.rb', line 71

def has_pending_invite?
  user_invite.present?
end

#on_invite_accepted(user) ⇒ Object

Called when the invited user accepts and joins the entity.

Override this method in your model to handle the acceptance, typically to connect the invitable to the user.

Parameters:

  • user (Object)

    the user who accepted the invite

Raises:

  • (NotImplementedError)

    if not overridden



92
93
94
# File 'lib/plutonium/invites/concerns/invitable.rb', line 92

def on_invite_accepted(user)
  raise NotImplementedError, "#{self.class.name} must implement #on_invite_accepted(user)"
end