Skip to content

Instantly share code, notes, and snippets.

@draveness
Last active October 7, 2017 15:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save draveness/10476fe67a10128a37ba27a4c6967d07 to your computer and use it in GitHub Desktop.
Save draveness/10476fe67a10128a37ba27a4c6967d07 to your computer and use it in GitHub Desktop.
Export MongoDB collection to ActiveRecord Model directly. Used for MongoId to ActiveRecord migration.
# 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