# frozen_string_literal: true class User < ApplicationRecord before_save { self.email = email.downcase } ##### ActiveRecord Associations has_many :parties, dependent: :destroy has_many :favorites, dependent: :destroy has_many :collection_characters, dependent: :destroy has_many :collection_weapons, dependent: :destroy has_many :collection_summons, dependent: :destroy has_many :collection_job_accessories, dependent: :destroy has_many :collection_artifacts, dependent: :destroy # Crew associations has_many :crew_memberships, dependent: :destroy has_one :active_crew_membership, -> { where(retired: false) }, class_name: 'CrewMembership' has_one :crew, through: :active_crew_membership has_many :crew_invitations, dependent: :destroy has_many :pending_crew_invitations, -> { where(status: :pending) }, class_name: 'CrewInvitation' has_many :sent_crew_invitations, class_name: 'CrewInvitation', foreign_key: :invited_by_id, dependent: :nullify ##### ActiveRecord Validations validates :username, presence: true, length: { minimum: 3, maximum: 26 } validates :email, presence: true, uniqueness: true, email: true validates :password, length: { minimum: 8 }, presence: true, on: :create validates :password, length: { minimum: 8 }, on: :update, if: :password_digest_changed? validates :password_confirmation, presence: true, on: :create validates :password_confirmation, presence: true, on: :update, if: :password_digest_changed? ##### ActiveModel Security has_secure_password ##### Enums # Enum for collection privacy levels (1-based to avoid JavaScript falsy 0 issues) enum :collection_privacy, { everyone: 1, crew_only: 2, private_collection: 3 }, prefix: true ##### Instance Methods def favorite_parties favorites.map(&:party) end def admin? role == 9 end def blueprint UserBlueprint end # Check if collection is viewable by another user def collection_viewable_by?(viewer) return true if self == viewer # Owners can always view their own collection case collection_privacy when 'everyone' true when 'crew_only' viewer.present? && in_same_crew_as?(viewer) when 'private_collection' false else false end end # Check if user is in same crew as another user def in_same_crew_as?(other_user) return false unless other_user.present? return false unless crew.present? && other_user.crew.present? crew.id == other_user.crew.id end # Get the user's crew role def crew_role active_crew_membership&.role end # Check if user is a crew officer (captain or vice captain) def crew_officer? crew_role.in?(%w[captain vice_captain]) end # Check if user is a crew captain def crew_captain? crew_role == 'captain' end end