Class: Soroban::Sheet
- Inherits:
-
Object
- Object
- Soroban::Sheet
- Defined in:
- lib/soroban/sheet.rb
Overview
A container for cells.
Instance Attribute Summary (collapse)
-
- (Object) bindings
readonly
Returns the value of attribute bindings.
Instance Method Summary (collapse)
-
- (Object) bind(options_hash)
Bind one or more named variables to a cell.
-
- (Object) cells
Return a hash of `label => contents` for each cell in the sheet.
- - (Object) factory(name)
-
- (Object) get(label_or_name)
Retrieve the contents of a cell.
-
- (Sheet) initialize(logger = nil)
constructor
Creates a new sheet.
-
- (Object) method_missing(method, *args, &block)
Used for calling dynamically defined functions, and for creating new cells (via `label=`).
-
- (Object) missing
Return a list of referenced but undefined cells.
-
- (Object) set(options_hash)
Set the contents of one or more cells or ranges.
-
- (Object) to_ruby(class_name)
Return a string containing a ruby class that implements the sheet.
-
- (Object) walk(range)
Visit each cell in the supplied range, yielding its value.
Constructor Details
- (Sheet) initialize(logger = nil)
Creates a new sheet.
15 16 17 18 19 20 21 |
# File 'lib/soroban/sheet.rb', line 15 def initialize(logger=nil) @logger = logger @cells = {} @compiled = {} @changes = Hash.new{ |h, k| h[k] = Set.new } @bindings = {} end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
- (Object) method_missing(method, *args, &block)
Used for calling dynamically defined functions, and for creating new cells (via `label=`).
76 77 78 79 80 81 82 83 |
# File 'lib/soroban/sheet.rb', line 76 def method_missing(method, *args, &block) if match = /^func_(.*)$/i.match(method.to_s) return Soroban::call(self, match[1], *args) elsif match = /^([a-z][\w]*)=$/i.match(method.to_s) return _add(match[1], args[0]) end super end |
Instance Attribute Details
- (Object) bindings (readonly)
Returns the value of attribute bindings
12 13 14 |
# File 'lib/soroban/sheet.rb', line 12 def bindings @bindings end |
Instance Method Details
- (Object) bind(options_hash)
Bind one or more named variables to a cell.
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/soroban/sheet.rb', line 121 def bind() .each do |name, label_or_range| _debug("binding '#{name}' to '#{label_or_range}'}") if Soroban::range?(label_or_range) LabelWalker.new(label_or_range).each do |label| next if @cells.keys.include?(label.to_sym) raise Soroban::UndefinedError, "Cannot bind '#{name}' to range '#{label_or_range}'; cell #{label} is not defined" end _bind_range(name, label_or_range) else unless @cells.keys.include?(label_or_range.to_sym) raise Soroban::UndefinedError, "Cannot bind '#{name}' to non-existent cell '#{label_or_range}'" end _bind(name, label_or_range) end end end |
- (Object) cells
Return a hash of `label => contents` for each cell in the sheet.
145 146 147 148 149 |
# File 'lib/soroban/sheet.rb', line 145 def cells labels = @cells.keys.map { |label| label.to_sym } contents = labels.map { |label| eval("@#{label}.excel") } Hash[labels.zip(contents)] end |
- (Object) factory(name)
23 24 25 26 |
# File 'lib/soroban/sheet.rb', line 23 def factory(name) eval(self.to_ruby(name), TOPLEVEL_BINDING) Object::const_get('Soroban').const_get('Model').const_get(name).new end |
- (Object) get(label_or_name)
Retrieve the contents of a cell.
110 111 112 113 114 115 116 117 118 |
# File 'lib/soroban/sheet.rb', line 110 def get(label_or_name) label = @bindings[label_or_name.to_sym] || label_or_name _debug("retrieving '#{label_or_name}' from '#{label}'}") if Soroban::range?(label) walk(label) else _get(label_or_name, eval("@#{label}", binding)) end end |
- (Object) missing
Return a list of referenced but undefined cells.
152 153 154 |
# File 'lib/soroban/sheet.rb', line 152 def missing @cells.values.flatten.uniq - @cells.keys end |
- (Object) set(options_hash)
Set the contents of one or more cells or ranges.
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/soroban/sheet.rb', line 86 def set() .each do |label_or_range, contents| _debug("setting '#{label_or_range}' to '#{contents}'") unless range = Soroban::getRange(label_or_range) _add(label_or_range, contents) next end fc, fr, tc, tr = range if fc == tc || fr == tr raise ArgumentError, "Expecting an array when setting #{label_or_range}" unless contents.kind_of? Array cc, cr = fc, fr contents.each do |item| set("#{cc}#{cr}" => item) cc.next! if fr == tr cr.next! if fc == tc end raise Soroban::RangeError, "Supplied array doesn't match range length" if cc != tc && cr != tr else raise ArgumentError, "Can only set cells or 1-dimensional ranges of cells" end end end |
- (Object) to_ruby(class_name)
Return a string containing a ruby class that implements the sheet. You can call eval() on this string to create the class, which you can then instantiate. Set inputs on the instance and read outputs off.
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/soroban/sheet.rb', line 31 def to_ruby(class_name) data = [] data << "module Soroban" data << "module Model" data << "class #{class_name}" data << " def initialize" data << " @binds = {" data << bindings.map do |name, cell| " '#{name}' => :#{cell}" end.join(",\n") data << " }" data << " @cache = {}" data << " @cells = {" data << @compiled.map do |label, cell| " :#{label} => lambda { @cache[:#{label}] ||= #{cell.to_compiled_ruby} }" end.join(",\n") data << " }" data << " end" data << " def clear" data << " @cache.clear" data << " end" data << " def get(name)" data << " @cells[@binds[name]].call" data << " end" data << " def set(name, value)" data << " self.clear" data << " @cells[@binds[name]] = lambda { @cache[@binds[name]] ||= value }" data << " end" bindings.each do |name, cell| data << " def #{name}" data << " get('#{name}')" data << " end" data << " def #{name}=(value)" data << " set('#{name}', value)" data << " end" end data << "end" data << "end" data << "end" puts data.join("\n") data.join("\n") end |
- (Object) walk(range)
Visit each cell in the supplied range, yielding its value.
140 141 142 |
# File 'lib/soroban/sheet.rb', line 140 def walk(range) ValueWalker.new(range, binding) end |