refactoring - How to refactor singleton methods in Ruby? -


currently have code following (simplified somewhat). eventually, i've added more , more new classes d1/d2, , think it's time refactoring make more elegant. goal of course make adding new class dx use little duplicate code possible. @ least, duplicate parts of calling fileimporter.import inside singleton method dx.import should factored out.

module fileimporter   def self.import(main_window, viewers)     ...     importer = yield file  # delegate d1/d2 preparing importer object     ...   end end  class d1   def self.import(main_window)     viewers = [:v11, ]  # d1 specific viewers     fileimporter.import(main_window, viewers) |file|       importer = self.new(file)       ...  # d1 specific handling of importer       return importer     end   end end  class d2   def self.import(main_window)     viewers = [:v21,:v22, ]  # d2 specific viewers     fileimporter.import(main_window, viewers) |file|       importer = self.new(file)       ...  # d2 specific handling of importer       return importer     end   end end  # client code calls d1.import(...) or d2.import(...) 

essentially fileimporter.import common part, dx.import being variation. i'm not sure how refactor these singleton methods. common ruby way of doing this?

update: (some comments added code above, make intension clearer ...)

originally, i've left out code thought not significant avoid confusion. should have mentioned code above result of refactoring class d1 , d2 (by moving common part out , module fileimporter). purpose of d1.import , d2.import create objects of proper class (and possibly followed class-specific handling before returning block). fileimporter.import common logic, within @ point yield specific class generating importer object.

i feel class d1 , d2 , looks similar , should possible further refactor them. example, both call fileimporter.import supply block, within both create object of itself.

solution: didn't realize call base class's singleton methods calling super within derived class's corresponding singleton methods. main problem had , not able go route. i've accepted @makevoid answer indeed makes creating new derived classes more easily.

using common base class elegant refactoring solution, 1 problem new derived classes use 1 base class quota. i've came class macro method provides more concise results derived class perspective.

module fileimporter   def self.included(mod)     mod.extend classmethods   end    module classmethods     def importer_viewer(*viewers, &blk)       @viewers = viewers       @blk = blk        class << self         def import(main_window)           if @blk.nil?             fileimporter.import(main_window, @viewers) |file|               self.new(file)             end           else             fileimporter.import(main_window, @viewers, &@blk)           end               end       end     end   end    def self.import(main_window, viewers, multi=true)     ...     importer = yield file  # delegate d1/d2 preparing importer object     ...   end end  class d1   include fileimporter   importer_viewer [:v11, ]     ...  # d1 specific handling of importer   end end  class d2   include fileimporter   importer_viewer [:v21,:v22, ]     ...  # d2 specific handling of importer   end end 

maybe it's not best solution @ first seems dx classes share same behaviour, sublassing them c class has self.import method uses block accept other code work. or done including module too.

anyway, should work (sorry shorter names prototyping). notice changed fileimporter.import method name avoid misunderstandings , note haven't tested code :)

module f   def self.fimport(something)     yield "file"   end end   class c      include f     def initialize(f)    end    def self.import(something, &block)     f.fimport(something) { |f|       d = self.new(f)       block.call       d     }   end end   class d1 < c   def self.import(something)     super(something){       puts     }   end end   class d2 < c   def self.import(something)     super(something){       puts     }   end end  p d1.import("a") p d2.import("b")  #=> #=> #<d1:0x100163068> #=> b #=> #<d2:0x100162e88> 

Comments

Popular posts from this blog

c++ - Convert big endian to little endian when reading from a binary file -

C#: Application without a window or taskbar item (background app) that can still use Console.WriteLine() -

unicode - Are email addresses allowed to contain non-alphanumeric characters? -