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
-
.delegated_array_class ⇒ Object
This adjustment to ‘DelegateClass(Array)` is necessary to allow calling puts on a
Tablesmith::Tableand still get the table output, rather than the default puts output of the underlyingArray.
Class Method Details
.delegated_array_class ⇒ Object
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 |