Export MongoDB collection to ActiveRecord Model directly. Used for MongoId to ActiveRecord migration.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
require 'colorize' | |
module DatabaseTransformer | |
attr_reader :database | |
def initialize(database) | |
@database = database | |
end | |
def import(collection_name, *obsolete_columns, **rename_columns) | |
collection = Mongoid::Clients.default.collections.select do |c| | |
c.namespace == "#{database}.#{collection_name.to_s.pluralize}" | |
end.first | |
unless collection.present? | |
STDOUT.puts "#{collection_name.to_s.yellow}: skipped" | |
STDOUT.puts | |
return | |
end | |
constant = collection_name.to_s.singularize.camelcase.constantize | |
reset_callbacks constant | |
DatabaseTransformer.profiling do | |
collection_count = collection.find.count | |
collection.find.each_with_index do |document, index| | |
delete_obsolete_columns document, obsolete_columns | |
update_rename_columns document, rename_columns | |
update_id_columns document | |
document = yield document if block_given? | |
insert_record constant, document | |
STDOUT.puts "#{index}/#{collection_count}\n" if (index % 1000).zero? | |
end | |
end | |
end | |
private | |
def reset_callbacks(constant) | |
%i(create save update).each do |callback| | |
constant.reset_callbacks callback | |
end | |
end | |
def delete_obsolete_columns(document, obsolete_columns) | |
obsolete_columns.each { |column| document.delete column.to_s } | |
end | |
def update_rename_columns(document, rename_columns) | |
document.deep_transform_keys do |key| | |
new_key = rename_columns[key.to_sym] | |
new_key.present? ? new_key : key | |
end | |
end | |
def update_id_columns(document) | |
document.map! do |key, value| | |
next ['uuid', value.to_s] if key == '_id' # save _id to uuid temp | |
if key.end_with? '_id' # save xx_id to xx_uuid | |
uuid_key = key[0...-2] + 'uuid' | |
[uuid_key, value.to_s] | |
else | |
[key, value] # normal case | |
end | |
end | |
Hash[document] | |
end | |
def insert_record(constant, params) | |
model = constant.new params | |
model.save! validate: false | |
rescue Exception => exception | |
STDERR.puts "Import Error: #{exception}" | |
raise exception | |
end | |
def self.profiling | |
started_at = Time.now | |
yield if block_given? | |
seconds = Time.now.to_i - started_at.to_i | |
STDOUT.puts "Completed: #{seconds.to_s.green} seconds\n" | |
STDOUT.puts "\n" | |
end | |
end | |
transformer = DatabaseTransformer.new 'draven_production' | |
transformer.import :post, :_slugs, :status, title: :name, desc: :description, _type: :type | |
# Restore relation with https://gist.github.com/Draveness/c0798fb1272f483a176fa67741a3f1ee | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment