Skip to content

Instantly share code, notes, and snippets.

@shinenelson
Last active January 4, 2017 10:41
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 shinenelson/acdec385569e0ec37122388435f87dec to your computer and use it in GitHub Desktop.
Save shinenelson/acdec385569e0ec37122388435f87dec to your computer and use it in GitHub Desktop.
Generate collection map (YAML) for MoSQL (mongoid => Postgres) from rails console
#!/usr/bin/env ruby
# This script traverses over the fields in a model
# of a rails application to map them to
# the corresponding schema type in Postgres.
# The output generated is in YAML format
# and can be used as the collection map for MoSQL.
puts "#{Mongoid.default_session.options[:database]}:" # Print the database the application is connected to
models = Mongoid.models # Fetch all the models in the application
models.each do | model |
puts " #{model.collection_name}:" # Print Model's collection_name
puts " :columns:"
# Flags to check for common mongoid fields
id = false
created_at = false
updated_at = false
# Iterate over each field on the model and
# set id, created_at and updated_at if applicable
model.fields.each do | field |
case field.second.name
when "_id"
id = true
when "created_at"
created_at = true
when "updated_at"
updated_at = true
end
end
if id
puts " - id:"
puts " :source: _id"
puts " :type: TEXT"
end
if created_at
puts " - created_at: TIMESTAMP"
end
if updated_at
puts " - updated_at: TIMESTAMP"
end
# Declare Type Hash to map Mongoid :types to Postgres schema types
types = {
"Date" => "DATE",
"Time" => "TIMESTAMP",
"DateTime" => "TIMESTAMP",
"String" => "TEXT",
"Integer" => "INTEGER",
"Fixnum" => "INTEGER",
"Object" => "TEXT",
"Hash" => "JSON",
"Float" => "DOUBLE PRECISION",
}
# Declare Class Hash to map Mongoid :class to Postgres schema types
classes = {
"Mongoid::Boolean" => "BOOLEAN",
"BSON::Binary" => "BYTEA",
"BSON::Document" => "JSON",
"BSON::ObjectId" => "TEXT"
}
# Re-iterate over each field in the model
# to update the collection map with
# the respective field and type
model.fields.each do | field |
fs = field.second
unless fs.name.in? ["_id", "created_at", "updated_at"]
if fs.options[:type].to_s.in? (types.keys+classes.keys).uniq.map(&:to_s)
type = types["#{fs.options[:type]}"] || classes["#{fs.options[:type]}"]
puts " - #{fs.name}: #{type}"
elsif fs.options[:type].to_s == "Array"
if model.where(:"#{fs.name}".ne => []).first.attributes[:"#{fs.name}"].first.class.to_s.in? (types.keys+classes.keys).uniq.map(&:to_s)
type = types["#{model.where(:"#{fs.name}".ne => []).first.attributes[:"#{fs.name}"].first.class}"] || classes["#{model.where(:"#{fs.name}".ne => []).first.attributes[:"#{fs.name}"].first.class}"]
puts " - #{fs.name}: #{type} ARRAY"
# else
# puts " - #{fs.name}: #{model.where(:"#{fs.name}".ne => []).first.attributes[:"#{fs.name}"].first.class}"
end
# else
# puts " - #{fs.name}: #{fs.options[:type]}"
end
end
end
# Meta Information for Postgres
puts " :meta:"
puts " :table: #{model.collection_name}"
puts " :extra_props: true"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment