sup

A curses threads-with-tags style email client

sup.git

git clone https://supmua.dev/git/sup/
commit db1aa1429d96745b8a0c5f030a2170d71f8dfd86
parent 98d82009ec97951bfc55b6c5a1cc5785353bda49
Author: Whyme Lyu <callme5long@gmail.com>
Date:   Tue, 28 May 2013 23:10:35 +0800

Support loading legacy YAML for now.

Diffstat:
M lib/sup.rb | 27 ++++++++++++++++++++-------
M lib/sup/modes/inbox_mode.rb | 2 +-
A test/test_yaml_migration.rb | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 101 insertions(+), 8 deletions(-)
diff --git a/lib/sup.rb b/lib/sup.rb
@@ -22,17 +22,29 @@ end
 class Module
   def yaml_properties *props
     props = props.map { |p| p.to_s }
-    vars = props.map { |p| "@#{p}" }
     klass = self
-    path = klass.name.gsub(/::/, "/")
 
     klass.instance_eval do
-      define_method(:to_yaml_properties) { vars }
-      define_method(:to_yaml_type) { "!#{Redwood::YAML_DOMAIN},#{Redwood::YAML_DATE}/#{path}" }
-    end
+      def self.to_yaml_tag
+        path = name.gsub(/::/, "/")
+        "!#{Redwood::YAML_DOMAIN},#{Redwood::YAML_DATE}/#{path}"
+      end
+
+      define_method(:to_yaml_type) { self.class.to_yaml_tag }
+      define_method :init_with do |coder|
+        initialize(*coder.map.values_at(*props))
+      end
+      
+      define_method :encode_with do |coder|
+        coder.map = props.inject({}) do |hash, key|
+          hash[key] = instance_variable_get("@#{key}")
+          hash
+        end
+      end
 
-    YAML.add_domain_type("#{Redwood::YAML_DOMAIN},#{Redwood::YAML_DATE}", path) do |type, val|
-      klass.new(*props.map { |p| val[p] })
+      yaml_tag to_yaml_tag
+      path = name.gsub(/::/, "/")
+      Psych.load_tags["!#{Redwood::LEGACY_YAML_DOMAIN},#{Redwood::YAML_DATE}/#{path}"] = self
     end
   end
 end
@@ -53,6 +65,7 @@ module Redwood
   LOG_FN     = File.join(BASE_DIR, "log")
 
   YAML_DOMAIN = "supmua.org"
+  LEGACY_YAML_DOMAIN = "masanjin.net"
   YAML_DATE = "2006-10-01"
 
   ## record exceptions thrown in threads nicely
diff --git a/lib/sup/modes/inbox_mode.rb b/lib/sup/modes/inbox_mode.rb
@@ -1,4 +1,4 @@
-require 'sup'
+require "sup/modes/thread_index_mode"
 
 module Redwood
 
diff --git a/test/test_yaml_migration.rb b/test/test_yaml_migration.rb
@@ -0,0 +1,80 @@
+require "test_helper"
+
+require "sup"
+require "psych"
+
+describe "Sup's YAML util" do
+  describe "Module#yaml_properties" do
+    def build_class_with_name name, &b
+      Class.new do
+        meta_cls = class << self; self; end
+        meta_cls.send(:define_method, :name) { name }
+        class_exec(&b) unless b.nil?
+      end
+    end
+
+    after do
+      Psych.load_tags = {}
+      Psych.dump_tags = {}
+    end
+
+    it "defines YAML tag for class" do
+      cls = build_class_with_name 'Cls' do
+        yaml_properties
+      end
+
+      expected_yaml_tag = "!supmua.org,2006-10-01/Cls"
+
+      Psych.load_tags[expected_yaml_tag].must_equal cls
+      Psych.dump_tags[cls].must_equal expected_yaml_tag
+
+    end
+
+    it "Loads legacy YAML format as well" do
+      cls = build_class_with_name 'Cls' do
+        yaml_properties :id
+        attr_accessor :id
+        def initialize id
+          @id = id
+        end
+      end
+
+      Psych.load_tags["!masanjin.net,2006-10-01/Cls"].must_equal cls
+
+      yaml = <<EOF
+--- !masanjin.net,2006-10-01/Cls
+id: ID
+EOF
+      loaded = YAML.load(yaml)
+
+      loaded.id.must_equal 'ID'
+      loaded.must_be_kind_of cls
+    end
+
+    it "Dumps & loads w/ state re-initialized" do
+      cls = build_class_with_name 'Cls' do
+        yaml_properties :id
+        attr_accessor :id
+        attr_reader :flag
+
+        def initialize id
+          @id = id
+          @flag = true
+        end
+      end
+
+      instance = cls.new 'ID'
+
+      dumped = YAML.dump(instance)
+      loaded = YAML.load(dumped)
+
+      dumped.must_equal <<-EOF
+--- !supmua.org,2006-10-01/Cls
+id: ID
+      EOF
+
+      loaded.id.must_equal 'ID'
+      assert loaded.flag
+    end
+  end
+end