lib/table_helper/row.rb in table_helper-0.0.3 vs lib/table_helper/row.rb in table_helper-0.0.4

- old
+ new

@@ -1,72 +1,103 @@ require 'table_helper/cell' module PluginAWeek #:nodoc: module TableHelper + # Provides a blank class that can be used to build the cells for a row + class RowBuilder < BlankSlate + reveal :respond_to? + + attr_reader :row + + # Creates a builder for the given row + def initialize(row) + @row = row + end + + # Proxies all missed methods to the row + def method_missing(*args) + row.send(*args) + end + + # Defines the builder method for the given cell name. For example, if + # a cell with the name :title was defined, then the cell would be able + # to be read and written like so: + # + # row.title #=> Accesses the title + # row.title "Page Title" #=> Creates a new cell with "Page Title" as the content + def define_cell(name) + method_name = name.gsub('-', '_') + + klass = class << self; self; end + klass.class_eval do + define_method(method_name) do |*args| + if args.empty? + row.cells[name] + else + row.cell(name, *args) + end + end + end unless klass.method_defined?(method_name) + end + + # Removes the definition for the given cell + def undef_cell(name) + method_name = name.gsub('-', '_') + + klass = class << self; self; end + klass.class_eval do + remove_method(method_name) + end + end + end + # Represents a single row within a table. A row can consist of either # data cells or header cells. class Row < HtmlElement + # The proxy class used externally to build the actual cells + attr_reader :builder + + # The current cells in this row, in the order in which they will be built + attr_reader :cells + def initialize #:nodoc: super @cells = ActiveSupport::OrderedHash.new + @builder = RowBuilder.new(self) end # Creates a new cell with the given name and generates shortcut # accessors for the method. def cell(name, *args) name = name.to_s if name cell = Cell.new(name, *args) - @cells[name] = cell + cells[name] = cell + builder.define_cell(name) if name - define_cell_accessor(name) if name && !respond_to?(name) - cell end # The names of all cells in this row def cell_names - @cells.keys + cells.keys end # Clears all of the current cells from the row def clear - cell_names.each do |name| - klass = class << self; self; end - klass.class_eval do - remove_method(name) - end - end - - @cells.clear + # Remove all of the shortcut methods + cell_names.each {|name| builder.undef_cell(name)} + cells.clear end private - # Defines the accessor method for the given cell name. For example, if - # a cell with the name :title was defined, then the cell would be able - # to be read and written like so: - # - # row.title #=> Accesses the title - # row.title "Page Title" #=> Creates a new cell with "Page Title" as the content - def define_cell_accessor(name) - instance_eval <<-end_eval - def #{name.gsub('-', '_')}(*args) - if args.empty? - @cells[#{name.inspect}] - else - cell(#{name.inspect}, *args) - end - end - end_eval - end - def tag_name 'tr' end def content - @cells.values.map(&:html).join + cells.values.map(&:html).join end end end end