From 8130cf40433b179b1294625b747d306216c96d90 Mon Sep 17 00:00:00 2001 From: Michael Dvorkin Date: Tue, 5 Nov 2013 14:34:16 -0800 Subject: [PATCH] Refactored AwesomePrint::Plugin --- lib/awesome_print.rb | 1 + lib/awesome_print/ext/example.rb | 2 +- lib/awesome_print/plugin.rb | 44 ++++++++++++++++++++++---------- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/lib/awesome_print.rb b/lib/awesome_print.rb index d420e93..15e4dab 100755 --- a/lib/awesome_print.rb +++ b/lib/awesome_print.rb @@ -33,4 +33,5 @@ unless defined?(AwesomePrint::Inspector) require File.dirname(__FILE__) + "/awesome_print/ext/no_brainer" if defined?(NoBrainer) require File.dirname(__FILE__) + "/awesome_print/ext/ripple" if defined?(Ripple) require File.dirname(__FILE__) + "/awesome_print/ext/sequel" if defined?(Sequel) +# require File.dirname(__FILE__) + "/awesome_print/ext/example" end diff --git a/lib/awesome_print/ext/example.rb b/lib/awesome_print/ext/example.rb index 02c0ac2..d0c403b 100644 --- a/lib/awesome_print/ext/example.rb +++ b/lib/awesome_print/ext/example.rb @@ -10,7 +10,7 @@ module AwesomePrint def awesome_radix(object) # puts "example#awesome_radix(#{object.inspect})" - "#{object} (dec) 0#{object.to_s(8)} (oct) 0x#{object.to_s(16).upcase}" + "#{object} (dec) 0#{object.to_s(8)} (oct) 0x#{object.to_s(16).upcase} (hex)" end end end diff --git a/lib/awesome_print/plugin.rb b/lib/awesome_print/plugin.rb index 7ddd528..3535991 100644 --- a/lib/awesome_print/plugin.rb +++ b/lib/awesome_print/plugin.rb @@ -19,37 +19,53 @@ module AwesomePrint end def register(mod) - puts "mod.instance_methods: #{mod.instance_methods}" + # + # Make sure calling AwesomePrint::Plugin.register twice for the same + # plugin doesn't do any harm. + # + return nil if @list.include?(mod) + # + # The plugin *must* implement :cast(object, type) method. + # unless mod.instance_methods.include?(:cast) raise RuntimeError, "#{mod} plugin should define cast(object, type) instance method" end - - formatter = AwesomePrint::Formatter + # + # Create the hook name from the plugin's module name, for example: + # ActiveRecord => "active_record". Once we have the hook name rename + # generic :cast method to unique :cast_. + # hook = mod.name.gsub(/^.*::/, "").gsub(/(.)([A-Z])/, '\1_\2').downcase - mod.send(:alias_method, :"cast_#{hook}", :cast) mod.send(:remove_method, :cast) - - @list << mod + # + # Add plugin's instance methods to AwesomePrint::Formatter, then hook + # formatter's :cast method. + # + formatter = AwesomePrint::Formatter formatter.send(:include, mod) - - puts "defining cast_with_#{hook}..." - - # formatter.send(:alias_method, :"cast_without_#{hook}", :cast) + # + # The method chaining is done as follows: + # + # 1. Original :cast method becomes :cast_without_. + # 2. New :cast_with_ method gets created dynamically. It calls + # plugin's :cast (renamed :cast_ above) and if the return + # value is nil (i.e. no cast) it calls the original :cast from step 1. + # 3. Calling :cast now invokes :cast_with_ from step 2. + # chain_methods(formatter, hook) do formatter.send(:define_method, :"cast_with_#{hook}") do |object, type| - puts "cast_with_#{hook}(#{object.inspect}, #{type.inspect})" - cast = send(:"cast_#{hook}", object, type) || send(:"cast_without_#{hook}", object, type) + send(:"cast_#{hook}", object, type) || send(:"cast_without_#{hook}", object, type) end end - # formatter.send(:alias_method, :cast, :"cast_with_#{hook}") + @list << mod end private def chain_methods(formatter, hook) formatter.send(:alias_method, :"cast_without_#{hook}", :cast) - yield + yield # <-- Define :"cast_with_#{hook}". formatter.send(:alias_method, :cast, :"cast_with_#{hook}") end end