Class: ARDatabaseDuplicator
- Inherits:
-
Object
- Object
- ARDatabaseDuplicator
- Extended by:
- SingleForwardable
- Defined in:
- lib/ar_database_duplicator.rb
Defined Under Namespace
Classes: CapturedSchema, TableSchema
Instance Attribute Summary collapse
-
#destination ⇒ Object
Returns the value of attribute destination.
-
#force ⇒ Object
Returns the value of attribute force.
-
#schema_file ⇒ Object
Returns the value of attribute schema_file.
-
#silent ⇒ Object
Returns the value of attribute silent.
-
#source ⇒ Object
Returns the value of attribute source.
-
#split_data ⇒ Object
Returns the value of attribute split_data.
-
#test ⇒ Object
Returns the value of attribute test.
Class Method Summary collapse
Instance Method Summary collapse
- #define_class(name) ⇒ Object
-
#duplicate(klass, replacements = {}, *additional_replacements, &block) ⇒ Object
Duplicate each record, via ActiveRecord, from the source to the destination database.
-
#initialize(options = {}) ⇒ ARDatabaseDuplicator
constructor
A new instance of ARDatabaseDuplicator.
- #load_duplication(klass) ⇒ Object
- #load_schema ⇒ Object
- #use_destination(subname = nil) ⇒ Object
- #use_source(subname = nil) ⇒ Object
- #while_not_silent(&block) ⇒ Object
- #while_silent(&block) ⇒ Object
-
#with_connection(name, subname = nil, silent_change = false, &block) ⇒ Object
With a specified connection, connect, execute a block, then restore the connection to it’s previous state (if any).
- #with_destination(subname = nil, silent_change = false, &block) ⇒ Object
- #with_source(subname = nil, silent_change = false, &block) ⇒ Object
Constructor Details
#initialize(options = {}) ⇒ ARDatabaseDuplicator
Returns a new instance of ARDatabaseDuplicator.
125 126 127 128 129 130 131 132 |
# File 'lib/ar_database_duplicator.rb', line 125 def initialize(={}) @source = [:source] || 'development' @destination = [:destination] || 'dev_data' @schema_file = [:schema_file] || 'db/schema.rb' @force = .fetch(:force) { false } @test = .fetch(:test) { false } @split_data = .fetch(:split_data) { true } end |
Instance Attribute Details
#destination ⇒ Object
Returns the value of attribute destination.
123 124 125 |
# File 'lib/ar_database_duplicator.rb', line 123 def destination @destination end |
#force ⇒ Object
Returns the value of attribute force.
123 124 125 |
# File 'lib/ar_database_duplicator.rb', line 123 def force @force end |
#schema_file ⇒ Object
Returns the value of attribute schema_file.
123 124 125 |
# File 'lib/ar_database_duplicator.rb', line 123 def schema_file @schema_file end |
#silent ⇒ Object
Returns the value of attribute silent.
123 124 125 |
# File 'lib/ar_database_duplicator.rb', line 123 def silent @silent end |
#source ⇒ Object
Returns the value of attribute source.
123 124 125 |
# File 'lib/ar_database_duplicator.rb', line 123 def source @source end |
#split_data ⇒ Object
Returns the value of attribute split_data.
123 124 125 |
# File 'lib/ar_database_duplicator.rb', line 123 def split_data @split_data end |
#test ⇒ Object
Returns the value of attribute test.
123 124 125 |
# File 'lib/ar_database_duplicator.rb', line 123 def test @test end |
Class Method Details
.instance(options = {}) ⇒ Object
257 258 259 260 261 262 263 264 265 |
# File 'lib/ar_database_duplicator.rb', line 257 def self.instance(={}) [:source] ||= 'development' [:destination] ||= 'dev_data' [:schema] ||= 'db/schema.rb' [:force] = false unless .has_key?(:force) [:test] = true unless .has_key?(:test) [:split_data] = true unless .has_key?(:split_data) @duplicator ||= new() end |
.reset! ⇒ Object
267 268 269 |
# File 'lib/ar_database_duplicator.rb', line 267 def self.reset! @duplicator = nil end |
Instance Method Details
#define_class(name) ⇒ Object
167 168 169 170 171 |
# File 'lib/ar_database_duplicator.rb', line 167 def define_class(name) name = name.camelize.to_sym Object.const_set(name, Class.new(ActiveRecord::Base)) unless Object.const_defined?(name) Object.const_get(name) end |
#duplicate(klass, replacements = {}, *additional_replacements, &block) ⇒ Object
Duplicate each record, via ActiveRecord, from the source to the destination database. Field replacements can be given via a hash in the form of :original_field => :pseudo_person_field If a block is passed, the record will be passed for inspection/alteration before it is saved into the destination database.
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/ar_database_duplicator.rb', line 177 def duplicate(klass, replacements={}, *additional_replacements, &block) klass = define_class(klass) unless klass.is_a?(Class) plural = plural(klass) automatic_replacements = [replacements] + additional_replacements raise(ArgumentError, "Each group of replacements must be given as a Hash") unless automatic_replacements.all? { |x| x.is_a?(Hash) } sti_klasses = [] set_temporary_vetted_attributes(klass, automatic_replacements) # If we aren't guaranteed to fail on vetting if block_given? || !block_required?(klass) # If we have potential duplication to do if force || !already_duplicated?(klass) # Connect to the source database with_source do # Grab a quick count to see if there is anything we need to do. estimated_total = klass.count if estimated_total > 0 inform(test ? "Extracting first 1,000 #{plural} for testing" : "Extracting all #{plural}") # Pull in all records. Perhaps later we can enhance this to do it in batches. unless singleton?(klass) records = test ? klass.find(:all, :limit => 1000) : klass.find(:all) else records = [klass.instance] end # Handle any single table inheritance that may have shown up records.map(&:class).uniq.each { |k| sti_klasses << k if k != klass } sti_klasses.each { |k| set_temporary_vetted_attributes(k, automatic_replacements) } # Record the size so we can give some progress indication. inform "#{records.size} #{plural} read" transfer(klass, records, automatic_replacements, &block) else inform "Skipping #{plural}. No records exist." end end else inform "Skipping #{plural}. Records already exist." end else inform "Skipping #{plural}. The following field(s) were not checked: #{klass.unvetted_attributes.join(', ')}" end # Clean things up for the next bit of code that might use this class. klass.clear_temporary_safe_attributes sti_klasses.each { |k| k.clear_temporary_safe_attributes } end |
#load_duplication(klass) ⇒ Object
153 154 155 156 157 158 159 |
# File 'lib/ar_database_duplicator.rb', line 153 def load_duplication(klass) raise ArgumentError, "Production must be duplicated, not loaded from." if source.downcase == "production" klass = define_class(klass) unless klass.is_a?(Class) records = with_source(klass) { klass.all } puts "#{records.size} #{plural(klass)} read." klass.without_field_vetting { transfer(klass, records) } end |
#load_schema ⇒ Object
161 162 163 164 165 |
# File 'lib/ar_database_duplicator.rb', line 161 def load_schema # Adding this class just so we can check if a schema has already been loaded Object.const_set(:SchemaMigration, Class.new(ActiveRecord::Base)) unless Object.const_defined?(:SchemaMigration) split_data ? load_schema_split : load_schema_combined end |
#use_destination(subname = nil) ⇒ Object
138 139 140 |
# File 'lib/ar_database_duplicator.rb', line 138 def use_destination(subname=nil) use_connection destination, subname end |
#use_source(subname = nil) ⇒ Object
134 135 136 |
# File 'lib/ar_database_duplicator.rb', line 134 def use_source(subname=nil) use_connection source, subname end |
#while_not_silent(&block) ⇒ Object
233 234 235 |
# File 'lib/ar_database_duplicator.rb', line 233 def while_not_silent(&block) with_silence_at(false, &block) end |
#while_silent(&block) ⇒ Object
229 230 231 |
# File 'lib/ar_database_duplicator.rb', line 229 def while_silent(&block) with_silence_at(true, &block) end |
#with_connection(name, subname = nil, silent_change = false, &block) ⇒ Object
With a specified connection, connect, execute a block, then restore the connection to it’s previous state (if any).
246 247 248 249 250 251 252 253 254 255 |
# File 'lib/ar_database_duplicator.rb', line 246 def with_connection(name, subname=nil, silent_change=false, &block) old_connection = connection begin use_connection(name, subname, silent_change) result = yield ensure use_spec(old_connection) end result end |
#with_destination(subname = nil, silent_change = false, &block) ⇒ Object
241 242 243 |
# File 'lib/ar_database_duplicator.rb', line 241 def with_destination(subname=nil, silent_change=false, &block) with_connection(destination, subname, silent_change, &block) end |
#with_source(subname = nil, silent_change = false, &block) ⇒ Object
237 238 239 |
# File 'lib/ar_database_duplicator.rb', line 237 def with_source(subname=nil, silent_change=false, &block) with_connection(source, subname, silent_change, &block) end |