From 484ee329c1b0849d8675f5600bc4535f977508b4 Mon Sep 17 00:00:00 2001 From: "Gary S. Weaver" Date: Tue, 25 Feb 2014 16:01:21 -0500 Subject: [PATCH] writer should use code/iso8601 for date/time/datetime, not inspect --- lib/seed-fu/source_extensions.rb | 113 +++++++++++++++++++++++++++++++ lib/seed-fu/writer.rb | 4 +- 2 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 lib/seed-fu/source_extensions.rb diff --git a/lib/seed-fu/source_extensions.rb b/lib/seed-fu/source_extensions.rb new file mode 100644 index 0000000..7b6623b --- /dev/null +++ b/lib/seed-fu/source_extensions.rb @@ -0,0 +1,113 @@ +# Depending on what has been predefined, these may need to be required. +require 'date' unless defined?(::DateTime) +require 'time' unless ::Time.respond_to?(:iso8601) + +class ::Object + def seed_fu_source + inspect + end +end + +module ::SeedFu + module RecursiveSource + def seed_fu_source + escaped_result = (convert = ->(obj) do + case obj + when ::Array + obj.map {|v| convert.call(v)} + when ::Hash + ::Hash[obj.map{|k,v| [convert.call(k), convert.call(v)]}] + else + obj.seed_fu_source + end + end)[self].inspect + + # We did inspect because the hash must be converted to a string, but + # now we must convert the double-escaped string to a single escaped + # string and remove quote wrappers around code and numbers. + # + # For a list of the escape codes handled here: + # http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Literals#Backslash_Notation + result = '' + parse_mode = :normal + escape_char_array = nil + escaped_result.each_char do |c| + if parse_mode == :special + chars_left -= 1 + escape_char_array << c + if chars_left == 0 + if escape_char_array[0] == 'M' && escape_char_array[2] == "\\" + chars_left = 3 + else + result << eval(['"\\', *escape_char_array, '"'].join) + parse_mode = :normal + end + end + elsif parse_mode == :normal_escape + case c + when 'n'; result << "\n" + when 's'; result << "\s" + when 'r'; result << "\r" + when 't'; result << "\t" + when 'v'; result << "\v" + when 'f'; result << "\f" + when 'b'; result << "\b" + when 'a'; result << "\a" + when 'e'; result << "\e" + when 'r'; result << "\r" + when *(0..9); escape_char_array = [c]; parse_mode = :special; chars_left = 2 # we got \n and need nn + when 'x'; escape_char_array = [c]; parse_mode = :special; chars_left = 2 # we got \x and need nn + when 'u'; escape_char_array = [c]; parse_mode = :special; chars_left = 4 # we got \u and need nnnn + when 'c'; escape_char_array = [c]; parse_mode = :special; chars_left = 1 # we got \c and need x + when 'C'; escape_char_array = [c]; parse_mode = :special; chars_left = 2 # we got \C and need -x + when 'M'; escape_char_array = [c]; parse_mode = :special; chars_left = 2 # we got \M and need -x, or got \M and need -\C-x + else + result << c + parse_mode = :normal + end + else + case c + when "\\"; parse_mode = :normal_escape + when '"' # ignore unescaped quote, since we are unescaping + else + result << c + end + end + end + + result + end + end +end + +class ::Array + include ::SeedFu::RecursiveSource +end + +class ::Hash + include ::SeedFu::RecursiveSource +end + +class ::ActiveSupport::TimeWithZone + def seed_fu_source + "DateTime.iso8601(#{iso8601.inspect})" + end +end if defined?(::ActiveSupport::TimeWithZone) + +class ::DateTime + def seed_fu_source + "DateTime.iso8601(#{iso8601.inspect})" + end +end + +class ::Date + def seed_fu_source + "Date.iso8601(#{iso8601.inspect})" + end +end + +class ::Time + def seed_fu_source + "Time.iso8601(#{iso8601.inspect})" + end +end diff --git a/lib/seed-fu/writer.rb b/lib/seed-fu/writer.rb index 04e28fd..a90a642 100644 --- a/lib/seed-fu/writer.rb +++ b/lib/seed-fu/writer.rb @@ -1,3 +1,5 @@ +require 'seed-fu/source_extensions' + module SeedFu # {Writer} is used to programmatically generated seed files. For example, you might want to write # a script which converts data in a CSV file to a valid Seed Fu seed file, which can then be @@ -76,7 +78,7 @@ def <<(seed) end buffer << ",\n" - buffer << ' ' + seed.inspect + buffer << ' ' + seed.seed_fu_source @io.write(buffer)