lib/yaml_normalizer/services/normalize.rb
# frozen_string_literal: true
require 'peach'
module YamlNormalizer
module Services
# Normalize is a service class that provides functionality to update giving
# YAML files to a standardized (normalized) format.
# @exmaple
# normalize = YamlNormalizer::Services::Normalize.new('path/to/*.yml')
# result = normalize.call
class Normalize < Base
include Helpers::Normalize
include Helpers::ParamParser
# files is a sorted array of file path Strings
attr_reader :files
# Create a Normalize service object by calling .new and passing one or
# more String that are interpreted as file glob pattern.
# @param *args [Array<String>] a list of file glob patterns
def initialize(*args)
parse_params(*args)
files = args.each_with_object([]) { |a, o| o << Dir[a.to_s] }
@files = files.flatten.sort.uniq
end
# Normalizes all YAML files defined on instantiation.
def call
files.peach { |file| process(file) }
end
private
def process(file)
if IsYaml.call(file)
normalize!(file)
else
$stderr.print "#{file} not a YAML file\n"
end
end
def normalize!(file)
file = relative_path_for(file)
if stable?(input = read(file), norm = normalize_yaml(input))
File.open(file, 'w') { |f| f.write(norm) }
$stderr.print "[NORMALIZED] #{file}\n"
else
$stderr.print "[ERROR] Could not normalize #{file}\n"
end
end
def stable?(yaml_a, yaml_b)
convert(yaml_a).each_with_index.all? do |a, i|
a.namespaced.eql?(convert(yaml_b).fetch(i).namespaced)
end
end
def convert(yaml)
ary = Psych.parse_stream(yaml).transform
ary.each { |hash| hash.extend(Ext::Namespaced) }
ary
end
end
end
end