fit 1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. data/README.txt +203 -0
  2. data/Rakefile +111 -0
  3. data/bin/FitServer.rb +6 -0
  4. data/bin/fit +10 -0
  5. data/bin/fit.cgi +36 -0
  6. data/doc/examples/AllCombinations.html +55 -0
  7. data/doc/examples/AllFiles.html +60 -0
  8. data/doc/examples/AllPairs/function/cosine.html +57 -0
  9. data/doc/examples/AllPairs/function/sine.html +57 -0
  10. data/doc/examples/AllPairs/magnitude/180+30.html +45 -0
  11. data/doc/examples/AllPairs/magnitude/30.html +33 -0
  12. data/doc/examples/AllPairs/magnitude/360+30.html +45 -0
  13. data/doc/examples/AllPairs/magnitude/90-30.html +45 -0
  14. data/doc/examples/AllPairs/sign/change-sign.html +27 -0
  15. data/doc/examples/AllPairs/sign/multiply.html +31 -0
  16. data/doc/examples/AllPairs/sign/no-change.html +23 -0
  17. data/doc/examples/AllPairs.html +51 -0
  18. data/doc/examples/BinaryChop.html +89 -0
  19. data/doc/examples/CalculatorExample.html +108 -0
  20. data/doc/examples/ColumnIndex.html +43 -0
  21. data/doc/examples/ExampleTests.html +43 -0
  22. data/doc/examples/FitAcceptanceTests.html +53 -0
  23. data/doc/examples/GeoCoordinate.html +87 -0
  24. data/doc/examples/MusicExample.html +143 -0
  25. data/doc/examples/MusicExampleWithErrors.html +128 -0
  26. data/doc/examples/NetworkExample.html +47 -0
  27. data/doc/examples/WebPageExample.html +92 -0
  28. data/doc/examples/arithmetic.html +211 -0
  29. data/doc/examples/files/hp35bk.jpg +0 -0
  30. data/doc/examples/logo.gif +0 -0
  31. data/doc/fitnesse/FitNesse.RubY.AcceptanceTests.FixtureParameters.html +81 -0
  32. data/doc/fitnesse/FitNesse.RubY.AcceptanceTests.GracefulFixtureNames.html +87 -0
  33. data/doc/fitnesse/FitNesse.RubY.AcceptanceTests.GracefulMemberNames.html +73 -0
  34. data/doc/fitnesse/FitNesse.RubY.AcceptanceTests.ImportFixture.html +61 -0
  35. data/doc/fitnesse/FitNesse.RubY.AcceptanceTests.WaysToSpecifyaFixtureNamespace.html +81 -0
  36. data/doc/spec/annotation.html +3833 -0
  37. data/doc/spec/extensions.html +302 -0
  38. data/doc/spec/fixtures.html +5181 -0
  39. data/doc/spec/index.html +947 -0
  40. data/doc/spec/parse.html +3094 -0
  41. data/lib/eg/all_combinations.rb +44 -0
  42. data/lib/eg/all_files.rb +94 -0
  43. data/lib/eg/all_pairs.rb +172 -0
  44. data/lib/eg/arithmetic_column_fixture.rb +35 -0
  45. data/lib/eg/arithmetic_fixture.rb +29 -0
  46. data/lib/eg/binary_chop.rb +100 -0
  47. data/lib/eg/calculator.rb +69 -0
  48. data/lib/eg/column_index.rb +85 -0
  49. data/lib/eg/division.rb +13 -0
  50. data/lib/eg/echo_args_fixture.rb +9 -0
  51. data/lib/eg/example_tests.rb +84 -0
  52. data/lib/eg/music/Music.txt +38 -0
  53. data/lib/eg/music/browser.rb +60 -0
  54. data/lib/eg/music/display.rb +24 -0
  55. data/lib/eg/music/music.rb +67 -0
  56. data/lib/eg/music/music_library.rb +70 -0
  57. data/lib/eg/music/music_player.rb +77 -0
  58. data/lib/eg/music/realtime.rb +39 -0
  59. data/lib/eg/music/simulator.rb +81 -0
  60. data/lib/eg/nested/bob.rb +12 -0
  61. data/lib/eg/nested/bob_the_builder_fixture.rb +11 -0
  62. data/lib/eg/net/simulator.rb +69 -0
  63. data/lib/eg/page.rb +91 -0
  64. data/lib/eg/sqrt.rb +19 -0
  65. data/lib/fat/annotation_fixture.rb +83 -0
  66. data/lib/fat/color.rb +45 -0
  67. data/lib/fat/divide.rb +13 -0
  68. data/lib/fat/document_parse_fixture.rb +67 -0
  69. data/lib/fat/equals.rb +59 -0
  70. data/lib/fat/fixture_name_fixture.rb +67 -0
  71. data/lib/fat/html_to_text_fixture.rb +20 -0
  72. data/lib/fat/money.rb +18 -0
  73. data/lib/fat/output_fixture.rb +32 -0
  74. data/lib/fat/parse_fixture.rb +92 -0
  75. data/lib/fat/reference_fixture.rb +31 -0
  76. data/lib/fat/standard_annotation_fixture.rb +58 -0
  77. data/lib/fat/string_writer.rb +12 -0
  78. data/lib/fat/table.rb +23 -0
  79. data/lib/fat/table_parse_fixture.rb +33 -0
  80. data/lib/fat/text_to_html_fixture.rb +21 -0
  81. data/lib/fit/action_fixture.rb +65 -0
  82. data/lib/fit/column_fixture.rb +104 -0
  83. data/lib/fit/file_runner.rb +80 -0
  84. data/lib/fit/fit_protocol.rb +62 -0
  85. data/lib/fit/fit_server.rb +173 -0
  86. data/lib/fit/fixture.rb +309 -0
  87. data/lib/fit/fixture_loader.rb +75 -0
  88. data/lib/fit/import_fixture.rb +9 -0
  89. data/lib/fit/parse.rb +206 -0
  90. data/lib/fit/primitive_fixture.rb +52 -0
  91. data/lib/fit/row_fixture.rb +188 -0
  92. data/lib/fit/scientific_double.rb +70 -0
  93. data/lib/fit/summary.rb +46 -0
  94. data/lib/fit/timed_action_fixture.rb +35 -0
  95. data/lib/fit/type_adapter.rb +95 -0
  96. data/lib/fit/wiki_runner.rb +15 -0
  97. data/lib/fittask.rb +184 -0
  98. data/test/all_tests.rb +13 -0
  99. data/test/file_runner_test.rb +52 -0
  100. data/test/fit_server_test.rb +214 -0
  101. data/test/fixture_loader_test.rb +71 -0
  102. data/test/fixture_test.rb +41 -0
  103. data/test/fixtures/fail_fixture.rb +9 -0
  104. data/test/fixtures/pass_fixture.rb +9 -0
  105. data/test/framework_test.rb +51 -0
  106. data/test/parse_test.rb +101 -0
  107. data/test/row_fixture_test.rb +44 -0
  108. data/test/scientific_double_test.rb +35 -0
  109. data/test/type_adapter_test.rb +120 -0
  110. metadata +165 -0
@@ -0,0 +1,44 @@
1
+ # Copyright (c) 2002 Cunningham & Cunningham, Inc.
2
+ # Released under the terms of the GNU General Public License version 2 or later.
3
+
4
+ require 'eg/all_files'
5
+
6
+ module Eg
7
+
8
+ class AllCombinations < AllFiles
9
+ def initialize
10
+ super
11
+ @lists = []
12
+ @case_number = 1
13
+ end
14
+ def do_table table
15
+ @row = table.parts.last
16
+ super
17
+ combinations
18
+ end
19
+ protected
20
+ def do_row_files row, files
21
+ @lists << files
22
+ end
23
+ def combinations index = 0, combination = @lists
24
+ if index == @lists.size
25
+ do_case combination
26
+ else
27
+ files = @lists[index]
28
+ files.each do |f|
29
+ comb = combination.dup
30
+ comb[index] = f
31
+ combinations(index + 1, comb)
32
+ end
33
+ end
34
+ end
35
+ def do_case combination
36
+ number = tr(td('#' + @case_number.to_s, nil), nil)
37
+ @case_number += 1
38
+ number.leaf.add_to_tag 'colspan="2"'
39
+ @row.last.more = number
40
+ do_files number, combination
41
+ end
42
+ end
43
+
44
+ end
@@ -0,0 +1,94 @@
1
+ # Copyright (c) 2002 Cunningham & Cunningham, Inc.
2
+ # Released under the terms of the GNU General Public License version 2 or later.
3
+
4
+ require 'fit/column_fixture'
5
+ require 'fit/fixture'
6
+
7
+ module Eg
8
+
9
+ class AllFiles < Fit::Fixture
10
+ @@file_stack = []
11
+ def do_row row
12
+ cell = row.leaf
13
+ files = expand cell.text
14
+ if files.size > 0
15
+ do_row_files row, files
16
+ else
17
+ ignore cell
18
+ cell.add_to_body Fit::Fixture.gray('no match')
19
+ end
20
+ end
21
+ def expand pattern; Dir[pattern]; end
22
+ protected
23
+ def do_row_files row, files; do_files row, files; end
24
+ def do_files row, files
25
+ files.each do |filename|
26
+ cells = td(File.basename(filename), td('', nil))
27
+ row = (row.more = tr(cells, row.more))
28
+ fixture = Fit::Fixture.new
29
+ run(filename, fixture, cells)
30
+ summarize(fixture, filename)
31
+ end
32
+ end
33
+ def run filename, fixture, cells
34
+ if push_and_check(filename)
35
+ ignore cells
36
+ cells.add_to_body Fit::Fixture.gray('recursive')
37
+ return
38
+ end
39
+ begin
40
+ input = File.open(filename) {|f| f.read}
41
+ if input.index('<wiki>')
42
+ tables = Fit::Parse.new(input, ['wiki', 'table', 'tr', 'td'])
43
+ fixture.do_tables tables.parts
44
+ else
45
+ tables = Fit::Parse.new(input, ['table', 'tr', 'td'])
46
+ fixture.do_tables tables
47
+ end
48
+ cells.more.add_to_body Fit::Fixture.gray(fixture.totals)
49
+ if fixture.total_errors.zero?
50
+ right cells.more
51
+ else
52
+ wrong cells.more
53
+ cells.more.add_to_body tables.footnote
54
+ end
55
+ rescue Exception => e
56
+ exception cells, e
57
+ end
58
+ pop filename
59
+ end
60
+ def push_and_check filename
61
+ return true if @@file_stack.member? filename
62
+ @@file_stack << filename
63
+ false
64
+ end
65
+ def pop filename; @@file_stack.delete filename; end
66
+ def tr cells, more
67
+ Fit::ParseHolder.create('tr', nil, cells, more)
68
+ end
69
+ def td text, more
70
+ Fit::ParseHolder.create('td', Fit::Fixture.gray(text), nil, more)
71
+ end
72
+ private
73
+ def summarize fixture, filename
74
+ fixture.summary['input file'] = filename
75
+ fixture.summary['input update'] = File.open(filename) {|f| f.mtime.to_s}
76
+ run_totals = @summary.include?('counts run') ? @summary['counts run'] : Fit::Counts.new
77
+ run_totals.tally fixture.counts
78
+ @summary['counts run'] = run_totals
79
+ end
80
+ # Self test.
81
+ class Expand < Fit::ColumnFixture
82
+ attr_accessor :path
83
+ def initialize
84
+ super
85
+ @fixture = AllFiles.new
86
+ end
87
+ def expansion
88
+ files = @fixture.expand @path
89
+ files.sort.collect {|filename| File.basename(filename)}
90
+ end
91
+ end
92
+ end
93
+
94
+ end
@@ -0,0 +1,172 @@
1
+ # Copyright (c) 2002 Cunningham & Cunningham, Inc.
2
+ # Released under the terms of the GNU General Public License version 2 or later.
3
+
4
+ require 'eg/all_combinations'
5
+ require 'set'
6
+
7
+ module Eg
8
+
9
+ class AllPairs < AllCombinations
10
+
11
+ attr_accessor :steps, :to_item, :vars, :pairs
12
+ @@rank = 0
13
+ def AllPairs.rank; @@rank; end
14
+
15
+ def initialize
16
+ super
17
+ @steps = 0
18
+ @to_item = {}
19
+ @vars = []
20
+ @pairs = Set.new
21
+ end
22
+
23
+ protected
24
+
25
+ def combinations
26
+ populate
27
+ generate
28
+ end
29
+
30
+ # Populate
31
+
32
+ def populate
33
+ do_all_vars
34
+ do_all_var_pairs
35
+ end
36
+
37
+ def do_all_vars
38
+ @@rank = 0
39
+ @lists.each_with_index do |files, i|
40
+ var = Var.new i, files
41
+ @vars << var
42
+ do_all_items var, files
43
+ end
44
+ end
45
+
46
+ def do_all_items var, files
47
+ files.each_with_index do |file, i|
48
+ item = Item.new var, i, @@rank
49
+ @@rank += 1
50
+ @to_item[file] = item
51
+ var.items << item
52
+ end
53
+ end
54
+
55
+ def do_all_var_pairs
56
+ @vars.each_with_index do |var, i|
57
+ j = i + 1
58
+ while j < @vars.size
59
+ do_all_item_pairs @vars[i], @vars[j]
60
+ j += 1
61
+ end
62
+ end
63
+ end
64
+
65
+ def do_all_item_pairs vl, vr
66
+ vl.items.each do |var_left|
67
+ vr.items.each do |var_right|
68
+ @pairs << Pair.new(var_left, var_right)
69
+ end
70
+ end
71
+ end
72
+
73
+ # Generate
74
+
75
+ def generate
76
+ while @pairs.sort.first.used.zero?
77
+ emit next_case
78
+ end
79
+ end
80
+
81
+ def next_case
82
+ slug = [nil] * @vars.size
83
+ while not is_full?(slug)
84
+ p = next_fit slug
85
+ fill slug, p
86
+ end
87
+ slug
88
+ end
89
+ private :next_case
90
+
91
+ def fill slug, pair
92
+ slug[pair.left.var.index] = pair.left
93
+ slug[pair.right.var.index] = pair.right
94
+ pair.used += 1
95
+ @pairs << pair
96
+ end
97
+
98
+ def is_full? slug
99
+ slug.each {|s| return false if s.nil?}
100
+ true
101
+ end
102
+
103
+ def next_fit slug
104
+ hold = []
105
+ pair = next_pair
106
+ while not pair.is_fit?(slug)
107
+ hold << pair
108
+ pair = next_pair
109
+ end
110
+ @pairs += hold
111
+ pair
112
+ end
113
+
114
+ def next_pair
115
+ first = @pairs.sort.first
116
+ @pairs.delete first
117
+ @steps += 1
118
+ first
119
+ end
120
+
121
+ def emit slug
122
+ combination = []
123
+ slug.each {|s| combination << s.file}
124
+ do_case combination
125
+ end
126
+
127
+ # Helper classes
128
+
129
+ class Var
130
+ attr_accessor :files, :items
131
+ attr_accessor :index
132
+ def initialize index, files
133
+ @index, @files = index, files
134
+ @items = []
135
+ end
136
+ end
137
+
138
+ class Item
139
+ attr_accessor :var
140
+ attr_accessor :index, :rank
141
+ def initialize v, i, n
142
+ @var, @index, @rank = v, i, n
143
+ end
144
+ def file; var.files[@index]; end
145
+ def is_fit? slug
146
+ slug[var.index].nil? or slug[var.index] == self
147
+ end
148
+ end
149
+
150
+ class Pair
151
+ attr_accessor :left, :right
152
+ attr_accessor :used
153
+ def initialize left, right
154
+ @left, @right = left, right
155
+ @used = 0
156
+ end
157
+ def is_fit? slug
158
+ @left.is_fit?(slug) and @right.is_fit?(slug)
159
+ end
160
+ def rank
161
+ AllPairs.rank * (AllPairs.rank * @used + @left.rank) + @right.rank
162
+ end
163
+ def <=> obj
164
+ rank - obj.rank
165
+ end
166
+ end
167
+
168
+ # No self test classes.
169
+
170
+ end
171
+
172
+ end
@@ -0,0 +1,35 @@
1
+ # Copyright (c) 2002 Cunningham & Cunningham, Inc.
2
+ # Released under the terms of the GNU General Public License version 2 or later.
3
+
4
+ require 'fit/column_fixture'
5
+ require 'fit/scientific_double'
6
+
7
+ module Eg
8
+
9
+ class ArithmeticColumnFixture < Fit::ColumnFixture
10
+ attr_accessor :x, :y
11
+ @@metadata = { 'sin()' => Fit::ScientificDouble, 'cos()' => Fit::ScientificDouble }
12
+ def plus
13
+ x + y
14
+ end
15
+ def minus
16
+ x - y
17
+ end
18
+ def times
19
+ x * y
20
+ end
21
+ def divide
22
+ x / y
23
+ end
24
+ def floating
25
+ Float(x) / Float(y)
26
+ end
27
+ def sin
28
+ Fit::ScientificDouble.new Math.sin(x / 180.0 * Math::PI)
29
+ end
30
+ def cos
31
+ Fit::ScientificDouble.new Math.cos(x / 180.0 * Math::PI)
32
+ end
33
+ end
34
+
35
+ end
@@ -0,0 +1,29 @@
1
+ # Copyright (c) 2002 Cunningham & Cunningham, Inc.
2
+ # Released under the terms of the GNU General Public License version 2 or later.
3
+
4
+ require 'fit/primitive_fixture'
5
+
6
+ module Eg
7
+
8
+ class ArithmeticFixture < Fit::PrimitiveFixture
9
+ def initialize
10
+ super
11
+ @x = @y = 0
12
+ end
13
+ def do_rows rows
14
+ super(rows.more) # skip column heads
15
+ end
16
+ def do_cell cell, column_index
17
+ case column_index
18
+ when 0 then @x = parse_integer(cell);
19
+ when 1 then @y = parse_integer(cell);
20
+ when 2 then check(cell, parse_integer(cell), @x + @y)
21
+ when 3 then check(cell, parse_integer(cell), @x - @y)
22
+ when 4 then check(cell, parse_integer(cell), @x * @y)
23
+ when 5 then check(cell, parse_integer(cell), @x / @y)
24
+ else ignore(cell)
25
+ end
26
+ end
27
+ end
28
+
29
+ end
@@ -0,0 +1,100 @@
1
+ # Copyright (c) 2002 Cunningham & Cunningham, Inc.
2
+ # Released under the terms of the GNU General Public License version 2 or later.
3
+
4
+ require 'fit/column_fixture'
5
+
6
+ module Eg
7
+
8
+ class BinaryChop < Fit::ColumnFixture
9
+
10
+ attr_accessor :key
11
+
12
+ def execute
13
+ @array = [] if @array.nil?
14
+ end
15
+
16
+ def array= value
17
+ unless value.kind_of? Array
18
+ @array = [value]
19
+ else
20
+ @array = value
21
+ end
22
+ end
23
+ def array; @array; end
24
+
25
+ def result
26
+ chop_friday key, array
27
+ end
28
+
29
+ def mon; chop_monday(key, array); end
30
+ def tue; chop_tuesday(key, array); end
31
+ def wed; chop_wednesday(key, array); end
32
+ def thr; chop_thursday(key, array); end
33
+ def fri; chop_friday(key, array); end
34
+
35
+ # Search methods
36
+
37
+ def chop_monday key, array
38
+ min = 0
39
+ max = array.size - 1
40
+ while min <= max
41
+ probe = (min + max) / 2
42
+ if key == array[probe]
43
+ return probe
44
+ elsif key > array[probe]
45
+ min = probe + 1
46
+ else
47
+ max = probe - 1
48
+ end
49
+ end
50
+ -1
51
+ end
52
+
53
+ def chop_tuesday key, array
54
+ min = 0
55
+ max = array.size - 1
56
+ while min <= max
57
+ probe = (min + max) / 2
58
+ case key <=> array[probe]
59
+ when 0 then return probe
60
+ when 1 then min = probe + 1
61
+ when -1 then max = probe - 1
62
+ else raise "Unexpected result from <=>"
63
+ end
64
+ end
65
+ -1
66
+ end
67
+
68
+ def chop_wednesday key, array
69
+ return -1 if array.size.zero?
70
+ probe = array.size / 2
71
+ return probe if key == array[probe]
72
+ return chop_wednesday(key, array[0, probe]) if key < array[probe]
73
+ result = chop_wednesday(key, array[(probe + 1)..-1])
74
+ return (result < 0) ? result : result + probe + 1
75
+ end
76
+
77
+ def chop_thursday key, array
78
+ min = 0
79
+ max = array.size - 1
80
+ while min <= max
81
+ probe = (rand * (max - min) + min).to_i
82
+ if key == array[probe]
83
+ return probe
84
+ elsif key > array[probe]
85
+ min = probe + 1
86
+ else
87
+ max = probe - 1
88
+ end
89
+ end
90
+ -1
91
+ end
92
+
93
+ def chop_friday key, array
94
+ array.each_with_index {|e, i| return i if key == e}
95
+ -1
96
+ end
97
+
98
+ end
99
+
100
+ end
@@ -0,0 +1,69 @@
1
+ # Copyright (c) 2002 Cunningham & Cunningham, Inc.
2
+ # Released under the terms of the GNU General Public License version 2 or later.
3
+
4
+ require 'fit/column_fixture'
5
+ require 'fit/scientific_double'
6
+
7
+ module Eg
8
+
9
+ class Hp35
10
+ attr_reader :r
11
+ def initialize
12
+ @r = [0, 0, 0, 0]
13
+ @s = 0
14
+ end
15
+ def key key
16
+ if key.kind_of? Numeric
17
+ push key.to_f
18
+ else
19
+ case key
20
+ when 'enter' then push
21
+ when '+' then push(pop() + pop())
22
+ when '-' then n = pop(); push(pop() - n)
23
+ when '*' then push(pop() * pop())
24
+ when '/' then n = pop(); push(pop() / n)
25
+ when 'x^y' then push(pop() ** pop())
26
+ when 'clx' then @r[0] = 0
27
+ when 'clr' then @r[0] = @r[1] = @r[2] = @r[3] = 0
28
+ when 'chs' then @r[0] = -@r[0]
29
+ when 'x<>y' then @r[0], @r[1] = @r[1], @r[0]
30
+ when 'r!' then @r[3] = pop()
31
+ when 'sto' then @s = @r[0]
32
+ when 'rcl' then push(@s)
33
+ when 'sqrt' then push(Math.sqrt(pop()))
34
+ when 'ln' then push(Math.log(pop()))
35
+ when 'sin' then push(Math.sin(pop() / 180 * Math::PI))
36
+ when 'cos' then push(Math.cos(pop() / 180 * Math::PI))
37
+ when 'tan' then push(Math.tan(pop() / 180 * Math::PI))
38
+ else raise "Can't do key: #{key}"
39
+ end
40
+ end
41
+ end
42
+ def push value = nil
43
+ 3.downto(1) {|i| @r[i] = @r[i - 1]}
44
+ @r[0] = value unless value.nil?
45
+ end
46
+ def pop
47
+ result = @r[0]
48
+ 0.upto(2) {|i| @r[i] = @r[i + 1]}
49
+ result
50
+ end
51
+ end
52
+
53
+ class Calculator < Fit::ColumnFixture
54
+ attr_accessor :volts, :key
55
+ @@metadata = { 'x()' => Fit::ScientificDouble, 'y()' => Fit::ScientificDouble,
56
+ 'z()' => Fit::ScientificDouble, 't()' => Fit::ScientificDouble }
57
+ @@hp = Hp35.new
58
+ def points; false; end
59
+ def flash; false; end
60
+ def watts; 0.5; end
61
+ def reset; key = nil; end
62
+ def execute; @@hp.key(key) unless key.nil?; end
63
+ def x; Fit::ScientificDouble.new @@hp.r[0]; end
64
+ def y; Fit::ScientificDouble.new @@hp.r[1]; end
65
+ def z; Fit::ScientificDouble.new @@hp.r[2]; end
66
+ def t; Fit::ScientificDouble.new @@hp.r[3]; end
67
+ end
68
+
69
+ end
@@ -0,0 +1,85 @@
1
+ # Copyright (c) 2002 Cunningham & Cunningham, Inc.
2
+ # Released under the terms of the GNU General Public License version 2 or later.
3
+
4
+ require 'fit/row_fixture'
5
+ require 'set'
6
+
7
+ module Eg
8
+
9
+ class ColumnIndex < Fit::RowFixture
10
+
11
+ def do_rows rows
12
+ @rows = rows
13
+ super
14
+ end
15
+
16
+ def query
17
+ # first find what classes are mentioned in the table...
18
+ names = Set.new
19
+ column_index = 0
20
+ cell = @rows.parts
21
+ until cell.nil?
22
+ break if cell.text == 'className'
23
+ column_index += 1
24
+ cell = cell.more
25
+ end
26
+ row = @rows.more
27
+ until row.nil?
28
+ names.add row.at(0, column_index).text
29
+ row = row.more
30
+ end
31
+ # ...then find the columns in these classes
32
+ columns = []
33
+ names.each do |name|
34
+ obj = Fit::FixtureLoader.new.find_class(name).new
35
+ attributes = obj.methods - Object.new.methods
36
+ setters = attributes.dup.delete_if {|a| a[-1..-1] != "="}
37
+ attributes -= setters
38
+ setters.each do |s|
39
+ getter = s[0..-2]
40
+ if attributes.include? getter
41
+ attributes.delete getter
42
+ columns << Column.create(obj, getter)
43
+ end
44
+ end
45
+ attributes.each do |m|
46
+ meth = obj.method(m.to_sym)
47
+ columns << Column.create(obj, "#{m}()") if meth.arity.zero?
48
+ end
49
+ end
50
+ columns
51
+ end
52
+
53
+ def get_target_class; Column; end
54
+
55
+ def parse string, klass
56
+ return parse_class(string) if klass == Class
57
+ super
58
+ end
59
+
60
+ def parse_class name
61
+ Fit::FixtureLoader.new.find_class(name)
62
+ end
63
+
64
+ # Helper class
65
+
66
+ class Column
67
+ attr_accessor :column, :class_name, :column_name, :column_type
68
+ @@metadata = { 'column_name' => String, 'column_type' => Class, 'column' => Object, 'class_name' => Class }
69
+ def Column.metadata; @@metadata; end
70
+ def Column.create obj, attribute
71
+ c = new
72
+ c.column = attribute
73
+ c.class_name = obj.class
74
+ column_name = attribute.to_s
75
+ column_name_parts = column_name.split(/_/)
76
+ c.column_name = column_name_parts.shift
77
+ column_name_parts.each {|name| c.column_name += name.capitalize}
78
+ c.column_type = obj.class.metadata[column_name]
79
+ c
80
+ end
81
+ end
82
+
83
+ end
84
+
85
+ end
@@ -0,0 +1,13 @@
1
+ # Copyright (c) 2002 Cunningham & Cunningham, Inc.
2
+ # Released under the terms of the GNU General Public License version 2 or later.
3
+
4
+ require 'fit/column_fixture'
5
+
6
+ module Eg
7
+
8
+ class Division < Fit::ColumnFixture
9
+ attr_accessor :numerator, :denominator
10
+ def quotient; @numerator.to_f / @denominator.to_f; end
11
+ end
12
+
13
+ end
@@ -0,0 +1,9 @@
1
+ require 'fit/row_fixture'
2
+
3
+ module Eg
4
+ class EchoArgsFixture < Fit::RowFixture
5
+ def query
6
+ @args
7
+ end
8
+ end
9
+ end