lujanfernaud/prevy

View on GitHub
app/models/user.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true

# == Schema Information
#
# Table name: users
#
#  id                     :bigint(8)        not null, primary key
#  admin                  :boolean          default(FALSE)
#  bio                    :string
#  confirmation_sent_at   :datetime
#  confirmation_token     :string
#  confirmed_at           :datetime
#  current_sign_in_at     :datetime
#  current_sign_in_ip     :inet
#  email                  :string           default(""), not null
#  encrypted_password     :string           default(""), not null
#  last_sign_in_at        :datetime
#  last_sign_in_ip        :inet
#  location               :string
#  name                   :string
#  notifications_count    :integer          default(0), not null
#  remember_created_at    :datetime
#  reset_password_sent_at :datetime
#  reset_password_token   :string
#  sample_user            :boolean          default(FALSE)
#  settings               :jsonb            not null
#  sign_in_count          :integer          default(0), not null
#  slug                   :string
#  unconfirmed_email      :string
#  created_at             :datetime         not null
#  updated_at             :datetime         not null
#
# Indexes
#
#  index_users_on_confirmation_token    (confirmation_token) UNIQUE
#  index_users_on_reset_password_token  (reset_password_token) UNIQUE
#  index_users_on_slug                  (slug)
#

class User < ApplicationRecord
  attribute :skip_sample_content, :boolean

  has_many :owned_groups, class_name: "Group", foreign_key: "user_id",
            dependent: :destroy
  has_many :received_requests, through: :owned_groups

  has_many :group_invitations, dependent: :destroy
  has_many :sent_invitations,  class_name: "GroupInvitation",
            foreign_key: "sender_id"

  has_many :membership_requests, dependent: :destroy
  has_many :sent_requests, through: :membership_requests, source: "group"

  has_many :group_memberships, dependent: :delete_all
  has_many :associated_groups, through: :group_memberships, source: "group"

  has_many :user_roles, dependent: :delete_all
  has_many :roles,      through:   :user_roles

  has_many :user_group_points, dependent: :destroy

  has_many :organized_events, class_name: "Event", foreign_key: "organizer_id",
            dependent: :destroy

  has_many :attendances, foreign_key: "attendee_id", dependent: :destroy
  has_many :attended_events, through: :attendances

  has_many :topics,         dependent: :destroy
  has_many :topic_comments, dependent: :delete_all

  has_many :notifications, dependent: :destroy
  has_many :membership_request_notifications
  has_many :group_membership_notifications
  has_many :group_role_notifications
  has_many :announcement_topic_notifications
  has_many :group_invitation_notifications

  validates :email,    presence: true, email:  true
  validates :name,     presence: true, length: { in: 2..50 }
  validates :password, presence: true, length: { minimum: 6 }, allow_nil: true

  before_save   :format_name
  before_update :titleize_location
  before_update :capitalize_bio
  after_create  :create_user_sample_content

  # Devise
  devise :database_authenticatable, :registerable, :confirmable,
         :recoverable, :rememberable, :trackable, :validatable

  # FriendlyId
  include FriendlyId
  friendly_id :slug_candidates, use: :slugged

  # Rolify
  rolify

  # Storext
  include Storext.model
  #
  # Store typecasted values in 'settings' jsonb column.
  store_attributes :settings do
    membership_request_emails Boolean, default: true
    group_membership_emails   Boolean, default: true
    group_role_emails         Boolean, default: true
    group_event_emails        Boolean, default: true
    group_announcement_emails Boolean, default: true
    group_invitation_emails   Boolean, default: true
  end

  scope :confirmed, -> { where.not(confirmed_at: nil) }

  def sample_group
    owned_groups.where(sample_group: true).first
  end

  def groups
    UserGroupsQuery.call(self)
  end

  def group_roles(group)
    roles.where(resource_id: group).map(&:name)
  end

  def events_from_groups
    Event.where(group_id: groups.distinct.pluck(:id)).upcoming
  end

  def group_points(group)
    user_group_points.find_or_create_by!(group: group)
  end

  def group_points_amount(group)
    group_points(group).amount
  end

  def total_membership_requests
    MembershipRequest.total(self)
  end

  # Devise
  #
  # Used for customized account confirmation.
  # See Users::ConfirmationsController#confirm
  def password_match?
    add_password_match_error if password != password_confirmation

    password == password_confirmation && !password.blank?
  end

  protected

    # Devise
    def after_confirmation
      SupportMailer.welcome(self).deliver_later
    end

    # Devise
    #
    # Used for customized sign up and account confirmation.
    def password_required?
      super if confirmed?
    end

  private

    def format_name
      self.name = NameFormatter.call(name)
    end

    def titleize_location
      return unless location

      self.location = location.titleize
    end

    def capitalize_bio
      return unless bio && !bio.empty?

      self.bio = bio[0].capitalize + bio[1..-1]
    end

    def create_user_sample_content
      UserSampleContentCreator.call(self)
    end

    def add_password_match_error
      self.errors[:password_confirmation] << "does not match password"
    end

    def should_generate_new_friendly_id?
      slug.blank? || saved_change_to_name?
    end

    def slug_candidates
      [
        :name,
        [:name, :id]
      ]
    end
end