class ConfigFileGenerator

Attributes

date[RW]
environment[RW]
template[RW]

Public Class Methods

new(template_path: 'deployment/templates', vars: File.join(template_path, 'vars.yml')) click to toggle source

Set up our instance variables so that we can pass them to the template.

# File lib/config_file_generator.rb, line 12
def initialize(template_path: 'deployment/templates', vars: File.join(template_path, 'vars.yml'))
  @templates = find_templates(template_path)
  @template_vars = load_vars(vars)
end

Public Instance Methods

generate(environment, output_directory: File.join('deployment', environment), dry_run: false) click to toggle source

Parse the templates given to the class. If an output directory is given to this function, write out the parsed templates to files within that

directory with the same name, without the ".erb"
Directory structure is also preserved.

If an output directory isn't given, just print out the parsed templates to stdout.

Basically, this allows for a "dry run" which is useful for testing that your templates are looking solid.
# File lib/config_file_generator.rb, line 23
def generate(environment, output_directory: File.join('deployment', environment), dry_run: false)
  if dry_run == true or dry_run.to_s.downcase == 'true'
    puts "Running generate() in dry_run. Printing parsed templates to stdout instead of to a file:"
    for template in @templates
      # Fail early if the template uses variables that weren't passed in.
      check_required_vars(template, environment)
      puts "\n~~~~~~~~~~ #{template} ~~~~~~~~~~\n\n"
      puts render(template, environment)
    end
  else
    for template in @templates
      # Fail early if the template uses variables that weren't passed in.
      check_required_vars(template, environment)
      begin
        file_name = File.join(output_directory, File.basename(template, '.erb'))
        File.open(file_name, 'w+') do |f|
          f.write(render(template, environment))
        end
      rescue Errno::ENOENT # if directory path doesn't exist, create it
        FileUtils.mkdir_p(File.dirname(file_name))
        retry
      end

    end
  end
end

Private Instance Methods

check_required_vars(template, environment) click to toggle source

Check that the caller passed in one of every variable that is needed by the template. If not, raise.

# File lib/config_file_generator.rb, line 92
def check_required_vars(template, environment)
  template_vars = get_vars_used_in_template(template).sort
  passed_vars = @template_vars[environment].keys.sort.map {|x| x.to_s}
  difference = template_vars - passed_vars
  unless difference.empty?
    raise "\n\nNot all required variables were provided for template '#{template}'.\n" + \
          "Missing variables: #{difference}\n" + \
          "The variables provided were: #{passed_vars}\n\n"
  end
end
find_templates(template_path) click to toggle source

Returns an array of templates. If a directory is passed in, then it returns all files within that directory (recursively). If a file is passed in, then just that file is returned.

# File lib/config_file_generator.rb, line 59
def find_templates(template_path)
  if File.directory?(template_path)
    Dir["#{template_path}/**/*"].select do |file|
      File.file?(file) and File.extname(file) == '.erb' and ! file.include? 'vars.yml'
    end
  elsif File.file?(template_path)
    [template_path]
  else
    raise "Need a valid Template file path. Instead received: '#{template_path}', " + \
           "which doesn't look to exist."
  end
end
get_vars_used_in_template(template) click to toggle source

Get all of the variables used within the template so that we can let the user know which variables they need to be passing in.

# File lib/config_file_generator.rb, line 87
def get_vars_used_in_template(template)
  File.read(template).scan(/<%= ?([a-z]+[0-9a-z_]*)/i).uniq.flatten
end
load_vars(vars) click to toggle source

Load variables for use within the templates. Accepts either a file path or a Hash.

# File lib/config_file_generator.rb, line 74
def load_vars(vars)
  if File.file?(vars)
    YAML.load(File.read(vars))
  elsif vars.is_a?(Hash)
    vars
  else
    raise "Either a Hash or a file path is required to load template variables from. " + \
          "Instead received: #{vars}"
  end
end
render(template, environment) click to toggle source

ERB passes variables to the template from a Binding, an object that provides access to the instance

methods and variables that are owned by another object.

If you do not specify a Binding, the result() method only passes the Binding to the template for

the top-level object. To pass the template your class's binding (probably what you want), you
must pass render() your class's private binding() instance method (which Ruby provides) as done here.
# File lib/config_file_generator.rb, line 108
def render(template, environment)
  vars = OpenStruct.new(@template_vars[environment]).instance_eval { binding }
  ERB.new(File.read(template)).result(vars)
end