hobo 1.0.3 → 1.1.0.pre0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/CHANGES.txt +0 -66
  2. data/README +3 -0
  3. data/Rakefile +7 -7
  4. data/doctest/model.rdoctest +0 -2
  5. data/doctest/multi_model_forms.rdoctest +0 -2
  6. data/doctest/scopes.rdoctest +13 -21
  7. data/lib/active_record/association_collection.rb +7 -16
  8. data/lib/hobo.rb +10 -65
  9. data/lib/hobo/accessible_associations.rb +1 -5
  10. data/lib/hobo/authentication_support.rb +1 -1
  11. data/lib/hobo/controller.rb +5 -5
  12. data/lib/hobo/hobo_helper.rb +0 -84
  13. data/lib/hobo/lifecycles/lifecycle.rb +37 -31
  14. data/lib/hobo/lifecycles/transition.rb +1 -2
  15. data/lib/hobo/model.rb +13 -21
  16. data/lib/hobo/model_controller.rb +8 -8
  17. data/lib/hobo/rapid_helper.rb +12 -1
  18. data/lib/hobo/scopes/automatic_scopes.rb +26 -13
  19. data/lib/hobo/scopes/named_scope_extensions.rb +16 -28
  20. data/lib/hobo/user_controller.rb +1 -0
  21. data/lib/hobo/view_hints.rb +1 -5
  22. data/rails_generators/hobo/templates/initializer.rb +1 -1
  23. data/rails_generators/hobo_front_controller/templates/summary.dryml +4 -2
  24. data/rails_generators/hobo_model/hobo_model_generator.rb +12 -0
  25. data/rails_generators/hobo_model/templates/model.rb +9 -2
  26. data/rails_generators/hobo_rapid/templates/hobo-rapid.js +98 -23
  27. data/rails_generators/hobo_rapid/templates/themes/clean/public/stylesheets/clean.css +1 -1
  28. data/rails_generators/hobo_rapid/templates/themes/clean/public/stylesheets/rapid-ui.css +3 -1
  29. data/{dryml_generators → rapid_generators}/rapid/cards.dryml.erb +0 -0
  30. data/{dryml_generators → rapid_generators}/rapid/forms.dryml.erb +0 -0
  31. data/{dryml_generators → rapid_generators}/rapid/pages.dryml.erb +1 -1
  32. data/taglibs/rapid.dryml +2 -0
  33. data/taglibs/rapid_core.dryml +10 -9
  34. data/taglibs/rapid_forms.dryml +70 -35
  35. data/taglibs/rapid_lifecycles.dryml +17 -4
  36. data/taglibs/rapid_plus.dryml +3 -3
  37. data/taglibs/rapid_summary.dryml +11 -0
  38. data/taglibs/rapid_user_pages.dryml +39 -28
  39. data/tasks/hobo_tasks.rake +1 -1
  40. metadata +45 -61
  41. data/hobo.gemspec +0 -226
  42. data/lib/hobo/dryml.rb +0 -188
  43. data/lib/hobo/dryml/dryml_builder.rb +0 -140
  44. data/lib/hobo/dryml/dryml_doc.rb +0 -159
  45. data/lib/hobo/dryml/dryml_generator.rb +0 -263
  46. data/lib/hobo/dryml/dryml_support_controller.rb +0 -13
  47. data/lib/hobo/dryml/parser.rb +0 -3
  48. data/lib/hobo/dryml/parser/attribute.rb +0 -41
  49. data/lib/hobo/dryml/parser/base_parser.rb +0 -254
  50. data/lib/hobo/dryml/parser/document.rb +0 -57
  51. data/lib/hobo/dryml/parser/element.rb +0 -27
  52. data/lib/hobo/dryml/parser/elements.rb +0 -45
  53. data/lib/hobo/dryml/parser/source.rb +0 -58
  54. data/lib/hobo/dryml/parser/text.rb +0 -13
  55. data/lib/hobo/dryml/parser/tree_parser.rb +0 -67
  56. data/lib/hobo/dryml/part_context.rb +0 -137
  57. data/lib/hobo/dryml/scoped_variables.rb +0 -42
  58. data/lib/hobo/dryml/tag_parameters.rb +0 -36
  59. data/lib/hobo/dryml/taglib.rb +0 -123
  60. data/lib/hobo/dryml/template.rb +0 -1019
  61. data/lib/hobo/dryml/template_environment.rb +0 -613
  62. data/lib/hobo/dryml/template_handler.rb +0 -187
  63. data/lib/hobo/static_tags +0 -98
  64. data/taglibs/core.dryml +0 -104
@@ -1,263 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require 'set'
3
- require 'fileutils'
4
-
5
- require 'action_controller/dispatcher'
6
-
7
- module Hobo
8
-
9
- module Dryml
10
-
11
- class DrymlGenerator
12
-
13
- TEMPLATES = "#{HOBO_ROOT}/dryml_generators"
14
- OUTPUT = "#{RAILS_ROOT}/app/views/taglibs/auto"
15
-
16
- HEADER = "<!-- AUTOMATICALLY GENERATED FILE - DO NOT EDIT -->\n\n"
17
-
18
- class << self
19
- attr_accessor :run_on_every_request
20
- end
21
-
22
- def self.enable
23
-
24
- # Unfortunately the dispatcher callbacks don't give us the hook we need (after routes are reloaded)
25
- # so we have to alias_method_chain
26
- ActionController::Dispatcher.class_eval do
27
-
28
- if respond_to? :reload_application
29
- #Rails 2.3
30
- class << self
31
- def reload_application_with_dryml_generators
32
- reload_application_without_dryml_generators
33
- DrymlGenerator.run unless Hobo::Dryml::DrymlGenerator.run_on_every_request == false || Rails.env.production?
34
- end
35
- alias_method_chain :reload_application, :dryml_generators
36
- end
37
- else
38
- #Rails <= 2.2
39
- def reload_application_with_dryml_generators
40
- reload_application_without_dryml_generators
41
- DrymlGenerator.run unless Hobo::Dryml::DrymlGenerator.run_on_every_request == false || Rails.env.production?
42
- end
43
- alias_method_chain :reload_application, :dryml_generators
44
- end
45
- end
46
- end
47
-
48
- def self.run
49
- @generator ||= DrymlGenerator.new
50
- @generator.run
51
- end
52
-
53
-
54
- def initialize
55
- @templates = {}
56
- @digests = {}
57
- load_templates
58
- end
59
-
60
- attr_accessor :subsite
61
-
62
-
63
- def load_templates
64
- Dir["#{TEMPLATES}/**/*.dryml.erb"].each do |f|
65
- name = f[TEMPLATES.length + 1..-11]
66
- erb = File.read(f)
67
- @templates[name] = ERB.new(erb, nil, '-').src
68
-
69
- # Create output directories and parents as required
70
- [nil, *Hobo.subsites].each do |s|
71
- FileUtils.mkdir_p(File.dirname("#{output_dir s}/#{name}"))
72
- end
73
- end
74
- end
75
-
76
-
77
- def run
78
- # Ensure all view hints loaded before running
79
- Hobo::Model.all_models.*.view_hints
80
-
81
- [nil, *Hobo.subsites].each { |s| run_for_subsite(s) }
82
- end
83
-
84
-
85
- def run_for_subsite(subsite)
86
- self.subsite = subsite
87
- @templates.each_pair do |name, src|
88
- run_one(name, src)
89
- end
90
- end
91
-
92
-
93
- def output_dir(s=subsite)
94
- s ? "#{OUTPUT}/#{s}" : OUTPUT
95
- end
96
-
97
-
98
- def run_one(name, src)
99
- dryml = instance_eval(src, name)
100
- if dryml_changed?(name, dryml)
101
- out = HEADER + dryml
102
- File.open("#{output_dir}/#{name}.dryml", 'w') { |f| f.write(out) }
103
- end
104
- end
105
-
106
-
107
- def dryml_changed?(name, dryml)
108
- key = "#{subsite}/#{name}"
109
- d = digest dryml
110
- if d != @digests[key]
111
- @digests[key] = d
112
- true
113
- else
114
- false
115
- end
116
- end
117
-
118
-
119
- def digest(s)
120
- OpenSSL::Digest::SHA1.hexdigest(s)
121
- end
122
-
123
-
124
- # --- Helper methods for the templates --- #
125
-
126
- attr_reader :controller
127
-
128
-
129
- def controllers
130
- Hobo::ModelController.all_controllers(subsite).sort_by &:name
131
- end
132
-
133
-
134
- def models
135
- Hobo::Model.all_models.sort_by &:name
136
- end
137
-
138
- def each_controller
139
- controllers.each do |controller|
140
- @controller = controller
141
- yield
142
- end
143
- @controller = nil
144
- end
145
-
146
-
147
- def each_model
148
- models.each do |model|
149
- @model = model
150
- yield
151
- end
152
- @model = nil
153
- end
154
-
155
-
156
- def model
157
- @model || @controller.model
158
- end
159
-
160
-
161
- def model_name(*options)
162
- name = :plural.in?(options) ? model.view_hints.model_name_plural : model.view_hints.model_name
163
- name = name.titleize.downcase if :lowercase.in?(options)
164
- name = name.camelize if :camel.in?(options)
165
- name
166
- end
167
-
168
- # escape single quotes and backslashes for use in a single
169
- # quoted string
170
- def sq_escape(s)
171
- s.gsub(/[\\]/, "\\\\\\\\").gsub(/'/, "\\\\'")
172
- end
173
-
174
-
175
- def model_class
176
- model.name.underscore.gsub('_', '-').gsub('/', '--')
177
- end
178
-
179
-
180
- def view_hints
181
- model.view_hints
182
- end
183
-
184
-
185
- def through_collection_names(klass=model)
186
- klass.reflections.values.select do |refl|
187
- refl.macro == :has_many && refl.options[:through]
188
- end.map {|x| x.options[:through]}
189
- end
190
-
191
-
192
- def linkable?(*args)
193
- options = args.extract_options!
194
- options[:subsite] = subsite
195
- klass, action = if args.length == 1
196
- [model, args.first]
197
- else
198
- args
199
- end
200
- Hobo::ModelRouter.linkable?(klass, action, options)
201
- end
202
-
203
-
204
- def sortable_collection?(collection, model=self.model)
205
- # There's no perfect way to detect for this, given that acts_as_list
206
- # does not provide any metadata to reflect on, but if the :order
207
- # option is the same as the target classes position_column, that's a
208
- # pretty safe bet
209
- if defined? ActiveRecord::Acts::List::InstanceMethods
210
- refl = model.reflections[collection]
211
- klass = refl.klass
212
- klass < ActiveRecord::Acts::List::InstanceMethods &&
213
- klass.new.position_column == refl.options[:order].to_s
214
- end
215
- end
216
-
217
-
218
- def standard_fields(*args)
219
- klass = args.first.is_a?(Class) ? args.shift : model
220
- extras = args
221
-
222
- fields = klass.attr_order.*.to_s & klass.content_columns.*.name
223
-
224
- fields -= %w{created_at updated_at created_on updated_on deleted_at} unless extras.include?(:include_timestamps)
225
-
226
- bt = extras.include?(:belongs_to)
227
- hm = extras.include?(:has_many)
228
- klass.reflections.values.sort_by { |refl| refl.name.to_s }.map do |refl|
229
- fields << refl.name.to_s if bt && refl.macro == :belongs_to
230
- fields << refl.name.to_s if hm && refl.macro == :has_many && refl.options[:accessible]
231
- end
232
-
233
- fields.reject! { |f| model.never_show? f }
234
- fields
235
- end
236
-
237
-
238
- def creators
239
- defined?(model::Lifecycle) ? model::Lifecycle.publishable_creators : []
240
- end
241
-
242
- def transitions
243
- defined?(model::Lifecycle) ? model::Lifecycle.publishable_transitions : []
244
- end
245
-
246
- def creator_names
247
- creators.map { |c| c.name.to_s }
248
- end
249
-
250
- def transition_names
251
- transitions.map { |t| t.name.to_s }.uniq
252
- end
253
-
254
-
255
- def a_or_an(word)
256
- (word =~ /^[aeiou]/i ? "an " : "a ") + word
257
- end
258
-
259
- end
260
-
261
- end
262
-
263
- end
@@ -1,13 +0,0 @@
1
- class Hobo::Dryml::DrymlSupportController < ActionController::Base
2
-
3
- def edit_source
4
- dryml_editor = ENV['DRYML_EDITOR']
5
- if dryml_editor
6
- file = File.join(RAILS_ROOT, params[:file])
7
- command = dryml_editor.sub(":file", file).sub(":line", params[:line])
8
- system(command)
9
- end
10
- render :nothing => true
11
- end
12
-
13
- end
@@ -1,3 +0,0 @@
1
- module Hobo::Dryml::Parser
2
-
3
- end
@@ -1,41 +0,0 @@
1
- module Hobo::Dryml::Parser
2
-
3
- class Attribute < REXML::Attribute
4
-
5
- def initialize(first, second=nil, parent=nil)
6
- super
7
- if first.is_a?(String) && second == true
8
- @value = true
9
- end
10
- end
11
-
12
- def value
13
- if has_rhs?
14
- super
15
- else
16
- element.document.default_attribute_value
17
- end
18
- end
19
-
20
- def to_string
21
- if has_rhs?
22
- super
23
- else
24
- @expanded_name
25
- end
26
- end
27
-
28
- def has_rhs?
29
- @value != true
30
- end
31
-
32
-
33
- # Override to supress Text.check call
34
- def element=( element )
35
- @element = element
36
- self
37
- end
38
-
39
- end
40
-
41
- end
@@ -1,254 +0,0 @@
1
- module Hobo::Dryml::Parser
2
-
3
- class BaseParser < REXML::Parsers::BaseParser
4
-
5
- NEW_REX = defined?(REXML::VERSION) && REXML::VERSION =~ /3\.1\.(\d)(?:\.(\d))?/ && $1.to_i*1000 + $2.to_i >= 7002
6
-
7
- DRYML_NAME_STR = "#{NCNAME_STR}(?::(?:#{NCNAME_STR})?)?"
8
- DRYML_ATTRIBUTE_PATTERN = if NEW_REX
9
- /\s*(#{NAME_STR})(?:\s*=\s*(["'])(.*?)\4)?/um
10
- else
11
- /\s*(#{NAME_STR})(?:\s*=\s*(["'])(.*?)\2)?/um
12
- end
13
- DRYML_TAG_MATCH = if NEW_REX
14
- /^<((?>#{DRYML_NAME_STR}))\s*((?>\s+#{NAME_STR}(?:\s*=\s*(["']).*?\5)?)*)\s*(\/)?>/um
15
- else
16
- /^<((?>#{DRYML_NAME_STR}))\s*((?>\s+#{NAME_STR}(?:\s*=\s*(["']).*?\3)?)*)\s*(\/)?>/um
17
- end
18
- DRYML_CLOSE_MATCH = /^\s*<\/(#{DRYML_NAME_STR})\s*>/um
19
-
20
- # For compatibility with REXML 3.1.7.3
21
- IDENTITY = /^([!\*\w\-]+)(\s+#{NCNAME_STR})?(\s+["'](.*?)['"])?(\s+['"](.*?)["'])?/u
22
-
23
- def pull
24
- if @closed
25
- x, @closed = @closed, nil
26
- return [ :end_element, x, false ]
27
- end
28
- return [ :end_document ] if empty?
29
- return @stack.shift if @stack.size > 0
30
- #STDERR.puts @source.encoding
31
- @source.read if @source.buffer.size<2
32
- #STDERR.puts "BUFFER = #{@source.buffer.inspect}"
33
- if @document_status == nil
34
- #@source.consume( /^\s*/um )
35
- word = @source.match( /^((?:\s+)|(?:<[^>]*>))/um ) #word = @source.match(/(<[^>]*)>/um)
36
- word = word[1] unless word.nil?
37
- #STDERR.puts "WORD = #{word.inspect}"
38
- case word
39
- when COMMENT_START
40
- return [ :comment, @source.match( COMMENT_PATTERN, true )[1] ]
41
- when XMLDECL_START
42
- #STDERR.puts "XMLDECL"
43
- results = @source.match( XMLDECL_PATTERN, true )[1]
44
- version = VERSION.match( results )
45
- version = version[1] unless version.nil?
46
- encoding = ENCODING.match(results)
47
- encoding = encoding[1] unless encoding.nil?
48
- @source.encoding = encoding
49
- standalone = STANDALONE.match(results)
50
- standalone = standalone[1] unless standalone.nil?
51
- return [ :xmldecl, version, encoding, standalone ]
52
- when INSTRUCTION_START
53
- return [ :processing_instruction, *@source.match(INSTRUCTION_PATTERN, true)[1,2] ]
54
- when DOCTYPE_START
55
- md = @source.match( DOCTYPE_PATTERN, true )
56
- #@nsstack.unshift(curr_ns=Set.new)
57
- identity = md[1]
58
- close = md[2]
59
- identity =~ IDENTITY
60
- name = $1
61
- raise REXML::ParseException.new("DOCTYPE is missing a name") if name.nil?
62
- pub_sys = $2.nil? ? nil : $2.strip
63
- long_name = $4.nil? ? nil : $4.strip
64
- uri = $6.nil? ? nil : $6.strip
65
- args = [ :start_doctype, name, pub_sys, long_name, uri ]
66
- if close == ">"
67
- @document_status = :after_doctype
68
- @source.read if @source.buffer.size<2
69
- md = @source.match(/^\s*/um, true)
70
- @stack << [ :end_doctype ]
71
- else
72
- @document_status = :in_doctype
73
- end
74
- return args
75
- when /^\s+/
76
- else
77
- @document_status = :after_doctype
78
- @source.read if @source.buffer.size<2
79
- md = @source.match(/\s*/um, true)
80
- if @source.encoding == "UTF-8"
81
- if @source.buffer.respond_to? :force_encoding
82
- @source.buffer.force_encoding(Encoding::UTF_8)
83
- end
84
- end
85
- end
86
- end
87
- if @document_status == :in_doctype
88
- md = @source.match(/\s*(.*?>)/um)
89
- case md[1]
90
- when SYSTEMENTITY
91
- match = @source.match( SYSTEMENTITY, true )[1]
92
- return [ :externalentity, match ]
93
-
94
- when ELEMENTDECL_START
95
- return [ :elementdecl, @source.match( ELEMENTDECL_PATTERN, true )[1] ]
96
-
97
- when ENTITY_START
98
- match = @source.match( ENTITYDECL, true ).to_a.compact
99
- match[0] = :entitydecl
100
- ref = false
101
- if match[1] == '%'
102
- ref = true
103
- match.delete_at 1
104
- end
105
- # Now we have to sort out what kind of entity reference this is
106
- if match[2] == 'SYSTEM'
107
- # External reference
108
- match[3] = match[3][1..-2] # PUBID
109
- match.delete_at(4) if match.size > 4 # Chop out NDATA decl
110
- # match is [ :entity, name, SYSTEM, pubid(, ndata)? ]
111
- elsif match[2] == 'PUBLIC'
112
- # External reference
113
- match[3] = match[3][1..-2] # PUBID
114
- match[4] = match[4][1..-2] # HREF
115
- # match is [ :entity, name, PUBLIC, pubid, href ]
116
- else
117
- match[2] = match[2][1..-2]
118
- match.pop if match.size == 4
119
- # match is [ :entity, name, value ]
120
- end
121
- match << '%' if ref
122
- return match
123
- when ATTLISTDECL_START
124
- md = @source.match( ATTLISTDECL_PATTERN, true )
125
- raise REXML::ParseException.new( "Bad ATTLIST declaration!", @source ) if md.nil?
126
- element = md[1]
127
- contents = md[0]
128
-
129
- pairs = {}
130
- values = md[0].scan( ATTDEF_RE )
131
- values.each do |attdef|
132
- unless attdef[3] == "#IMPLIED"
133
- attdef.compact!
134
- val = attdef[3]
135
- val = attdef[4] if val == "#FIXED "
136
- pairs[attdef[0]] = val
137
- if attdef[0] =~ /^xmlns:(.*)/
138
- #@nsstack[0] << $1
139
- end
140
- end
141
- end
142
- return [ :attlistdecl, element, pairs, contents ]
143
- when NOTATIONDECL_START
144
- md = nil
145
- if @source.match( PUBLIC )
146
- md = @source.match( PUBLIC, true )
147
- vals = [md[1],md[2],md[4],md[6]]
148
- elsif @source.match( SYSTEM )
149
- md = @source.match( SYSTEM, true )
150
- vals = [md[1],md[2],nil,md[4]]
151
- else
152
- raise REXML::ParseException.new( "error parsing notation: no matching pattern", @source )
153
- end
154
- return [ :notationdecl, *vals ]
155
- when CDATA_END
156
- @document_status = :after_doctype
157
- @source.match( CDATA_END, true )
158
- return [ :end_doctype ]
159
- end
160
- end
161
- begin
162
- if @source.buffer[0] == ?<
163
- if @source.buffer[1] == ?/
164
- #@nsstack.shift
165
- last_tag, line_no = @tags.pop
166
- #md = @source.match_to_consume( '>', CLOSE_MATCH)
167
- md = @source.match(DRYML_CLOSE_MATCH, true)
168
-
169
- valid_end_tag = last_tag =~ /^#{Regexp.escape(md[1])}(:.*)?$/
170
- raise REXML::ParseException.new( "Missing end tag for "+
171
- "'#{last_tag}' (line #{line_no}) (got \"#{md[1]}\")",
172
- @source) unless valid_end_tag
173
- return [ :end_element, last_tag, true ]
174
- elsif @source.buffer[1] == ?!
175
- md = @source.match(/\A(\s*[^>]*>)/um)
176
- #STDERR.puts "SOURCE BUFFER = #{source.buffer}, #{source.buffer.size}"
177
- raise REXML::ParseException.new("Malformed node", @source) unless md
178
- if md[0][2] == ?-
179
- md = @source.match( COMMENT_PATTERN, true )
180
-
181
- case md[1]
182
- when /--/, /-$/
183
- raise REXML::ParseException.new("Malformed comment", @source)
184
- end
185
-
186
- return [ :comment, md[1] ] if md
187
- else
188
- md = @source.match( CDATA_PATTERN, true )
189
- return [ :cdata, md[1] ] if md
190
- end
191
- raise REXML::ParseException.new( "Declarations can only occur "+
192
- "in the doctype declaration.", @source)
193
- elsif @source.buffer[1] == ??
194
- md = @source.match( INSTRUCTION_PATTERN, true )
195
- return [ :processing_instruction, md[1], md[2] ] if md
196
- raise REXML::ParseException.new( "Bad instruction declaration",
197
- @source)
198
- else
199
- # Get the next tag
200
- md = @source.match(DRYML_TAG_MATCH, true)
201
- unless md
202
- # Check for missing attribute quotes
203
- raise REXML::ParseException.new("missing attribute quote", @source) if
204
- defined?(MISSING_ATTRIBUTE_QUOTES) && @source.match(MISSING_ATTRIBUTE_QUOTES)
205
- raise REXML::ParseException.new("malformed XML: missing tag start", @source)
206
-
207
- end
208
- attributes = {}
209
- #@nsstack.unshift(curr_ns=Set.new)
210
- if md[2].size > 0
211
- attrs = md[2].scan(DRYML_ATTRIBUTE_PATTERN)
212
- raise REXML::ParseException.new( "error parsing attributes: [#{attrs.join ', '}], excess = \"#$'\"", @source) if $' and $'.strip.size > 0
213
- attrs.each { |a,b,c,d,e|
214
- val = NEW_REX ? e : c
215
- if attributes.has_key? a
216
- msg = "Duplicate attribute #{a.inspect}"
217
- raise REXML::ParseException.new( msg, @source, self)
218
- end
219
- attributes[a] = val || true
220
- }
221
- end
222
-
223
- if md[NEW_REX ? 6 : 4]
224
- @closed = md[1]
225
- #@nsstack.shift
226
- else
227
- cl = @source.current_line
228
- @tags.push( [md[1], cl && cl[2]] )
229
- end
230
- return [ :start_element, md[1], attributes, md[0],
231
- @source.respond_to?(:last_match_offset) && @source.last_match_offset ]
232
- end
233
- else
234
- md = @source.match( TEXT_PATTERN, true )
235
- if md[0].length == 0
236
- @source.match( /(\s+)/, true )
237
- end
238
- #STDERR.puts "GOT #{md[1].inspect}" unless md[0].length == 0
239
- #return [ :text, "" ] if md[0].length == 0
240
- # unnormalized = Text::unnormalize( md[1], self )
241
- # return PullEvent.new( :text, md[1], unnormalized )
242
- return [ :text, md[1] ]
243
- end
244
- rescue REXML::ParseException
245
- raise
246
- rescue Exception, NameError => error
247
- raise REXML::ParseException.new( "Exception parsing",
248
- @source, self, (error ? error : $!) )
249
- end
250
- return [ :dummy ]
251
- end
252
- end
253
-
254
- end