Class: ApplicationRecord

Direct Known Subclasses

AbuseReport, Achievements::Achievement, Achievements::UserAchievement, ActivityPub::ReleasesSubscription, AlertManagement::Alert, AlertManagement::AlertAssignee, AlertManagement::HttpIntegration, AlertManagement::MetricImage, Analytics::CycleAnalytics::Aggregation, Analytics::CycleAnalytics::IssueStageEvent, Analytics::CycleAnalytics::MergeRequestStageEvent, Analytics::CycleAnalytics::Stage, Analytics::CycleAnalytics::StageAggregation, Analytics::CycleAnalytics::StageEventHash, Analytics::CycleAnalytics::ValueStream, Analytics::UsageTrends::Measurement, AntiAbuse::Event, Appearance, ApplicationSetting, ApplicationSetting::Term, Approval, Atlassian::Identity, AuditEvent, AuditEvents::GroupAuditEvent, AuditEvents::InstanceAuditEvent, AuditEvents::ProjectAuditEvent, AuditEvents::UserAuditEvent, AuthenticationEvent, Authn::PersonalAccessTokenLastUsedIp, Authz::GranularScope, Authz::PersonalAccessTokenGranularScope, AwardEmoji, Aws::Role, Badge, BatchedGitRefUpdates::Deletion, Board, BoardGroupRecentVisit, BoardProjectRecentVisit, BulkImport, BulkImports::BatchTracker, BulkImports::Configuration, BulkImports::Entity, BulkImports::Export, BulkImports::ExportBatch, BulkImports::ExportUpload, BulkImports::Failure, BulkImports::Tracker, Cells::OutstandingLease, ChatName, ChatTeam, Ci::ApplicationRecord, Ci::Catalog::Resource, Ci::Catalog::Resources::Component, Ci::Catalog::Resources::Components::LastUsage, Ci::Catalog::Resources::SyncEvent, Ci::Catalog::Resources::Version, Ci::NamespaceMirror, Ci::ProjectWithPipelineVariable, CloudConnector::ServiceAccessToken, Clusters::Agent, Clusters::AgentMigration, Clusters::AgentToken, Clusters::Agents::ActivityEvent, Clusters::Agents::Authorizations::CiAccess::GroupAuthorization, Clusters::Agents::Authorizations::CiAccess::OrganizationAuthorization, Clusters::Agents::Authorizations::CiAccess::ProjectAuthorization, Clusters::Agents::Authorizations::UserAccess::GroupAuthorization, Clusters::Agents::Authorizations::UserAccess::ProjectAuthorization, Clusters::Agents::ManagedResource, Clusters::Cluster, Clusters::ClusterEnabledGrant, Clusters::Group, Clusters::KubernetesNamespace, Clusters::Platforms::Kubernetes, Clusters::Project, Clusters::Providers::Aws, Clusters::Providers::Gcp, CommitSignatures::GpgSignature, CommitSignatures::SshSignature, CommitSignatures::X509CommitSignature, ContainerExpirationPolicy, ContainerRegistry::DataRepairDetail, ContainerRegistry::Protection::Rule, ContainerRegistry::Protection::TagRule, ContainerRepository, CustomEmoji, CustomerRelations::Contact, CustomerRelations::IssueContact, CustomerRelations::Organization, DependencyProxy::Blob, DependencyProxy::GroupSetting, DependencyProxy::ImageTtlGroupPolicy, DependencyProxy::Manifest, DeployKeysProject, DeployToken, Deployment, DeploymentCluster, DeploymentMergeRequest, DescriptionVersion, DesignManagement::Action, DesignManagement::Design, DesignManagement::Repository, DesignManagement::Version, DevOpsReport::Metric, DiffNotePosition, Doorkeeper::AccessGrant, Doorkeeper::AccessToken, Doorkeeper::DeviceAuthorizationGrant::DeviceGrant, Doorkeeper::OpenidConnect::Request, DraftNote, Email, Environment, Environments::Job, Epic, ErrorTracking::ClientKey, ErrorTracking::Error, ErrorTracking::ErrorEvent, ErrorTracking::ProjectErrorTrackingSetting, Event, ForkNetwork, ForkNetworkMember, Gitlab::BackgroundMigration::BackfillIssueTrackerDataShardingKey::Integration, Gitlab::BackgroundMigration::BackfillJiraTrackerDataShardingKey::Integration, Gitlab::BackgroundMigration::BackfillNoteDiscussionId::Note, Gitlab::BackgroundMigration::BackfillOnboardingStatusSetupForCompany::UserDetail, Gitlab::BackgroundMigration::BackfillPartitionedUploads::Upload, Gitlab::BackgroundMigration::BackfillPlaceholderUsersDetailsFromSourceUsers::ImportPlaceholderUserDetail, Gitlab::BackgroundMigration::BackfillPlaceholderUsersDetailsFromSourceUsers::ImportSourceUser, Gitlab::BackgroundMigration::BackfillPlaceholderUsersDetailsFromSourceUsers::Namespace, Gitlab::BackgroundMigration::BackfillProjectFeaturePackageRegistryAccessLevel::ProjectFeature, Gitlab::BackgroundMigration::BackfillProjectIdForProjectsWithPipelineVariables::Project, Gitlab::BackgroundMigration::BackfillProjectIdForProjectsWithPipelineVariables::ProjectWithPipelineVariable, Gitlab::BackgroundMigration::BackfillSecurityProjectTrackedContextsDefaultBranch::Namespace, Gitlab::BackgroundMigration::BackfillSecurityProjectTrackedContextsDefaultBranch::Project, Gitlab::BackgroundMigration::BackfillSecurityProjectTrackedContextsDefaultBranch::Route, Gitlab::BackgroundMigration::BackfillTerraformModulesMetadataWithSemver::ModuleMetadatum, Gitlab::BackgroundMigration::BackfillVulnerabilityFindingRiskScores::CveEnrichment, Gitlab::BackgroundMigration::BackfillWorkItemTransitions::WorkItemTransition, Gitlab::BackgroundMigration::CleanupTerminatedBulkImportConfigs::BulkImport, Gitlab::BackgroundMigration::CleanupTerminatedBulkImportConfigs::BulkImportConfiguration, Gitlab::BackgroundMigration::CreateMissingNugetSymbolFiles::Packages::Nuget::Symbol, Gitlab::BackgroundMigration::DeleteOrphanedSbomOccurrences::Project, Gitlab::BackgroundMigration::DisableLegacyOpenSourceLicenseForInactivePublicProjects::ProjectSetting, Gitlab::BackgroundMigration::DisableLegacyOpenSourceLicenseForNoIssuesNoRepoProjects::ProjectSetting, Gitlab::BackgroundMigration::FixVulnerabilitiesTransitionedFromDismissedToResolved::Note, Gitlab::BackgroundMigration::FixVulnerabilitiesTransitionedFromDismissedToResolved::Project, Gitlab::BackgroundMigration::FixVulnerabilitiesTransitionedFromDismissedToResolved::User, Gitlab::BackgroundMigration::MigrateDuplicatePushRulesToProjectPushRules::ProjectPushRule, Gitlab::BackgroundMigration::MigrateDuplicatePushRulesToProjectPushRules::PushRule, Gitlab::BackgroundMigration::RecalculateTwoFactorEnforcementOnUsers::Group, Gitlab::BackgroundMigration::RecalculateTwoFactorEnforcementOnUsers::GroupMember, Gitlab::BackgroundMigration::RecalculateTwoFactorEnforcementOnUsers::User, Gitlab::BackgroundMigration::RemoveInvalidOrganizationUsers::Organization, Gitlab::BackgroundMigration::RemoveInvalidOrganizationUsers::OrganizationUser, Gitlab::BackgroundMigration::RemoveInvalidOrganizationUsers::User, Gitlab::BackgroundMigration::ResyncEpicDatesToWorkItemsDatesSources::Epics, Gitlab::BackgroundMigration::ResyncEpicDatesToWorkItemsDatesSources::WorkItemDatesSources, Gitlab::BackgroundMigration::Route, Gitlab::BackgroundMigration::UpdateDelayedProjectRemovalToNullForUserNamespaces::NamespaceSetting, Gitlab::Database::PgUser, Gitlab::DatabaseImporters::Security::TrainingProviders::Importer::Security::TrainingProvider, GpgKey, GpgKeySubkey, Group::CrmSettings, GroupCustomAttribute, GroupDeletionSchedule, GroupDeployToken, GroupGroupLink, GroupImportState, Groups::FeatureSetting, Identity, Import::NamespaceImportUser, Import::Offline::Configuration, Import::Offline::Export, Import::PlaceholderUserDetail, Import::Placeholders::Membership, Import::SourceUser, Import::SourceUserPlaceholderReference, ImportExportUpload, ImportFailure, IncidentManagement::IssuableEscalationStatus, IncidentManagement::ProjectIncidentManagementSetting, IncidentManagement::TimelineEvent, IncidentManagement::TimelineEventTag, IncidentManagement::TimelineEventTagLink, Integration, Integrations::IssueTrackerData, Integrations::JiraTrackerData, Integrations::SlackWorkspace::ApiScope, Integrations::SlackWorkspace::IntegrationApiScope, Integrations::ZentaoTrackerData, InternalId, IssuableSeverity, Issue, Issue::Email, Issue::Metrics, IssueAssignee, IssueEmailParticipant, IssueLink, Issues::CsvImport, Issues::SearchData, JiraConnectInstallation, JiraConnectSubscription, JiraImportState, Key, Label, LabelLink, LabelPriority, LfsFileLock, LfsObject, LfsObjectsProject, List, ListUserPreference, Member, Members::DeletionSchedule, MergeRequest, MergeRequest::ApprovalMetrics, MergeRequest::CleanupSchedule, MergeRequest::CommitsMetadata, MergeRequest::DiffCommitUser, MergeRequest::Metrics, MergeRequestAssignee, MergeRequestContextCommit, MergeRequestContextCommitDiffFile, MergeRequestDiff, MergeRequestDiffCommit, MergeRequestDiffFile, MergeRequestReviewer, MergeRequests::GeneratedRefCommit, MergeRequests::MergeData, MergeRequests::MergeSchedule, MergeRequestsClosingIssues, Milestone, MilestoneRelease, Ml::Candidate, Ml::CandidateMetadata, Ml::CandidateMetric, Ml::CandidateParam, Ml::Experiment, Ml::ExperimentMetadata, Ml::Model, Ml::ModelMetadata, Ml::ModelVersion, Ml::ModelVersionMetadata, Namespace, Namespace::AdminNote, Namespace::AggregationSchedule, Namespace::Detail, Namespace::PackageSetting, Namespace::RootStorageStatistics, NamespaceCiCdSetting, NamespaceSetting, NamespaceStatistics, Namespaces::Descendants, Namespaces::LdapSetting, Namespaces::SyncEvent, Namespaces::VerifiedNamespace, Note, NoteDiffFile, Notes::NoteMetadata, NotificationSetting, Observability::GroupO11ySetting, Operations::FeatureFlag, Operations::FeatureFlags::Scope, Operations::FeatureFlags::Strategy, Operations::FeatureFlags::StrategyUserList, Operations::FeatureFlags::UserList, Operations::FeatureFlagsClient, Organizations::IsolationRecord, Organizations::Organization, Organizations::OrganizationDetail, Organizations::OrganizationSetting, Organizations::OrganizationUser, Organizations::OrganizationUserDetail, PackageMetadata::ApplicationRecord, Packages::BuildInfo, Packages::Cargo::Metadatum, Packages::Cleanup::Policy, Packages::Composer::Metadatum, Packages::Conan::FileMetadatum, Packages::Conan::Metadatum, Packages::Conan::PackageReference, Packages::Conan::PackageRevision, Packages::Conan::RecipeRevision, Packages::Debian::FileMetadatum, Packages::Debian::GroupArchitecture, Packages::Debian::GroupComponent, Packages::Debian::GroupComponentFile, Packages::Debian::GroupDistribution, Packages::Debian::GroupDistributionKey, Packages::Debian::ProjectArchitecture, Packages::Debian::ProjectComponent, Packages::Debian::ProjectComponentFile, Packages::Debian::ProjectDistribution, Packages::Debian::ProjectDistributionKey, Packages::Debian::Publication, Packages::Dependency, Packages::DependencyLink, Packages::Helm::FileMetadatum, Packages::Helm::MetadataCache, Packages::Maven::Metadatum, Packages::Npm::MetadataCache, Packages::Npm::Metadatum, Packages::Nuget::DependencyLinkMetadatum, Packages::Nuget::Metadatum, Packages::Nuget::Symbol, Packages::Package, Packages::PackageFile, Packages::PackageFileBuildInfo, Packages::Protection::Rule, Packages::Pypi::FileMetadatum, Packages::Pypi::Metadatum, Packages::Rpm::Metadatum, Packages::Rpm::RepositoryFile, Packages::Rubygems::Metadatum, Packages::Tag, Packages::TerraformModule::Metadatum, PagesDeployment, PagesDomain, PagesDomainAcmeOrder, PersonalAccessToken, Plan, PlanLimits, PoolRepository, ProgrammingLanguage, Project, ProjectAuthorization, ProjectAutoDevops, ProjectCiCdSetting, ProjectCustomAttribute, ProjectDailyStatistic, ProjectDeployToken, ProjectExportJob, ProjectFeature, ProjectFeatureUsage, ProjectGroupLink, ProjectImportData, ProjectImportState, ProjectPagesMetadatum, ProjectRepository, ProjectSetting, ProjectStatistics, Projects::BranchRules::SquashOption, Projects::BuildArtifactsSizeRefresh, Projects::CiFeatureUsage, Projects::DataTransfer, Projects::ImportExport::RelationExport, Projects::ImportExport::RelationExportUpload, Projects::ImportExport::RelationImportTracker, Projects::ProjectTopic, Projects::RepositoryStorageMove, Projects::SyncEvent, Projects::Topic, Projects::WikiRepository, ProtectedBranch, ProtectedBranch::MergeAccessLevel, ProtectedBranch::PushAccessLevel, ProtectedTag, ProtectedTag::CreateAccessLevel, PushEventPayload, RawUsageData, RedirectRoute, Release, Releases::Evidence, Releases::Link, RemoteMirror, Repositories::Tags::GpgSignature, Repositories::Tags::SshSignature, Repositories::Tags::X509Signature, RepositoryLanguage, ResourceEvent, ResourceEvents::AbuseReportEvent, ResourceEvents::IssueAssignmentEvent, ResourceEvents::MergeRequestAssignmentEvent, Review, Route, SecApplicationRecord, SentNotification, SentryIssue, ServiceDesk::CustomEmailCredential, ServiceDesk::CustomEmailVerification, ServiceDeskSetting, ServicePing::NonSqlServicePing, ServicePing::QueriesServicePing, Shard, SlackIntegration, Snippet, SnippetRepository, SnippetStatistics, Snippets::RepositoryStorageMove, SpamLog, Subscription, Suggestion, SupplyChain::Attestation, System::BroadcastMessage, SystemNoteMetadata, TermAgreement, Terraform::State, Terraform::StateVersion, TimeTracking::TimelogCategory, Timelog, Todo, TrendingProject, Upload, User, UserAgentDetail, UserCustomAttribute, UserDetail, UserHighestRole, UserMention, UserPreference, UserStatus, UserSyncedAttributesMetadata, Users::BannedUser, Users::BroadcastMessageDismissal, Users::Callout, Users::CreditCardValidation, Users::GhostUserMigration, Users::GroupCallout, Users::GroupVisit, Users::NamespaceCommitEmail, Users::PhoneNumberValidation, Users::ProjectCallout, Users::ProjectVisit, Users::SavedReply, Users::UserFollowUser, UsersStarProject, UsersStatistics, VsCode::Settings::VsCodeSetting, WebHook, WebHookLog, WebauthnRegistration, WikiPage::Meta, WikiPage::Slug, WorkItems::DatesSource, WorkItems::Description, WorkItems::ParentLink, WorkItems::RelatedWorkItemLink, WorkItems::SavedViews::SavedView, WorkItems::SavedViews::UserSavedView, WorkItems::Transition, WorkItems::Type, WorkItems::UserPreference, WorkItems::WidgetDefinition, X509Certificate, X509Issuer, ZoomMeeting

Constant Summary collapse

MAX_PLUCK =

We should avoid using pluck docs.gitlab.com/ee/development/sql.html#plucking-ids but, if we are going to use it, let’s try and limit the number of records

1_000

Constants included from HasCheckConstraints

HasCheckConstraints::NOT_NULL_CHECK_PATTERN

Constants included from ResetOnColumnErrors

ResetOnColumnErrors::MAX_RESET_PERIOD

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Organizations::Sharding

#sharding_organization

Methods included from ResetOnColumnErrors

#reset_on_union_error, #reset_on_unknown_attribute_error

Methods included from Gitlab::SensitiveSerializableHash

#serializable_hash

Class Method Details

.===(object) ⇒ Object

This method has been removed in Rails 7.1 However, application relies on it in case-when usages with objects wrapped in presenters



150
151
152
# File 'app/models/application_record.rb', line 150

def self.===(object)
  object.is_a?(self)
end

.cached_column_listObject



136
137
138
# File 'app/models/application_record.rb', line 136

def self.cached_column_list
  column_names.map { |column_name| arel_table[column_name] }
end

.current_transactionObject



110
111
112
# File 'app/models/application_record.rb', line 110

def self.current_transaction
  connection.current_transaction
end

.declarative_enum(enum_mod) ⇒ Object



132
133
134
# File 'app/models/application_record.rb', line 132

def self.declarative_enum(enum_mod)
  enum enum_mod.key, enum_mod.values
end

.default_select_columnsObject



140
141
142
143
144
145
146
# File 'app/models/application_record.rb', line 140

def self.default_select_columns
  if ignored_columns.any?
    cached_column_list
  else
    arel_table[Arel.star]
  end
end

.delete_all_returning(*columns) ⇒ Object



159
160
161
162
163
# File 'app/models/application_record.rb', line 159

def self.delete_all_returning(*columns)
  relation = current_scope || all

  Gitlab::Database::DeleteRelationWithReturning.execute(relation, columns.flatten)
end

.id_in(ids) ⇒ Object



39
40
41
# File 'app/models/application_record.rb', line 39

def self.id_in(ids)
  where(id: ids)
end

.id_not_in(ids) ⇒ Object



51
52
53
# File 'app/models/application_record.rb', line 51

def self.id_not_in(ids)
  where.not(id: ids)
end

.iid_in(iids) ⇒ Object



47
48
49
# File 'app/models/application_record.rb', line 47

def self.iid_in(iids)
  where(iid: iids)
end

.nullable_column?(column_name) ⇒ Boolean

Returns:

  • (Boolean)


154
155
156
157
# File 'app/models/application_record.rb', line 154

def self.nullable_column?(column_name)
  columns.find { |column| column.name == column_name }.null &&
    !not_null_check?(column_name)
end

.primary_key_in(values) ⇒ Object



43
44
45
# File 'app/models/application_record.rb', line 43

def self.primary_key_in(values)
  where(primary_key => values)
end

.safe_ensure_unique(retries: 0) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
# File 'app/models/application_record.rb', line 55

def self.safe_ensure_unique(retries: 0)
  transaction(requires_new: true) do # rubocop:disable Performance/ActiveRecordSubtransactions
    yield
  end
rescue ActiveRecord::RecordNotUnique
  if retries > 0
    retries -= 1
    retry
  end

  false
end

.safe_find_or_create_by(*args, &block) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'app/models/application_record.rb', line 90

def self.safe_find_or_create_by(*args, &block)
  record = find_by(*args)
  return record if record.present?

  # We need to use `all.create` to make this implementation follow `find_or_create_by` which delegates this in
  # https://github.com/rails/rails/blob/v6.1.3.2/activerecord/lib/active_record/querying.rb#L22
  #
  # When calling this method on an association, just calling `self.create` would call `ActiveRecord::Persistence.create`
  # and that skips some code that adds the newly created record to the association.
  transaction(requires_new: true) { all.create(*args, &block) } # rubocop:disable Performance/ActiveRecordSubtransactions
rescue ActiveRecord::RecordNotUnique => e
  find_by(*args).tap do |result|
    # It's unusual if the find_by was not able to find the record that the
    # database claimed already existed. There could be some underlying issue,
    # such as a database trigger that inserts a record into another table.
    # Log this error so that the full database error can be investigated.
    Gitlab::ErrorTracking.track_exception(e, args: args) unless result
  end
end

.safe_find_or_create_by!(*args, &block) ⇒ Object



68
69
70
71
72
73
74
# File 'app/models/application_record.rb', line 68

def self.safe_find_or_create_by!(*args, &block)
  safe_find_or_create_by(*args, &block).tap do |record|
    raise ActiveRecord::RecordNotFound unless record.present?

    record.validate! unless record.persisted?
  end
end

.underscoreObject



120
121
122
# File 'app/models/application_record.rb', line 120

def self.underscore
  @underscore ||= to_s.underscore
end

.where_exists(query) ⇒ Object



124
125
126
# File 'app/models/application_record.rb', line 124

def self.where_exists(query)
  where('EXISTS (?)', query.select(1))
end

.where_not_exists(query) ⇒ Object



128
129
130
# File 'app/models/application_record.rb', line 128

def self.where_not_exists(query)
  where('NOT EXISTS (?)', query.select(1))
end

.with_fast_read_statement_timeout(timeout_ms = 4500) ⇒ Object

Start a new transaction with a shorter-than-usual statement timeout. This is currently one third of the default 15-second timeout with a 500ms buffer to allow callers gracefully handling the errors to still complete within the 5s target duration of a low urgency request.



80
81
82
83
84
85
86
87
88
# File 'app/models/application_record.rb', line 80

def self.with_fast_read_statement_timeout(timeout_ms = 4500)
  ::Gitlab::Database::LoadBalancing::SessionMap.current(load_balancer).fallback_to_replicas_for_ambiguous_queries do
    transaction(requires_new: true) do # rubocop:disable Performance/ActiveRecordSubtransactions
      connection.exec_query("SET LOCAL statement_timeout = #{timeout_ms}")

      yield
    end
  end
end

.without_orderObject



35
36
37
# File 'app/models/application_record.rb', line 35

def self.without_order
  reorder(nil)
end

Instance Method Details

#create_or_load_association(association_name) ⇒ Object



114
115
116
117
118
# File 'app/models/application_record.rb', line 114

def create_or_load_association(association_name)
  association(association_name).create unless association(association_name).loaded?
rescue ActiveRecord::RecordNotUnique, PG::UniqueViolation
  association(association_name).reader
end

#deleted_from_database?Boolean

Returns:

  • (Boolean)


173
174
175
# File 'app/models/application_record.rb', line 173

def deleted_from_database?
  !self.class.exists?(id)
end

#readable_by?(user) ⇒ Boolean

Returns:

  • (Boolean)


165
166
167
# File 'app/models/application_record.rb', line 165

def readable_by?(user)
  Ability.allowed?(user, :"read_#{to_ability_name}", self)
end

#to_ability_nameObject



169
170
171
# File 'app/models/application_record.rb', line 169

def to_ability_name
  model_name.element
end