cuke_modeler 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.simplecov +8 -0
  4. data/Gemfile +4 -0
  5. data/History.rdoc +3 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +73 -0
  8. data/Rakefile +38 -0
  9. data/cuke_modeler.gemspec +29 -0
  10. data/features/analysis/test_comparison.feature +123 -0
  11. data/features/analysis/test_manipulation.feature +37 -0
  12. data/features/modeling/background_modeling.feature +75 -0
  13. data/features/modeling/background_output.feature +130 -0
  14. data/features/modeling/directory_modeling.feature +120 -0
  15. data/features/modeling/directory_output.feature +13 -0
  16. data/features/modeling/doc_string_modeling.feature +63 -0
  17. data/features/modeling/doc_string_output.feature +71 -0
  18. data/features/modeling/example_modeling.feature +111 -0
  19. data/features/modeling/example_output.feature +192 -0
  20. data/features/modeling/feature_file_modeling.feature +64 -0
  21. data/features/modeling/feature_file_output.feature +13 -0
  22. data/features/modeling/feature_modeling.feature +164 -0
  23. data/features/modeling/feature_output.feature +244 -0
  24. data/features/modeling/outline_modeling.feature +100 -0
  25. data/features/modeling/outline_output.feature +197 -0
  26. data/features/modeling/row_modeling.feature +77 -0
  27. data/features/modeling/row_output.feature +27 -0
  28. data/features/modeling/scenario_modeling.feature +89 -0
  29. data/features/modeling/scenario_output.feature +147 -0
  30. data/features/modeling/step_modeling.feature +85 -0
  31. data/features/modeling/step_output.feature +52 -0
  32. data/features/modeling/table_modeling.feature +52 -0
  33. data/features/modeling/table_output.feature +42 -0
  34. data/features/modeling/table_row_modeling.feature +67 -0
  35. data/features/modeling/table_row_output.feature +27 -0
  36. data/features/modeling/tag_modeling.feature +58 -0
  37. data/features/modeling/tag_output.feature +16 -0
  38. data/features/step_definitions/action_steps.rb +3 -0
  39. data/features/step_definitions/background_steps.rb +81 -0
  40. data/features/step_definitions/directory_steps.rb +52 -0
  41. data/features/step_definitions/doc_string_steps.rb +63 -0
  42. data/features/step_definitions/feature_file_steps.rb +41 -0
  43. data/features/step_definitions/feature_steps.rb +96 -0
  44. data/features/step_definitions/outline_steps.rb +252 -0
  45. data/features/step_definitions/setup_steps.rb +50 -0
  46. data/features/step_definitions/spec_steps.rb +18 -0
  47. data/features/step_definitions/step_steps.rb +159 -0
  48. data/features/step_definitions/table_steps.rb +54 -0
  49. data/features/step_definitions/tag_steps.rb +61 -0
  50. data/features/step_definitions/test_steps.rb +114 -0
  51. data/features/step_definitions/verification_steps.rb +9 -0
  52. data/features/support/env.rb +27 -0
  53. data/features/support/transforms.rb +3 -0
  54. data/lib/cuke_modeler.rb +29 -0
  55. data/lib/cuke_modeler/background.rb +38 -0
  56. data/lib/cuke_modeler/containing.rb +18 -0
  57. data/lib/cuke_modeler/directory.rb +86 -0
  58. data/lib/cuke_modeler/doc_string.rb +87 -0
  59. data/lib/cuke_modeler/example.rb +184 -0
  60. data/lib/cuke_modeler/feature.rb +147 -0
  61. data/lib/cuke_modeler/feature_element.rb +73 -0
  62. data/lib/cuke_modeler/feature_file.rb +77 -0
  63. data/lib/cuke_modeler/nested.rb +34 -0
  64. data/lib/cuke_modeler/outline.rb +68 -0
  65. data/lib/cuke_modeler/parsing.rb +32 -0
  66. data/lib/cuke_modeler/raw.rb +20 -0
  67. data/lib/cuke_modeler/row.rb +64 -0
  68. data/lib/cuke_modeler/scenario.rb +45 -0
  69. data/lib/cuke_modeler/sourceable.rb +20 -0
  70. data/lib/cuke_modeler/step.rb +214 -0
  71. data/lib/cuke_modeler/table.rb +90 -0
  72. data/lib/cuke_modeler/table_row.rb +64 -0
  73. data/lib/cuke_modeler/tag.rb +62 -0
  74. data/lib/cuke_modeler/taggable.rb +54 -0
  75. data/lib/cuke_modeler/test_element.rb +77 -0
  76. data/lib/cuke_modeler/version.rb +3 -0
  77. data/lib/cuke_modeler/world.rb +113 -0
  78. data/spec/integration/background_integration_spec.rb +72 -0
  79. data/spec/integration/directory_integration_spec.rb +48 -0
  80. data/spec/integration/doc_string_integration_spec.rb +66 -0
  81. data/spec/integration/example_integration_spec.rb +94 -0
  82. data/spec/integration/feature_file_integration_spec.rb +44 -0
  83. data/spec/integration/feature_integration_spec.rb +152 -0
  84. data/spec/integration/outline_integration_spec.rb +92 -0
  85. data/spec/integration/scenario_integration_spec.rb +80 -0
  86. data/spec/integration/step_integration_spec.rb +184 -0
  87. data/spec/integration/table_integration_spec.rb +86 -0
  88. data/spec/integration/table_row_integration_spec.rb +68 -0
  89. data/spec/integration/tag_integration_spec.rb +67 -0
  90. data/spec/integration/world_integration_spec.rb +13 -0
  91. data/spec/spec_helper.rb +30 -0
  92. data/spec/unit/background_unit_spec.rb +55 -0
  93. data/spec/unit/bare_bones_unit_specs.rb +13 -0
  94. data/spec/unit/containing_element_unit_specs.rb +17 -0
  95. data/spec/unit/directory_unit_spec.rb +103 -0
  96. data/spec/unit/doc_string_unit_spec.rb +109 -0
  97. data/spec/unit/example_unit_spec.rb +251 -0
  98. data/spec/unit/feature_element_unit_spec.rb +19 -0
  99. data/spec/unit/feature_element_unit_specs.rb +46 -0
  100. data/spec/unit/feature_file_unit_spec.rb +94 -0
  101. data/spec/unit/feature_unit_spec.rb +135 -0
  102. data/spec/unit/nested_element_unit_specs.rb +36 -0
  103. data/spec/unit/nested_unit_spec.rb +37 -0
  104. data/spec/unit/outline_unit_spec.rb +91 -0
  105. data/spec/unit/parsing_unit_spec.rb +21 -0
  106. data/spec/unit/prepopulated_unit_specs.rb +13 -0
  107. data/spec/unit/raw_element_unit_specs.rb +24 -0
  108. data/spec/unit/raw_unit_spec.rb +25 -0
  109. data/spec/unit/row_unit_spec.rb +55 -0
  110. data/spec/unit/scenario_unit_spec.rb +71 -0
  111. data/spec/unit/sourceable_unit_spec.rb +17 -0
  112. data/spec/unit/sourced_element_unit_specs.rb +18 -0
  113. data/spec/unit/step_unit_spec.rb +259 -0
  114. data/spec/unit/table_row_unit_spec.rb +55 -0
  115. data/spec/unit/table_unit_spec.rb +96 -0
  116. data/spec/unit/tag_unit_spec.rb +51 -0
  117. data/spec/unit/taggable_unit_spec.rb +78 -0
  118. data/spec/unit/tagged_element_unit_specs.rb +63 -0
  119. data/spec/unit/test_element_unit_spec.rb +40 -0
  120. data/spec/unit/test_element_unit_specs.rb +31 -0
  121. data/spec/unit/world_unit_spec.rb +130 -0
  122. metadata +364 -0
@@ -0,0 +1,77 @@
1
+ module CukeModeler
2
+
3
+ # A class modeling a Cucumber .feature file.
4
+
5
+ class FeatureFile
6
+
7
+ include Containing
8
+ include Nested
9
+
10
+
11
+ # The Feature objects contained by the FeatureFile
12
+ attr_accessor :features
13
+
14
+
15
+ # Creates a new FeatureFile object and, if *file_parsed* is provided,
16
+ # populates the object.
17
+ def initialize(file = nil)
18
+ @file = file
19
+ @features = []
20
+
21
+ if file
22
+ raise(ArgumentError, "Unknown file: #{file.inspect}") unless File.exists?(file)
23
+
24
+ parsed_file = parse_file(file)
25
+
26
+ build_file(parsed_file)
27
+ end
28
+ end
29
+
30
+ # Returns the name of the file.
31
+ def name
32
+ File.basename(@file.gsub('\\', '/'))
33
+ end
34
+
35
+ # Returns the path of the file.
36
+ def path
37
+ @file
38
+ end
39
+
40
+ # Returns the immediate child elements of the file(i.e. its Feature object).
41
+ def contains
42
+ @features
43
+ end
44
+
45
+ # Returns the number of features contained in the file.
46
+ def feature_count
47
+ @features.count
48
+ end
49
+
50
+ # Returns the Feature object contained by the FeatureFile.
51
+ def feature
52
+ @features.first
53
+ end
54
+
55
+ # Returns the path of the feature file.
56
+ def to_s
57
+ path.to_s
58
+ end
59
+
60
+
61
+ private
62
+
63
+
64
+ def parse_file(file_to_parse)
65
+ source_text = IO.read(file_to_parse)
66
+
67
+ Parsing::parse_text(source_text)
68
+ end
69
+
70
+ def build_file(parsed_file)
71
+ unless parsed_file.empty?
72
+ @features << build_child_element(Feature, parsed_file.first)
73
+ end
74
+ end
75
+
76
+ end
77
+ end
@@ -0,0 +1,34 @@
1
+ module CukeModeler
2
+
3
+ # A mix-in module containing methods used by elements that are nested inside
4
+ # of other elements.
5
+
6
+ module Nested
7
+
8
+ # The parent object that contains *self*
9
+ attr_accessor :parent_element
10
+
11
+
12
+ # Returns the ancestor of *self* that matches the given type.
13
+ def get_ancestor(ancestor_type)
14
+ ancestor = self.parent_element
15
+ target_type = {:directory => Directory,
16
+ :feature_file => FeatureFile,
17
+ :feature => Feature,
18
+ :test => TestElement,
19
+ :step => Step,
20
+ :table => Table,
21
+ :example => Example
22
+ }[ancestor_type]
23
+
24
+ raise(ArgumentError, "Unknown ancestor type '#{ancestor_type}'.") if target_type.nil?
25
+
26
+ until ancestor.is_a?(target_type) || ancestor.nil?
27
+ ancestor = ancestor.parent_element
28
+ end
29
+
30
+ ancestor
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,68 @@
1
+ module CukeModeler
2
+
3
+ # A class modeling a Cucumber Scenario Outline.
4
+
5
+ class Outline < TestElement
6
+
7
+ include Taggable
8
+
9
+
10
+ # The Example objects contained by the Outline
11
+ attr_accessor :examples
12
+
13
+
14
+ # Creates a new Outline object and, if *source* is provided, populates the
15
+ # object.
16
+ def initialize(source = nil)
17
+ parsed_outline = process_source(source)
18
+
19
+ super(parsed_outline)
20
+
21
+ @tags = []
22
+ @tag_elements = []
23
+ @examples = []
24
+
25
+ build_outline(parsed_outline) if parsed_outline
26
+ end
27
+
28
+ # Returns the immediate child elements of the outline (i.e. its Example
29
+ # objects.
30
+ def contains
31
+ @examples + @steps
32
+ end
33
+
34
+ # Returns a gherkin representation of the outline.
35
+ def to_s
36
+ text = ''
37
+
38
+ text << tag_output_string + "\n" unless tags.empty?
39
+ text << "Scenario Outline:#{name_output_string}"
40
+ text << "\n" + description_output_string unless description_text.empty?
41
+ text << "\n" unless steps.empty? || description_text.empty?
42
+ text << "\n" + steps_output_string unless steps.empty?
43
+ text << "\n\n" + examples_output_string unless examples.empty?
44
+
45
+ text
46
+ end
47
+
48
+
49
+ private
50
+
51
+
52
+ def build_outline(parsed_outline)
53
+ populate_element_tags(parsed_outline)
54
+ populate_outline_examples(parsed_outline['examples']) if parsed_outline['examples']
55
+ end
56
+
57
+ def populate_outline_examples(parsed_examples)
58
+ parsed_examples.each do |example|
59
+ @examples << build_child_element(Example, example)
60
+ end
61
+ end
62
+
63
+ def examples_output_string
64
+ examples.empty? ? '' : examples.collect { |example| example.to_s }.join("\n\n")
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,32 @@
1
+ require 'stringio'
2
+ require 'gherkin/formatter/json_formatter'
3
+ require 'gherkin'
4
+ require 'json'
5
+ require 'multi_json'
6
+
7
+ module CukeModeler
8
+
9
+ # A module providing source text parsing functionality.
10
+
11
+ module Parsing
12
+
13
+ class << self
14
+
15
+ # Parses the Cucumber feature given in *source_text* and returns an array
16
+ # containing the hash representation of its logical structure.
17
+ def parse_text(source_text)
18
+ raise(ArgumentError, "Cannot parse #{source_text.class} objects. Strings only.") unless source_text.is_a?(String)
19
+
20
+ io = StringIO.new
21
+ formatter = Gherkin::Formatter::JSONFormatter.new(io)
22
+ parser = Gherkin::Parser::Parser.new(formatter)
23
+ parser.parse(source_text, 'fake_file.txt', 0)
24
+ formatter.done
25
+
26
+ MultiJson.load(io.string)
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,20 @@
1
+ module CukeModeler
2
+
3
+ # A mix-in module containing methods used by elements that store their
4
+ # underlying implementation
5
+
6
+ module Raw
7
+
8
+ # The raw representation of the element (i.e. the output of the gherkin gem)
9
+ attr_accessor :raw_element
10
+
11
+
12
+ private
13
+
14
+
15
+ def populate_raw_element(parsed_element)
16
+ @raw_element = parsed_element
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,64 @@
1
+ module CukeModeler
2
+
3
+ # A class modeling a Cucumber Examples table row.
4
+
5
+ class Row
6
+
7
+ include Sourceable
8
+ include Raw
9
+ include Nested
10
+
11
+
12
+ # The cells that make up the row
13
+ attr_accessor :cells
14
+
15
+
16
+ # Creates a new Row object and, if *source* is provided, populates
17
+ # the object.
18
+ def initialize(source = nil)
19
+ parsed_row = process_source(source)
20
+
21
+ @cells = []
22
+
23
+ build_row(parsed_row) if parsed_row
24
+ end
25
+
26
+ # Returns a gherkin representation of the row.
27
+ def to_s
28
+ "| #{cells.join(' | ')} |"
29
+ end
30
+
31
+
32
+ private
33
+
34
+
35
+ def process_source(source)
36
+ case
37
+ when source.is_a?(String)
38
+ parse_row(source)
39
+ else
40
+ source
41
+ end
42
+ end
43
+
44
+ def parse_row(source_text)
45
+ base_file_string = "Feature: Fake feature to parse\nScenario Outline:\n* fake step\nExamples: fake examples\n"
46
+ source_text = base_file_string + source_text
47
+
48
+ parsed_file = Parsing::parse_text(source_text)
49
+
50
+ parsed_file.first['elements'].first['examples'].first['rows'].first
51
+ end
52
+
53
+ def build_row(parsed_row)
54
+ populate_element_source_line(parsed_row)
55
+ populate_row_cells(parsed_row)
56
+ populate_raw_element(parsed_row)
57
+ end
58
+
59
+ def populate_row_cells(parsed_row)
60
+ @cells = parsed_row['cells']
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,45 @@
1
+ module CukeModeler
2
+
3
+ # A class modeling a Cucumber Scenario.
4
+
5
+ class Scenario < TestElement
6
+
7
+ include Taggable
8
+
9
+
10
+ # Creates a new Scenario object and, if *source* is provided, populates the
11
+ # object.
12
+ def initialize(source = nil)
13
+ parsed_scenario = process_source(source)
14
+
15
+ super(parsed_scenario)
16
+
17
+ @tags = []
18
+ @tag_elements = []
19
+
20
+ build_scenario(parsed_scenario) if parsed_scenario
21
+ end
22
+
23
+ # Returns gherkin representation of the scenario.
24
+ def to_s
25
+ text = ''
26
+
27
+ text << tag_output_string + "\n" unless tags.empty?
28
+ text << "Scenario:#{name_output_string}"
29
+ text << "\n" + description_output_string unless description_text.empty?
30
+ text << "\n" unless steps.empty? || description_text.empty?
31
+ text << "\n" + steps_output_string unless steps.empty?
32
+
33
+ text
34
+ end
35
+
36
+
37
+ private
38
+
39
+
40
+ def build_scenario(scenario)
41
+ populate_element_tags(scenario)
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,20 @@
1
+ module CukeModeler
2
+
3
+ # A mix-in module containing methods used by elements that know their
4
+ # source code line.
5
+
6
+ module Sourceable
7
+
8
+ # The line number where the element began in the source code
9
+ attr_reader :source_line
10
+
11
+
12
+ private
13
+
14
+
15
+ def populate_element_source_line(parsed_element)
16
+ @source_line = parsed_element['line']
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,214 @@
1
+ module CukeModeler
2
+
3
+ # A class modeling a Cucumber Feature.
4
+
5
+ class Step
6
+
7
+ include Containing
8
+ include Sourceable
9
+ include Raw
10
+ include Nested
11
+
12
+
13
+ # The step's keyword
14
+ attr_accessor :keyword
15
+
16
+ # The base text of the step
17
+ attr_accessor :base
18
+
19
+ # The step's passed block
20
+ attr_accessor :block
21
+
22
+ # The step's arguments
23
+ attr_accessor :arguments
24
+
25
+
26
+ # Creates a new Step object and, if *source* is provided, populates the
27
+ # object.
28
+ def initialize(source = nil)
29
+ @arguments = []
30
+
31
+ parsed_step = process_source(source)
32
+
33
+ build_step(parsed_step) if parsed_step
34
+ end
35
+
36
+ # Sets the delimiter that will be used by default when determining the
37
+ # boundaries of step arguments.
38
+ def delimiter=(new_delimiter)
39
+ self.left_delimiter = new_delimiter
40
+ self.right_delimiter = new_delimiter
41
+ end
42
+
43
+ # Returns the delimiter that is used to mark the beginning of a step
44
+ # argument.
45
+ def left_delimiter
46
+ @left_delimiter || World.left_delimiter
47
+ end
48
+
49
+ # Sets the left delimiter that will be used by default when determining
50
+ # step arguments.
51
+ def left_delimiter=(new_delimiter)
52
+ @left_delimiter = new_delimiter
53
+ end
54
+
55
+ # Returns the delimiter that is used to mark the end of a step
56
+ # argument.
57
+ def right_delimiter
58
+ @right_delimiter || World.right_delimiter
59
+ end
60
+
61
+ # Sets the right delimiter that will be used by default when determining
62
+ # step arguments.
63
+ def right_delimiter=(new_delimiter)
64
+ @right_delimiter = new_delimiter
65
+ end
66
+
67
+ # Returns true if the two steps have the same text, minus any keywords
68
+ # and arguments, and false otherwise.
69
+ def ==(other_step)
70
+ left_step = step_text(:with_keywords => false, :with_arguments => false)
71
+ right_step = other_step.step_text(:with_keywords => false, :with_arguments => false)
72
+
73
+ left_step == right_step
74
+ end
75
+
76
+ # Deprecated
77
+ #
78
+ # Returns the entire text of the step. Options can be set to selectively
79
+ # exclude certain portions of the text. *left_delimiter* and *right_delimiter*
80
+ # are used to determine which parts of the step are arguments.
81
+ #
82
+ # a_step = CukeModeler::Step.new("Given *some* step with a block:\n|block line 1|\n|block line 2|")
83
+ #
84
+ # a_step.step_text
85
+ # #=> ['Given *some* step with a block:', '|block line 1|', '|block line 2|']
86
+ # a_step.step_text(:with_keywords => false)
87
+ # #=> ['*some* step with a block:', '|block line 1|', '|block line 2|']
88
+ # a_step.step_text(:with_arguments => false, :left_delimiter => '*', :right_delimiter => '*')
89
+ # #=> ['Given ** step with a block:']
90
+ # a_step.step_text(:with_keywords => false, :with_arguments => false, :left_delimiter => '-', :right_delimiter => '-'))
91
+ # #=> ['*some* step with a block:']
92
+ #
93
+ def step_text(options = {})
94
+ options = {:with_keywords => true,
95
+ :with_arguments => true,
96
+ :left_delimiter => self.left_delimiter,
97
+ :right_delimiter => self.right_delimiter}.merge(options)
98
+
99
+ final_step = []
100
+ step_text = ''
101
+
102
+ step_text += "#{@keyword} " if options[:with_keywords]
103
+
104
+ if options[:with_arguments]
105
+ step_text += @base
106
+ final_step << step_text
107
+ final_step.concat(rebuild_block_text(@block)) if @block
108
+ else
109
+ step_text += stripped_step(@base, options[:left_delimiter], options[:right_delimiter])
110
+ final_step << step_text
111
+ end
112
+
113
+ final_step
114
+ end
115
+
116
+ # Populates the step's arguments based on the step's text and some method of
117
+ # determining which parts of the text are arguments. Methods include using
118
+ # a regular expression and using the step's delimiters.
119
+ def scan_arguments(*how)
120
+ if how.count == 1
121
+ pattern = how.first
122
+ else
123
+ left_delimiter = how[0] || self.left_delimiter
124
+ right_delimiter = how[1] || self.right_delimiter
125
+
126
+ return [] unless left_delimiter && right_delimiter
127
+
128
+ pattern = Regexp.new(Regexp.escape(left_delimiter) + '(.*?)' + Regexp.escape(right_delimiter))
129
+ end
130
+
131
+ @arguments = @base.scan(pattern).flatten
132
+ end
133
+
134
+ # Returns a gherkin representation of the step.
135
+ def to_s
136
+ text = "#{keyword} #{base}"
137
+ text << "\n" + block.to_s.split("\n").collect { |line| " #{line}" }.join("\n") if block
138
+
139
+ text
140
+ end
141
+
142
+
143
+ private
144
+
145
+
146
+ def process_source(source)
147
+ case
148
+ when source.is_a?(String)
149
+ parse_step(source)
150
+ else
151
+ source
152
+ end
153
+ end
154
+
155
+ def parse_step(source_text)
156
+ base_file_string = "Feature: Fake feature to parse\nScenario:\n"
157
+ source_text = base_file_string + source_text
158
+
159
+ parsed_file = Parsing::parse_text(source_text)
160
+
161
+ parsed_file.first['elements'].first['steps'].first
162
+ end
163
+
164
+ def build_step(step)
165
+ populate_base(step)
166
+ populate_block(step)
167
+ populate_keyword(step)
168
+ populate_element_source_line(step)
169
+ populate_raw_element(step)
170
+
171
+ scan_arguments
172
+ end
173
+
174
+ def populate_base(step)
175
+ @base = step['name']
176
+ end
177
+
178
+ def populate_block(step)
179
+ @block = build_block(step)
180
+ end
181
+
182
+ def populate_keyword(step)
183
+ @keyword = step['keyword'].strip
184
+ end
185
+
186
+ # Returns the step string minus any arguments based on the given delimiters.
187
+ def stripped_step(step, left_delimiter, right_delimiter)
188
+ unless left_delimiter.nil? || right_delimiter.nil?
189
+ pattern = Regexp.new(Regexp.escape(left_delimiter) + '.*?' + Regexp.escape(right_delimiter))
190
+ step = step.gsub(pattern, left_delimiter + right_delimiter)
191
+ end
192
+
193
+ step
194
+ end
195
+
196
+ def build_block(step)
197
+ case
198
+ when step['rows']
199
+ @block = build_child_element(Table, step['rows'])
200
+ when step['doc_string']
201
+ @block = build_child_element(DocString, step['doc_string'])
202
+ else
203
+ @block = nil
204
+ end
205
+
206
+ @block
207
+ end
208
+
209
+ def rebuild_block_text(blok)
210
+ blok.contents.collect { |row| "|#{row.join('|')}|" }
211
+ end
212
+
213
+ end
214
+ end