Class: Temping
- Inherits:
-
Object
- Object
- Temping
- Defined in:
- lib/temping.rb,
lib/temping.rb
Defined Under Namespace
Classes: ModelFactory, NamespaceFactory
Class Method Summary collapse
-
.cleanup ⇒ Object
Destroy all records from each of the models created by Temping.
-
.create(name, options = {}, &block) ⇒ Object
Create a new temporary ActiveRecord model with a name specified by ‘name`.
-
.delete_or_trim_in_namespaces(parent, parts, index) ⇒ Object
Clean ‘@namespaces` array by either removing current namespace or replacing it with its parent.
-
.namespace_removable?(namespace, parts, parent) ⇒ Boolean
Namespace can be removed only if it’s still defined and if it was created by Temping, we use ‘defined_by_temping?` to indicate the latter.
-
.namespace_still_defined?(namespace) ⇒ Boolean
Check if namespace is still defined.
-
.split_name(name) ⇒ Object
Split the provided name finding the namespace (if any) and the model name without namespace.
-
.teardown ⇒ Object
Completely destroy everything created by Temping.
-
.teardown_models ⇒ Object
Iterate over ‘@models`, undefine model constants, drop tables, and remove the constants from the array one by one starting with the models defined last.
-
.teardown_namespaces ⇒ Object
Iterate over ‘@namespaces`, undefine modules and remove them from the array one by one starting with the deepest ones first.
Class Method Details
.cleanup ⇒ Object
Destroy all records from each of the models created by Temping.
This does not undefine the models themselves or drop their tables. This method is an alternative to ‘teardown` if you want to keep the models and tables.
51 52 53 |
# File 'lib/temping.rb', line 51 def cleanup @models.reverse_each(&:destroy_all) end |
.create(name, options = {}, &block) ⇒ Object
Create a new temporary ActiveRecord model with a name specified by ‘name`.
Provided ‘options` are all passed to the inner `create_table` call so anything acceptable by `create_table` method can be passed here. In addition `options` can include `parent_class` key to specify parent class for the model. When `block` is passed, it is evaluated in the context of the class. This means anything you do in an ActiveRecord model class body can be accomplished in `block` including method definitions, validations, module includes, etc. Additional database columns can be specified via `with_columns` method inside `block`, which uses Rails migration syntax.
24 25 26 27 28 29 30 31 |
# File 'lib/temping.rb', line 24 def create(name, = {}, &block) namespace_name, model_name = split_name(name) namespace = namespace_name ? NamespaceFactory.new(namespace_name).klass : Object @namespaces << namespace if namespace_name model = ModelFactory.new(model_name, namespace, , &block).klass @models << model model end |
.delete_or_trim_in_namespaces(parent, parts, index) ⇒ Object
Clean ‘@namespaces` array by either removing current namespace or replacing it with its parent.
Case 1: @namespaces = [A, B, C, D]; index = 3 This is an outer-most module, we just remove it from ‘@namespaces`.
Case 2: @namespaces = [A::B, A::B::C, A::D]; index = 1 Once we remove C from A::B::C, it becomes A::B, but we already have A::B, so just remove it.
Case 3: @namespaces = [A::B, A::D]; index = 1 Once we remove D from A::D, it becomes A, replace A::D with A.
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/temping.rb', line 132 def delete_or_trim_in_namespaces(parent, parts, index) is_last_module = parts.length == 1 if is_last_module @namespaces.delete_at(index) return end parent_already_in_namespaces = @namespaces.include?(parent) if parent_already_in_namespaces @namespaces.delete_at(index) return end @namespaces[index] = parent end |
.namespace_removable?(namespace, parts, parent) ⇒ Boolean
Namespace can be removed only if it’s still defined and if it was created by Temping, we use ‘defined_by_temping?` to indicate the latter.
114 115 116 117 118 |
# File 'lib/temping.rb', line 114 def namespace_removable?(namespace, parts, parent) parent.const_defined?(parts.last) && namespace.defined_by_temping? rescue NoMethodError false end |
.namespace_still_defined?(namespace) ⇒ Boolean
Check if namespace is still defined. It could be already removed if it were inside a model created by Temping. Since ‘@models` are teared down first, it means that in such a case all modules that were inside that model are no longer defined.
99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/temping.rb', line 99 def namespace_still_defined?(namespace) parent = Object outer_namespace_parts = [] namespace.to_s.split("::").each do |part| return false unless parent.const_defined?(part) outer_namespace_parts.push(part) parent = outer_namespace_parts.join("::").constantize end true end |
.split_name(name) ⇒ Object
Split the provided name finding the namespace (if any) and the model name without namespace.
56 57 58 59 60 61 62 63 |
# File 'lib/temping.rb', line 56 def split_name(name) classified_name = name.to_s.classify name_parts = classified_name.split("::") namespace_name = name_parts[0...-1].join("::") return [nil, classified_name] if namespace_name.empty? [namespace_name, name_parts.last] end |
.teardown ⇒ Object
Completely destroy everything created by Temping.
This includes:
-
removing all the records in the models created by Temping and dropping their tables
from the database;
-
undefining model constants so they cannot be pointed to anymore in the code.
39 40 41 42 43 44 45 |
# File 'lib/temping.rb', line 39 def teardown if @models.any? teardown_models teardown_namespaces ActiveSupport::Dependencies::Reference.clear! if ActiveRecord::VERSION::MAJOR < 7 end end |
.teardown_models ⇒ Object
Iterate over ‘@models`, undefine model constants, drop tables, and remove the constants from the array one by one starting with the models defined last. (Models defined later can point to older models by using foreign keys so they have to be removed first).
69 70 71 72 73 74 75 76 77 78 |
# File 'lib/temping.rb', line 69 def teardown_models @models.reverse_each do |model| model_name_without_namespace = model.name.split("::").last if model.namespace.const_defined?(model_name_without_namespace) model.connection.drop_table(model.table_name) model.namespace.send(:remove_const, model_name_without_namespace) end end @models.clear end |
.teardown_namespaces ⇒ Object
Iterate over ‘@namespaces`, undefine modules and remove them from the array one by one starting with the deepest ones first.
83 84 85 86 87 88 89 90 91 92 |
# File 'lib/temping.rb', line 83 def teardown_namespaces @namespaces.select! { |namespace| namespace_still_defined?(namespace) } until @namespaces.empty? namespace, index = @namespaces.each_with_index.max_by { |n, _i| n.name.split("::").length } parts = namespace.name.split("::") parent = (parts.length == 1) ? Object : parts[0...-1].join("::").constantize parent.send(:remove_const, parts.last) if namespace_removable?(namespace, parts, parent) delete_or_trim_in_namespaces(parent, parts, index) end end |