# Copyright:: (c) Autotelik Media Ltd 2015
# Author :: Tom Statter
# Date :: Mar 2015
# License:: MIT
#
# Details:: Generate an empty Configuration file, users can populate
# to configure their specific import and export
#
require 'generator_base'
module DataShift
class ConfigGenerator < GeneratorBase
def self.title
@mappings_title ||= "datashift_mappings:\n"
end
attr_accessor :output_filename, :headers
attr_writer :import_template, :export_template
def initialize
super
end
def import_template
@import_template ||= File.join(DataShift.library_path, 'datashift/templates/import_export_config.erb')
end
def export_template
@export_template ||= File.join(DataShift.library_path, 'datashift/templates/import_export_config.erb')
end
# You can pass Transformations into the options
#
# options[:defaults]
# options[:overrides]
# options[:substitutions]
# options[:prefixes]
# options[:postfixes]
#
# For example :
#
# options = {
# defaults: {'value_as_string': 'some default text', 'value_as_double': 45.467 }
# }
#
def write_import(file_name, klass_or_name, options = {})
result = create_import_config(klass_or_name, options)
logger.info("Writing Import Config File [#{file_name}]")
File.open(file_name, 'w') { |f| f << result }
result
end
# N.B Gettign the YAML formatted correctly was nigh on impossible in ERB,
# be careful of the spacing in the string sections here e.g dont use IDE auto spacing tools
# TODO: - How to better isolate these string template snippets
# Create an YAML ERB Configuration template for Importing.
# Includes available transformations and column mapping
#
# For other options See DataShift::Loaders::Configuration
#
def create_section(hash)
section = ''
(hash || { "#name": 'value' } ).each { |n, v| section += " #{n}: #{v}\n" }
section
end
def create_import_config(klass_or_name, options = {})
klass = MapperUtils.ensure_class(klass_or_name)
@key = 'data_flow_schema'
@klass = klass.name.to_s
defaults_section = create_section(options[:defaults] )
overrides_section = create_section(options[:overrides] )
prefixes_section = create_section(options[:prefixes] )
postfixes_section = create_section(options[:postfixes] )
@substitutions = options[:substitutions] || {}
# operator => [rule , replacement]
substitutions_section = ''
@substitutions.each do |o, v|
raise BadConfig, 'Substitutions need be in format {operator: [rule, replacement]}' unless(v.is_a? Array)
substitutions_section += <<-EOS
#{o}:
- #{v.first}
- #{v.last}
EOS
end
@headers = Headers.klass_to_headers(klass)
nodes_section = <<-EOS
# Mappings between inbound column names and internal names
# are only required when datashift cannot guess the mapping itself
# It will automatically map headings like :
# 'Product properties' or 'Product_Properties', 'product Properties' etc to product_properties
nodes:
EOS
@headers.each_with_index do |s, _i|
nodes_section += <<-EOS
- #{s}:
heading:
source: #{s}
presentation: #{s}
EOS
end
x = <<-EOS
# YAML Configuration file for Datashift Import/Export
#
#{@key}:
#{@klass}:
defaults:
#{defaults_section}
overrides:
#{overrides_section}
# Expects a tuple (list with 2 entries), the rule and the replacement
substitutions:
#{substitutions_section}
prefixes:
#{prefixes_section}
postfixes:
#{postfixes_section}
#{nodes_section}
EOS
# This was a nightmare to get proeprly formatted YAML
# Erubis::Eruby.new( File.read(import_template)).result(binding)
x
end
# FOR EXPORTERS
def write_export(file_name, klass_or_name, options = {})
result = export(klass_or_name, options)
logger.info("Writing Export Config File [#{config[:file]}]")
File.open(file_name, 'w') { |f| f << result }
end
# Create an YAML Configuration template for Exporting
# includes available transformations and column mapping
#
# For other options See DataShift::Exporters::Configuration
#
def export(klass_or_name, options = {})
@klass = MapperUtils.ensure_class(klass_or_name)
@title = @klass.name.to_s
@defaults = options[:defaults] || []
@overrides = options[:overrides] || []
@substitutions = options[:substitutions] || []
@prefixs = options[:prefixs] || []
@postfixs = options[:postfixs] || []
klass_to_headers(@klass)
Erubis::Eruby.new( File.read(export_template)).result(binding)
end
# Create an YAML template BAASED on an Excel spreadsheet for mapping headers
#
# * :title - Top level YAML node -defaults to ConfigGenerator.title
#
# * :model_as_dest - Override default treatment of using model as the SOURCE
#
# * :file - Write mappings direct to file name provided
#
def generate_from_excel(excel_file_name, options = {})
excel = Excel.new
puts "\n\n\nGenerating mapping from Excel file: #{excel_file_name}"
excel.open(excel_file_name)
sheet_number = options[:sheet_number] || 0
sheet = excel.worksheet( sheet_number )
@headers = excel.parse_headers(sheet, options[:header_row] || 0)
mappings = options[:title] || ConfigGenerator.title
if options[:model_as_dest]
headers.each_with_index { |s, i| mappings += " #srcs_column_heading_#{i}: #{s}\n" }
else
headers.each_with_index { |s, i| mappings += " #{s}: #dest_column_heading_#{i}\n" }
end
File.open(options[:file], 'w') { |f| f << mappings } if options[:file]
mappings
end
end
end # DataShift