Module: Tablesmith

Defined in:
lib/tablesmith/table.rb,
lib/tablesmith/version.rb,
lib/tablesmith/delegated_array_class.rb

Defined Under Namespace

Modules: ActiveRecordSource, ArrayRowsSource, HashRowsBase, HashRowsSource Classes: Column, Table

Constant Summary collapse

VERSION =
'0.7.0'

Class Method Summary collapse

Class Method Details

.delegated_array_classObject

This adjustment to ‘DelegateClass(Array)` is necessary to allow calling puts on a Tablesmith::Table and still get the table output, rather than the default puts output of the underlying Array.

Explaining why requires breaking some things down.

The implementation of Kernel::puts has special code for an Array. The code inside rb_io_puts (in io.c) first checks to see if the object passed to it is a String. If not, it then calls io_puts_ary, which in turn calls rb_check_array_type. If rb_check_array_type confirms the passed object is an Array, then io_puts_ary loops over the elements of the Array and passes it to rb_io_puts. If the Array check fails in the original rb_io_puts, rb_obj_as_string is used.

Early versions of Tablesmith::Table subclassed Array, but even after changing Tablesmith::Table to use any of the Delegator options, the code in rb_check_array_type still detected Tablesmith::Table as an Array. How does it do this?

rb_check_array_type calls:

`return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);`

If a straight up type check fails, then it attempts to convert the object to an Array via the to_ary method.

And wha-lah. We simply need to undefine the to_ary method added to Tablesmith::Table by ‘DelegateClass(Array)` and rb_io_puts will no longer output Table as an Array and will use its to_s method, the same as print.



36
37
38
39
40
# File 'lib/tablesmith/delegated_array_class.rb', line 36

def self.delegated_array_class
  DelegateClass(Array).tap do |klass|
    klass.undef_method(:to_ary)
  end
end