class RailsArchiver::Unarchiver
Attributes
errors[RW]
transport[RW]
Public Class Methods
new(model, options={})
click to toggle source
@param model [ActiveRecord::Base] @param options [Hash]
* logger [Logger] * new_copy [Boolean] if true, create all new objects instead of replacing existing ones. * crash_on_errors [Boolean] if true, do not do any imports if any models' validations failed.
# File lib/rails-archiver/unarchiver.rb, line 20 def initialize(model, options={}) @model = model @logger = options.delete(:logger) || Logger.new(STDOUT) @options = options # Transport for downloading self.transport = _get_transport(options.delete(:transport) || :in_memory) self.errors = [] end
Public Instance Methods
import_objects(klass, models)
click to toggle source
Import saved objects. @param klass [Class] @param models [Array<ActiveRecord::Base>]
# File lib/rails-archiver/unarchiver.rb, line 72 def import_objects(klass, models) cols_to_update = klass.column_names - [klass.primary_key] # check other unique indexes indexes = ActiveRecord::Base.connection.indexes(klass.table_name). select(&:unique) indexes.each { |index| cols_to_update -= index.columns } options = { :validate => false, :timestamps => false, :on_duplicate_key_update => cols_to_update } @logger.info("Importing #{models.length} for #{klass.name}") models.in_groups_of(1000).each do |group| klass.import(group.compact, options) end rescue => e self.errors << "Error importing class #{klass.name}: #{e.message}" end
init_model(klass, hash)
click to toggle source
# File lib/rails-archiver/unarchiver.rb, line 89 def init_model(klass, hash) attrs = hash.select do |x| klass.column_names.include?(x) && x != klass.primary_key end # fix time zone issues klass.columns.each do |col| if col.type == :datetime && attrs[col.name] attrs[col.name] = Time.zone.parse(attrs[col.name]) end end model = klass.where(klass.primary_key => hash[klass.primary_key]).first if model.nil? model = klass.new _assign_attributes(model, attrs) # can't set this in the attribute hash, it'll be overridden. Need # to set it manually. model[klass.primary_key] = hash[klass.primary_key] else _assign_attributes(model, attrs) end model end
load_classes(hash)
click to toggle source
Load a list of general classes that were saved as JSON. @param hash [Hash]
# File lib/rails-archiver/unarchiver.rb, line 51 def load_classes(hash) full_hash = hash.with_indifferent_access full_hash.each do |key, vals| save_models(key.constantize, vals) end if @options[:crash_on_errors] && self.errors.any? raise ImportError.new("Errors occurred during load - please see 'errors' method for more details") end end
save_models(klass, hashes)
click to toggle source
Save all models into memory in the given hash on the given class. @param klass [Class] the starting class. @param hashes [Array<Hash<] the object hashes to import.
# File lib/rails-archiver/unarchiver.rb, line 64 def save_models(klass, hashes) models = hashes.map { |hash| init_model(klass, hash) } import_objects(klass, models) end
unarchive(location=nil)
click to toggle source
Unarchive a model. @param location [String] if given, uses the given location to unarchive. Otherwise uses the existing model in the database (e.g. attribute on the model) depending on the transport being used.
# File lib/rails-archiver/unarchiver.rb, line 33 def unarchive(location=nil) @errors = [] source = @model ? @model.class.name : location @logger.info('Downloading JSON file') hash = @transport.retrieve_archive(location) @logger.info("Loading #{source}") load_classes(hash) if @model @model.reload if @model.attribute_names.include?('archived') @model.update_attribute(:archived, false) end end @logger.info("#{source} load complete!") end
Private Instance Methods
_assign_attributes(model, attrs)
click to toggle source
@param model [ActiveRecord::Base] @param attrs [Hash]
# File lib/rails-archiver/unarchiver.rb, line 119 def _assign_attributes(model, attrs) if model.method(:attributes=).arity == 1 model.attributes = attrs else model.send(:attributes=, attrs, false) end end
_get_transport(symbol_or_object)
click to toggle source
# File lib/rails-archiver/unarchiver.rb, line 127 def _get_transport(symbol_or_object) if symbol_or_object.is_a?(Symbol) klass = if symbol_or_object.present? "RailsArchiver::Transport::#{symbol_or_object.to_s.classify}".constantize else Transport::InMemory end klass.new(@model, @logger) else symbol_or_object end end