Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
After export all the record from MongoDB, use this to build relation in all records. You need to handle many to many relations by yourself
# frozen_string_literal: true
require 'colorize'
module RelationBuilder
attr_reader :constants
def initialize(constants = [])
if constants.present?
@constants = constants
else
Rails.application.eager_load!
@constants = ActiveRecord::Base.descendants.reject { |constant| constant.to_s.include?('::') }
end
end
def build!(polymorphic_associations = [], rename_associations = {})
constants.each do |constant|
build_relation constant, polymorphic_associations, rename_associations
end
end
def build_relations(class_name, polymorphic_associations = [], rename_associations = {})
uuids = class_name.attribute_names.select { |name| name.end_with? '_uuid' }
unless uuids.present?
STDOUT.puts "#{class_name.to_s.yellow}: skipped"
STDOUT.puts
return
end
reset_callbacks class_name
RelationBuilder.profiling do
models_count = class_name.count
class_name.unscoped.all.each_with_index do |model, index|
update_params = uuids.map do |uuid|
original_association_name = uuid[0...-5]
association_model = association_model(
original_association_name,
model[uuid],
polymorphic_associations,
rename_associations
)
[original_association_name.to_s, association_model]
end.compact
begin
Hash[update_params].each do |key, value|
model.send "#{key}=", value
end
model.save! validate: false
rescue Exception => e
STDERR.puts e
raise e
end
STDOUT.puts "#{index}/#{models_count}\n" if (counter % 1000).zero?
end
end
end
def association_model(original_name, uuid, polymorphics, rename_associations)
association_name = rename_associations[original_name.to_sym] || original_name
association_name = model["#{original_name}_type".to_sym] if polymorphics.include? original_name.to_sym
return unless association_name.present?
association_constant = association_name.to_s.camelcase.constantize
association_constant.find_by uuid: uuid
end
def reset_callbacks(constant)
%i(create save update).each do |callback|
constant.reset_callbacks callback
end
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
builder = RelationBuilder.new([Post, Comment])
builder.build!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment