Module: TableStructured
- Defined in:
- lib/tablestructured.rb
Constant Summary collapse
- Error =
Class.new RuntimeError
Class Method Summary collapse
-
.new(object, headers: :top, drop_first: 0, drop_last: 0) ⇒ Object
TODO: headers_left should probably mean the ids of entries.
Class Method Details
.new(object, headers: :top, drop_first: 0, drop_last: 0) ⇒ Object
TODO: headers_left should probably mean the ids of entries
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/tablestructured.rb', line 3 def self.new object, headers: :top, drop_first: 0, drop_last: 0 # TODO: headers_left should probably mean the ids of entries if object.nil? raise ArgumentError, "passed object can be an Array or Ferrum Node, but not Nil" elsif object.respond_to? :css # the xml object ignores the :headers arg for now names = if :top == headers object elsif headers.respond_to? :css headers else fail "invalid type of headers" end.css("thead th")[drop_first..-1-drop_last].map do |_| _.text.sub(/\A[[[:space:]]]*/,"").sub(/[[[:space:]]]*\z/,"") end t = names.group_by(&:itself).map{ |k, g| [k, g.size.times.to_a] if 1 < g.size }.compact.to_h names = names.map{ |_| if i = t[_]&.shift then "#{_}_#{i+1}" else _ end.to_sym } struct = begin Struct.new *names rescue NameError raise $!.exception "#{$!}: #{names.inspect}" end require "timeout" object.css("tbody > tr").map do |row| tds = [] Timeout.timeout 5 do tds = [row.css("th"), *row.css("td")][drop_first..-1-drop_last] if tds.empty? STDERR.puts "empty row" sleep 0.1 redo end end raise Error, "size mismatch (#{names.size} headers (#{names}), #{tds.size} row items)" if tds.size != names.size struct.new *tds end else struct = Struct.new *(headers == :top ? object.first : headers).map(&:to_s).map(&:to_sym).tap{ |_| fail "headers should be unique" if _.uniq! } object.drop(headers == :top ? 1 : 0).map{ |_| struct.new *_ } end end |