require "yaml" require "json" require "json_schema" require "active_support" require "active_support/core_ext" module Hasmenu class Validator include Printer def initialize(type, options) @type = type.chomp("/") @schemad = options[:schema] || File.join(Dir.pwd, ".meta", "schema") end def load_schema file = File.join(@schemad, "#{@type}.json") if File.file? file schema_data = JSON.parse File.read(file) @schema, error = JsonSchema.parse(schema_data) if error puts error return false end return true else print_invalid_path return false end end def validate_uniqueness(data) schema_data = JSON.parse '{"type": "array", "items": {"type": "string"}, "uniqueItems": true}' schema = JsonSchema.parse!(schema_data) validated, errors = schema.validate(data) unless validated puts errors duplicates = data.group_by { |e| e }.select { |k, v| v.size > 1 }.map(&:first) puts JSON.dump duplicates end end def validate(path) print_header path data = YAML.load_file(path) # check valid schema validated, errors = @schema.validate(data) puts errors unless validated # check unique columns type, subtype = @type.split("/") case type when "chains", "restaurants" validate_uniqueness(data.map { |x| x["uid"] }) when "menu" case subtype when "chain" menus = data["chain"]["menus"] if data["chain"] when "restaurant" menus = data["restaurant"]["menus"] if data["restaurant"] end end if menus validate_uniqueness(menus.map { |m| m["uid"] }) menus.each do |menu| sections = menu["sections"] validate_uniqueness(sections.map { |s| s["uid"] }) items = sections.map { |s| s["items"].reject { |i| i["repeat"] } }.flatten validate_uniqueness(items.map { |i| i["uid"] }) validate_uniqueness(items.map { |i| i["name"] }) print_warn_repeats \ if sections.map { |s| s["items"].select { |i| i["repeat"] } }.flatten.present? end end # check file naming conventions if menus menu = menus.first filename = File.basename(path, ".yml") # sequence if menu && menu.key?("active") && !menu["active"] print_invalid_sequence unless filename[0..2] == "xa-" else print_invalid_sequence unless filename[0..2] =~ /[0-9][0-9]-/ end # version print_invalid_version unless filename[3..-1] == "#{menu['uid']}-v#{menu['version']}" end end def validate_all(path) Dir.glob(File.join(path, "**", "*.yml")) do |file| validate file end end def perform(path) unless File.exist? path print_invalid_path return end return unless load_schema if File.file? path validate path elsif File.directory? path validate_all path else print_invalid_path end end end end