module DR module Converter extend self #convert an obj to hash, using 'methods' for the methods attributes def to_hash(obj=nil, methods:[], recursive: false, check: false, compact: false) return {} if obj.nil? obj||=self stack=[*obj] processed=[] klass=stack.first.class h={} while !stack.empty? obj=stack.shift next if processed.include?(obj) processed << obj attributes={} methods.each do |m| next if check and !obj.respond_to? m v=obj.public_send(m) attributes[m]=v if recursive vals=v.kind_of?(Enumerable) ? v.to_a.flatten : [v] vals.select! {|v| v.kind_of?(klass)} stack.concat(vals) end end attributes=attributes.values.first if compact and attributes.keys.length == 1 h[obj]=attributes end h end end end