Module: TransientRecord::Context
- Defined in:
- lib/transient_record.rb
Overview
A module for creating Transient Record contexts.
A context is a Ruby module (created via Module.new) and extended with Context. This means instance methods below should be called as module methods on a context, not as instance methods.
Class Method Summary collapse
-
.create(base_class) ⇒ Module
private
Creates a context corresponding to the specified base class.
Instance Method Summary collapse
-
#cleanup ⇒ nil
Drops transient tables and models.
-
#create_table(table_name, options = {}) {|table| ... } ⇒ ModelDefinitionProxy
Creates a transient table.
-
#define_model(model_name, base_class = nil) { ... } ⇒ nil
Defines a transient Active Record model.
Class Method Details
.create(base_class) ⇒ Module
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Creates a context corresponding to the specified base class.
117 118 119 120 121 122 123 |
# File 'lib/transient_record.rb', line 117 def self.create base_class Module.new do extend Context @base_class = base_class @transient_tables = [] end end |
Instance Method Details
#cleanup ⇒ nil
Drops transient tables and models.
Calling this method removes all models and drops all tables created within this context. Instead of calling this method, you usually should TransientRecord.cleanup to cleanup all contexts.
Calling this method does the following:
-
Remove all models defined via #define_model.
-
Drop all tables created via #create_table.
-
Run garbage collection to ensure model classes are truly removed. This may be needed in some versions of Active Record.
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
# File 'lib/transient_record.rb', line 222 def cleanup constants.each { |name| remove_const name } tables_to_remove = @transient_tables drop_attempts = tables_to_remove.count * (1 + tables_to_remove.count) / 2 drop_attempts.times do table = tables_to_remove.pop break if table.nil? begin @base_class.connection.drop_table table, force: :cascade, if_exists: true rescue ActiveRecord::InvalidForeignKey, ActiveRecord::StatementInvalid # ActiveRecord::StatementInvalid is raised by MySQL when attempting to # drop a table that has foreign keys referring to it. tables_to_remove.unshift(table) end end if !@transient_tables.empty? raise Error.new(<<~ERROR) The following transient tables could not be removed: #{@transient_tables.join(', ')}. ERROR end GC.start nil end |
#create_table(table_name, options = {}) {|table| ... } ⇒ ModelDefinitionProxy
Creates a transient table.
This method can be considered to be a wrapper around #create_table in Active Record, as it forwards its arguments and the block.
Transient tables are not made temporary in the database (in other words, they are not created using CREATE TEMPORARY TABLE), because temporary tables are treated differently by Active Record. For example, they aren’t listed by #tables. If a temporary table is needed then pass temporary: true via options, which Active Record will recognized out of the box.
Transient tables must be dropped explicitly by calling TransientRecord.cleanup or #cleanup.
150 151 152 153 154 155 156 157 |
# File 'lib/transient_record.rb', line 150 def create_table table_name, = {}, &block table_name = table_name.to_sym @transient_tables << table_name @base_class.connection.create_table table_name, **, &block ModelDefinitionProxy.new self, table_name end |
#define_model(model_name, base_class = nil) { ... } ⇒ nil
Defines a transient Active Record model.
Calling this method is roughly equivalent to defining a class inheriting from the class the context corresponds to and with class body defined by the block passed to the method.
The base class can be customized by passing in a second argument, but it must be a subclass of the context’s base class.
Transient models must be removed explicitly by calling TransientRecord.cleanup or #cleanup.
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/transient_record.rb', line 191 def define_model model_name, base_class = nil, &block base_class ||= @base_class if base_class > @base_class raise Error.new(<<~ERROR) #{model_name} base class is #{base_class.name} but it must be a descendant of #{@base_class.name} ERROR end klass = Class.new base_class const_set model_name, klass klass.class_eval(&block) if block_given? nil end |