debian-mirror-gitlab/app/models/application_record.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

133 lines
3.7 KiB
Ruby
Raw Normal View History

2019-02-15 15:39:39 +05:30
# frozen_string_literal: true
class ApplicationRecord < ActiveRecord::Base
2021-12-11 22:18:48 +05:30
include DatabaseReflection
include Transactions
include LegacyBulkInsert
2022-04-04 11:22:00 +05:30
include CrossDatabaseModification
2022-05-07 20:08:51 +05:30
include SensitiveSerializableHash
2021-12-11 22:18:48 +05:30
2019-02-15 15:39:39 +05:30
self.abstract_class = true
2019-03-02 22:35:43 +05:30
2022-01-26 12:08:38 +05:30
# We should avoid using pluck https://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
MAX_PLUCK = 1_000
2019-07-31 22:56:46 +05:30
alias_method :reset, :reload
2020-06-23 00:09:42 +05:30
def self.without_order
reorder(nil)
end
2019-03-02 22:35:43 +05:30
def self.id_in(ids)
where(id: ids)
end
2020-11-24 15:15:51 +05:30
def self.primary_key_in(values)
where(primary_key => values)
end
2020-07-28 23:09:34 +05:30
def self.iid_in(iids)
where(iid: iids)
end
2019-07-07 11:18:12 +05:30
def self.id_not_in(ids)
where.not(id: ids)
end
def self.pluck_primary_key
where(nil).pluck(self.primary_key)
end
2019-05-03 19:53:19 +05:30
def self.safe_ensure_unique(retries: 0)
2021-11-11 11:23:49 +05:30
transaction(requires_new: true) do # rubocop:disable Performance/ActiveRecordSubtransactions
2019-05-03 19:53:19 +05:30
yield
end
rescue ActiveRecord::RecordNotUnique
if retries > 0
retries -= 1
retry
end
false
end
2020-10-24 23:57:45 +05:30
def self.safe_find_or_create_by!(*args, &block)
safe_find_or_create_by(*args, &block).tap do |record|
2021-01-29 00:20:46 +05:30
raise ActiveRecord::RecordNotFound unless record.present?
2019-03-02 22:35:43 +05:30
record.validate! unless record.persisted?
end
end
2021-01-03 14:25:43 +05:30
# Start a new transaction with a shorter-than-usual statement timeout. This is
2022-05-07 20:08:51 +05:30
# 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.
def self.with_fast_read_statement_timeout(timeout_ms = 4500)
2021-09-04 01:27:46 +05:30
::Gitlab::Database::LoadBalancing::Session.current.fallback_to_replicas_for_ambiguous_queries do
2021-11-11 11:23:49 +05:30
transaction(requires_new: true) do # rubocop:disable Performance/ActiveRecordSubtransactions
2021-09-04 01:27:46 +05:30
connection.exec_query("SET LOCAL statement_timeout = #{timeout_ms}")
2021-01-03 14:25:43 +05:30
2021-09-04 01:27:46 +05:30
yield
end
2021-01-03 14:25:43 +05:30
end
end
2020-10-24 23:57:45 +05:30
def self.safe_find_or_create_by(*args, &block)
2021-10-27 15:23:28 +05:30
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.
2021-11-11 11:23:49 +05:30
transaction(requires_new: true) { all.create(*args, &block) } # rubocop:disable Performance/ActiveRecordSubtransactions
2021-10-27 15:23:28 +05:30
rescue ActiveRecord::RecordNotUnique
find_by(*args)
end
2021-06-08 01:23:25 +05:30
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
2019-09-04 21:01:54 +05:30
def self.underscore
Gitlab::SafeRequestStore.fetch("model:#{self}:underscore") { self.to_s.underscore }
end
2021-01-03 14:25:43 +05:30
def self.where_exists(query)
where('EXISTS (?)', query.select(1))
end
2021-03-08 18:12:59 +05:30
2022-05-07 20:08:51 +05:30
def self.where_not_exists(query)
where('NOT EXISTS (?)', query.select(1))
end
2021-03-08 18:12:59 +05:30
def self.declarative_enum(enum_mod)
2021-12-11 22:18:48 +05:30
enum(enum_mod.key => enum_mod.values)
2021-03-08 18:12:59 +05:30
end
2021-08-04 16:29:09 +05:30
2021-10-27 15:23:28 +05:30
def self.cached_column_list
self.column_names.map { |column_name| self.arel_table[column_name] }
end
2021-11-11 11:23:49 +05:30
def self.default_select_columns
if ignored_columns.any?
cached_column_list
else
arel_table[Arel.star]
end
end
2021-08-04 16:29:09 +05:30
def readable_by?(user)
Ability.allowed?(user, "read_#{to_ability_name}".to_sym, self)
end
def to_ability_name
model_name.element
end
2019-02-15 15:39:39 +05:30
end