Module: AtomicInternalId
- Extended by:
- ActiveSupport::Concern
- Included in:
- AlertManagement::Alert, Ci::Pipeline, Deployment, DesignManagement::Design, Issue, MergeRequest, Operations::FeatureFlag, Operations::FeatureFlags::UserList, Timebox
- Defined in:
- app/models/concerns/atomic_internal_id.rb
Overview
Include atomic internal id generation scheme for a model
This allows us to atomically generate internal ids that are unique within a given scope.
For example, let's generate internal ids for Issue per Project: “` class Issue < ApplicationRecord
has_internal_id :iid, scope: :project, init: ->(s) { s.project.issues.maximum(:iid) }
end “`
This generates unique internal ids per project for newly created issues. The generated internal id is saved in the `iid` attribute of `Issue`.
This concern uses InternalId records to facilitate atomicity. In the absence of a record for the given scope, one will be created automatically. In this situation, the `init` block is called to calculate the initial value. In the example above, we calculate the maximum `iid` of all issues within the given project.
Note that a model may have more than one internal id associated with possibly different scopes.
Defined Under Namespace
Classes: Supply
Constant Summary collapse
- MissingValueError =
Class.new(StandardError)
Class Method Summary collapse
- .group_init(klass, column_name = :iid) ⇒ Object
- .project_init(klass, column_name = :iid) ⇒ Object
- .scope_attrs(scope_value) ⇒ Object
- .scope_usage(including_class) ⇒ Object
Instance Method Summary collapse
- #internal_id_read_scope(scope) ⇒ Object
- #internal_id_scope_attrs(scope) ⇒ Object
- #internal_id_scope_usage ⇒ Object
Class Method Details
.group_init(klass, column_name = :iid) ⇒ Object
217 218 219 220 221 222 223 224 225 |
# File 'app/models/concerns/atomic_internal_id.rb', line 217 def self.group_init(klass, column_name = :iid) ->(instance, scope) do if instance klass.where(group_id: instance.group_id).maximum(column_name) elsif scope.present? klass.where(group: scope[:namespace]).maximum(column_name) end end end |
.project_init(klass, column_name = :iid) ⇒ Object
207 208 209 210 211 212 213 214 215 |
# File 'app/models/concerns/atomic_internal_id.rb', line 207 def self.project_init(klass, column_name = :iid) ->(instance, scope) do if instance klass.default_scoped.where(project_id: instance.project_id).maximum(column_name) elsif scope.present? klass.default_scoped.where(**scope).maximum(column_name) end end end |
.scope_attrs(scope_value) ⇒ Object
189 190 191 |
# File 'app/models/concerns/atomic_internal_id.rb', line 189 def self.scope_attrs(scope_value) { scope_value.class.table_name.singularize.to_sym => scope_value } if scope_value end |
.scope_usage(including_class) ⇒ Object
203 204 205 |
# File 'app/models/concerns/atomic_internal_id.rb', line 203 def self.scope_usage(including_class) including_class.table_name.to_sym end |
Instance Method Details
#internal_id_read_scope(scope) ⇒ Object
227 228 229 |
# File 'app/models/concerns/atomic_internal_id.rb', line 227 def internal_id_read_scope(scope) association(scope).reader end |
#internal_id_scope_attrs(scope) ⇒ Object
193 194 195 196 197 |
# File 'app/models/concerns/atomic_internal_id.rb', line 193 def internal_id_scope_attrs(scope) scope_value = internal_id_read_scope(scope) ::AtomicInternalId.scope_attrs(scope_value) end |
#internal_id_scope_usage ⇒ Object
199 200 201 |
# File 'app/models/concerns/atomic_internal_id.rb', line 199 def internal_id_scope_usage ::AtomicInternalId.scope_usage(self.class) end |