nitro 0.20.0 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. data/CHANGELOG +752 -543
  2. data/INSTALL +38 -38
  3. data/README +264 -225
  4. data/Rakefile +48 -49
  5. data/bin/nitro +3 -3
  6. data/bin/nitrogen +6 -6
  7. data/doc/AUTHORS +10 -10
  8. data/doc/CHANGELOG.1 +1939 -1939
  9. data/doc/CHANGELOG.2 +954 -954
  10. data/doc/LICENSE +3 -3
  11. data/doc/MIGRATION +28 -0
  12. data/doc/RELEASES +814 -643
  13. data/doc/config.txt +5 -5
  14. data/install.rb +7 -17
  15. data/lib/nitro.rb +38 -9
  16. data/lib/nitro/adapter/cgi.rb +311 -312
  17. data/lib/nitro/adapter/fastcgi.rb +18 -25
  18. data/lib/nitro/adapter/webrick.rb +128 -137
  19. data/lib/nitro/adapter/wee.rb +51 -0
  20. data/lib/nitro/caching.rb +20 -20
  21. data/lib/nitro/caching/actions.rb +43 -43
  22. data/lib/nitro/caching/fragments.rb +46 -46
  23. data/lib/nitro/caching/invalidation.rb +11 -11
  24. data/lib/nitro/caching/output.rb +65 -65
  25. data/lib/nitro/caching/stores.rb +67 -67
  26. data/lib/nitro/compiler.rb +262 -0
  27. data/lib/nitro/compiler/elements.rb +0 -0
  28. data/lib/nitro/compiler/errors.rb +65 -0
  29. data/lib/nitro/compiler/localization.rb +25 -0
  30. data/lib/nitro/compiler/markup.rb +19 -0
  31. data/lib/nitro/compiler/shaders.rb +206 -0
  32. data/lib/nitro/compiler/squeeze.rb +20 -0
  33. data/lib/nitro/compiler/xslt.rb +61 -0
  34. data/lib/nitro/context.rb +87 -88
  35. data/lib/nitro/controller.rb +151 -158
  36. data/lib/nitro/cookie.rb +34 -34
  37. data/lib/nitro/dispatcher.rb +195 -186
  38. data/lib/nitro/element.rb +132 -126
  39. data/lib/nitro/element/java_script.rb +6 -6
  40. data/lib/nitro/flash.rb +66 -66
  41. data/lib/nitro/mail.rb +192 -192
  42. data/lib/nitro/mixin/buffer.rb +66 -0
  43. data/lib/nitro/mixin/debug.rb +16 -16
  44. data/lib/nitro/mixin/form.rb +88 -0
  45. data/lib/nitro/mixin/helper.rb +2 -2
  46. data/lib/nitro/mixin/javascript.rb +108 -108
  47. data/lib/nitro/mixin/markup.rb +144 -0
  48. data/lib/nitro/mixin/pager.rb +202 -202
  49. data/lib/nitro/mixin/rss.rb +67 -0
  50. data/lib/nitro/mixin/table.rb +63 -0
  51. data/lib/nitro/mixin/xhtml.rb +75 -0
  52. data/lib/nitro/mixin/xml.rb +124 -0
  53. data/lib/nitro/render.rb +183 -359
  54. data/lib/nitro/request.rb +140 -140
  55. data/lib/nitro/response.rb +27 -27
  56. data/lib/nitro/routing.rb +21 -21
  57. data/lib/nitro/scaffold.rb +124 -118
  58. data/lib/nitro/server.rb +117 -80
  59. data/lib/nitro/server/runner.rb +341 -0
  60. data/lib/nitro/service.rb +12 -12
  61. data/lib/nitro/service/xmlrpc.rb +22 -22
  62. data/lib/nitro/session.rb +122 -120
  63. data/lib/nitro/session/drb.rb +9 -9
  64. data/lib/nitro/session/drbserver.rb +34 -34
  65. data/lib/nitro/template.rb +171 -155
  66. data/lib/nitro/testing/assertions.rb +90 -90
  67. data/lib/nitro/testing/context.rb +16 -16
  68. data/lib/nitro/testing/testcase.rb +34 -34
  69. data/proto/conf/lhttpd.conf +9 -9
  70. data/proto/public/error.xhtml +75 -75
  71. data/proto/public/index.xhtml +18 -18
  72. data/proto/public/js/behaviour.js +65 -65
  73. data/proto/public/js/controls.js +1 -1
  74. data/proto/public/js/prototype.js +3 -3
  75. data/proto/public/settings.xhtml +61 -61
  76. data/proto/run.rb +1 -5
  77. data/test/nitro/adapter/raw_post1.bin +0 -0
  78. data/test/nitro/adapter/tc_cgi.rb +57 -57
  79. data/test/nitro/adapter/tc_webrick.rb +4 -4
  80. data/test/nitro/mixin/tc_pager.rb +25 -25
  81. data/test/nitro/mixin/tc_rss.rb +24 -0
  82. data/test/nitro/mixin/tc_table.rb +31 -0
  83. data/test/nitro/mixin/tc_xhtml.rb +13 -0
  84. data/test/nitro/tc_caching.rb +10 -10
  85. data/test/nitro/tc_context.rb +8 -8
  86. data/test/nitro/tc_controller.rb +48 -48
  87. data/test/nitro/tc_cookie.rb +6 -6
  88. data/test/nitro/tc_dispatcher.rb +64 -64
  89. data/test/nitro/tc_element.rb +27 -27
  90. data/test/nitro/tc_flash.rb +31 -31
  91. data/test/nitro/tc_mail.rb +63 -63
  92. data/test/nitro/tc_server.rb +26 -26
  93. data/test/nitro/tc_session.rb +9 -9
  94. data/test/nitro/tc_template.rb +19 -19
  95. data/test/public/blog/list.xhtml +1 -1
  96. metadata +31 -37
  97. data/lib/nitro/buffering.rb +0 -45
  98. data/lib/nitro/builder/form.rb +0 -104
  99. data/lib/nitro/builder/rss.rb +0 -104
  100. data/lib/nitro/builder/table.rb +0 -80
  101. data/lib/nitro/builder/xhtml.rb +0 -132
  102. data/lib/nitro/builder/xml.rb +0 -131
  103. data/lib/nitro/conf.rb +0 -36
  104. data/lib/nitro/environment.rb +0 -21
  105. data/lib/nitro/errors.rb +0 -69
  106. data/lib/nitro/localization.rb +0 -153
  107. data/lib/nitro/markup.rb +0 -147
  108. data/lib/nitro/output.rb +0 -24
  109. data/lib/nitro/runner.rb +0 -348
  110. data/lib/nitro/shaders.rb +0 -206
  111. data/test/nitro/builder/tc_rss.rb +0 -23
  112. data/test/nitro/builder/tc_table.rb +0 -30
  113. data/test/nitro/builder/tc_xhtml.rb +0 -39
  114. data/test/nitro/builder/tc_xml.rb +0 -56
  115. data/test/nitro/tc_localization.rb +0 -49
@@ -9,60 +9,60 @@ module Nitro
9
9
 
10
10
  module Caching
11
11
 
12
- # Action caching.
12
+ # Action caching.
13
13
 
14
- module Fragments
14
+ module Fragments
15
15
 
16
- @@store = FileStore.new # MemoryStore.new
16
+ @@store = FileStore.new # MemoryStore.new
17
17
 
18
- def self.store
19
- @@store
20
- end
21
-
22
- def self.store=(store)
23
- @@store = store
24
- end
25
-
26
- def self.get(name, options = {})
27
- return @@store.read(name, options)
28
- end
29
-
30
- def self.put(name, content = nil, options = {})
31
- @@store.write(name, content, options)
32
- return content
33
- end
34
-
35
- def self.append_features(base) # :nodoc:
36
- super
37
- end
18
+ def self.store
19
+ @@store
20
+ end
21
+
22
+ def self.store=(store)
23
+ @@store = store
24
+ end
25
+
26
+ def self.get(name, options = {})
27
+ return @@store.read(name, options)
28
+ end
29
+
30
+ def self.put(name, content = nil, options = {})
31
+ @@store.write(name, content, options)
32
+ return content
33
+ end
34
+
35
+ def self.append_features(base) # :nodoc:
36
+ super
37
+ end
38
38
 
39
- private
39
+ private
40
40
 
41
- def cache(name = nil, options = {}, &block)
42
- name = @action_name unless name
43
- cache_fragment(block, "#{name}#{options}", options)
44
- end
41
+ def cache(name = nil, options = {}, &block)
42
+ name = @action_name unless name
43
+ cache_fragment(block, "#{name}#{options}", options)
44
+ end
45
45
 
46
- def cache_fragment(block, name, options = {})
47
- unless caching_enabled?
48
- block.call
49
- return
50
- end
46
+ def cache_fragment(block, name, options = {})
47
+ unless caching_enabled?
48
+ block.call
49
+ return
50
+ end
51
51
 
52
- if fragment = Fragments.get(name, options)
53
- @out << fragment
54
- else
55
- pos = @out.length
56
- block.call
57
- Fragments.put(name, @out[pos..-1], options)
58
- end
59
- end
52
+ if fragment = Fragments.get(name, options)
53
+ @out << fragment
54
+ else
55
+ pos = @out.length
56
+ block.call
57
+ Fragments.put(name, @out[pos..-1], options)
58
+ end
59
+ end
60
60
 
61
- def expire_fragment(name, options = {})
62
- Fragments.store.delete(name, options)
63
- end
64
- end
65
-
61
+ def expire_fragment(name, options = {})
62
+ Fragments.store.delete(name, options)
63
+ end
64
+ end
65
+
66
66
  end
67
67
 
68
68
  end
@@ -1,24 +1,24 @@
1
1
  # * George Moschovitis <gm@navel.gr>
2
2
  # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: invalidation.rb 1 2005-04-11 11:04:30Z gmosx $
3
+ # $Id: invalidation.rb 182 2005-07-22 10:07:50Z gmosx $
4
4
 
5
5
  module Nitro
6
6
 
7
7
  module Caching
8
8
 
9
- # Support for invalidating output/fragment caches.
10
-
11
- module Invalidation
9
+ # Support for invalidating output/fragment caches.
10
+
11
+ module Invalidation
12
12
 
13
- def self.append_features(base) #:nodoc:
14
- super
15
- base.extend(ClassMethods)
16
- end
13
+ def self.append_features(base) #:nodoc:
14
+ super
15
+ base.extend(ClassMethods)
16
+ end
17
17
 
18
- module ClassMethods
19
- end
18
+ module ClassMethods
19
+ end
20
20
 
21
- end
21
+ end
22
22
 
23
23
  end
24
24
 
@@ -6,71 +6,71 @@ module Nitro
6
6
 
7
7
  module Caching
8
8
 
9
- # Output caching.
10
-
11
- module Output
12
-
13
- def self.append_features(base) # :nodoc:
14
- super
15
- base.extend(ClassMethods)
16
- base.module_eval do
17
- cattr_accessor :output_cache_root, 'public'
18
- end
19
- end
20
-
21
- module ClassMethods
22
-
23
- def do_cache_output(path, content)
24
- filepath = output_cache_path(path)
25
- FileUtils.makedirs(File.dirname(filepath))
26
- File.open(filepath, 'w+') { |f| f.write(content) }
27
- Logger.debug "Cached page: #{filepath}" if $DBG
28
- end
29
-
30
- # Enable output caching for the given actions.
31
-
32
- def cache_output(*actions)
33
- return unless caching_enabled?
34
-
35
- str = actions.collect { |a| ":#{a}" }.join(', ')
36
-
37
- module_eval %{
38
- post "do_cache_output", :only => [ #{str} ]
39
- }
40
- end
41
-
42
- private
43
-
44
- def output_cache_path(path)
45
- filename = ((path.empty? || path == '/') ? '/index' : path.dup)
46
- # filename.gsub!(/\/$/, '')
47
- filename << 'index.html' unless (name.split('/').last || name).include? '.'
48
- return output_cache_root + '/' + filename
49
- end
50
-
51
- end
52
-
53
- private
54
-
55
- def do_cache_output
56
- if caching_enabled? and caching_allowed?
57
- self.class.do_cache_output(@request.uri, @out)
58
- end
59
- end
60
-
61
- def expire_output(name)
62
- begin
63
- FileUtils.rm("#{context.dispatcher.public_root}/#{name}/index.html")
64
- rescue Object
65
- # gmosx: is this the right thing to do?
66
- end
67
- end
68
-
69
- def caching_allowed?
70
- !@request.post?
71
- end
72
-
73
- end
9
+ # Output caching.
10
+
11
+ module Output
12
+
13
+ def self.append_features(base) # :nodoc:
14
+ super
15
+ base.extend(ClassMethods)
16
+ base.module_eval do
17
+ cattr_accessor :output_cache_root, 'public'
18
+ end
19
+ end
20
+
21
+ module ClassMethods
22
+
23
+ def do_cache_output(path, content)
24
+ filepath = output_cache_path(path)
25
+ FileUtils.makedirs(File.dirname(filepath))
26
+ File.open(filepath, 'w+') { |f| f.write(content) }
27
+ Logger.debug "Cached page: #{filepath}" if $DBG
28
+ end
29
+
30
+ # Enable output caching for the given actions.
31
+
32
+ def cache_output(*actions)
33
+ return unless caching_enabled?
34
+
35
+ str = actions.collect { |a| ":#{a}" }.join(', ')
36
+
37
+ module_eval %{
38
+ post "do_cache_output", :only => [ #{str} ]
39
+ }
40
+ end
41
+
42
+ private
43
+
44
+ def output_cache_path(path)
45
+ filename = ((path.empty? || path == '/') ? '/index' : path.dup)
46
+ # filename.gsub!(/\/$/, '')
47
+ filename << 'index.html' unless (name.split('/').last || name).include? '.'
48
+ return output_cache_root + '/' + filename
49
+ end
50
+
51
+ end
52
+
53
+ private
54
+
55
+ def do_cache_output
56
+ if caching_enabled? and caching_allowed?
57
+ self.class.do_cache_output(@request.uri, @out)
58
+ end
59
+ end
60
+
61
+ def expire_output(name)
62
+ begin
63
+ FileUtils.rm("#{context.dispatcher.public_root}/#{name}/index.html")
64
+ rescue Object
65
+ # gmosx: is this the right thing to do?
66
+ end
67
+ end
68
+
69
+ def caching_allowed?
70
+ !@request.post?
71
+ end
72
+
73
+ end
74
74
 
75
75
  end
76
76
 
@@ -1,6 +1,6 @@
1
1
  # * George Moschovitis <gm@navel.gr>
2
2
  # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: stores.rb 9 2005-04-13 00:08:20Z nasis $
3
+ # $Id: stores.rb 182 2005-07-22 10:07:50Z gmosx $
4
4
 
5
5
  require 'fileutils'
6
6
 
@@ -12,72 +12,72 @@ module Nitro
12
12
 
13
13
  module Caching
14
14
 
15
- # Cached fragments are stored in memory.
16
-
17
- class MemoryStore < Glue::SafeHash
18
-
19
- def read(name, options = {})
20
- self[name]
21
- end
22
-
23
- def write(name, content = '', options = {})
24
- self[name] = content
25
- end
26
-
27
- def delete(name, options = {})
28
- self.delete(name)
29
- end
30
-
31
- end
32
-
33
- # Cached fragments are stored as html files
34
- # on the filesystem.
35
-
36
- class FileStore
37
- cattr_accessor :cache_root, 'cache'
38
-
39
- def initialize(cache_root = FileStore.cache_root)
40
- @cache_root = cache_root
41
- end
42
-
43
- def read(name, options = {})
44
- begin
45
- IO.read(path_for_name(name))
46
- rescue
47
- nil
48
- end
49
- end
50
-
51
- def write(name, content = '', options = {})
52
- begin
53
- path = path_for_name(name)
54
- dir = File.dirname(path)
55
- FileUtils.makedirs(dir) unless File.exists?(dir)
56
-
57
- File.open(path, 'w+') { |f| f.write(content) }
58
- rescue
59
- Logger.error "Could not save cached file '#{path}'"
60
- end
61
- end
62
-
63
- def delete(name, options = {})
64
- path = path_for_name(name)
65
- File.delete(path) if File.exist?(path)
66
- end
67
-
68
- private
69
-
70
- def path_for_name(name)
71
- "#@cache_root/#{name}"
72
- end
73
-
74
- end
75
-
76
- class DrbStrore
77
- end
78
-
79
- class MemcacheStore
80
- end
15
+ # Cached fragments are stored in memory.
16
+
17
+ class MemoryStore < Glue::SafeHash
18
+
19
+ def read(name, options = {})
20
+ self[name]
21
+ end
22
+
23
+ def write(name, content = '', options = {})
24
+ self[name] = content
25
+ end
26
+
27
+ def delete(name, options = {})
28
+ self.delete(name)
29
+ end
30
+
31
+ end
32
+
33
+ # Cached fragments are stored as html files
34
+ # on the filesystem.
35
+
36
+ class FileStore
37
+ cattr_accessor :cache_root, 'cache'
38
+
39
+ def initialize(cache_root = FileStore.cache_root)
40
+ @cache_root = cache_root
41
+ end
42
+
43
+ def read(name, options = {})
44
+ begin
45
+ IO.read(path_for_name(name))
46
+ rescue
47
+ nil
48
+ end
49
+ end
50
+
51
+ def write(name, content = '', options = {})
52
+ begin
53
+ path = path_for_name(name)
54
+ dir = File.dirname(path)
55
+ FileUtils.makedirs(dir) unless File.exists?(dir)
56
+
57
+ File.open(path, 'w+') { |f| f.write(content) }
58
+ rescue
59
+ Logger.error "Could not save cached file '#{path}'"
60
+ end
61
+ end
62
+
63
+ def delete(name, options = {})
64
+ path = path_for_name(name)
65
+ File.delete(path) if File.exist?(path)
66
+ end
67
+
68
+ private
69
+
70
+ def path_for_name(name)
71
+ "#@cache_root/#{name}"
72
+ end
73
+
74
+ end
75
+
76
+ class DrbStrore
77
+ end
78
+
79
+ class MemcacheStore
80
+ end
81
81
 
82
82
  end
83
83
 
@@ -0,0 +1,262 @@
1
+ require 'facet/object/singleton_class'
2
+
3
+ require 'nitro/template'
4
+ require 'nitro/compiler/errors'
5
+
6
+ module Nitro
7
+
8
+ # The Compiler transforms published methods (actions) and
9
+ # assorted template files (views) into specialized code that
10
+ # responds to a URI.
11
+
12
+ class Compiler
13
+ unless const_defined? :PROTO_TEMPLATE_ROOT
14
+ PROTO_TEMPLATE_ROOT = "#{Nitro.proto_path}/public"
15
+ end
16
+
17
+ # Set to true to force reloading of code and templates for
18
+ # each request. Extremely useful during development. Must be
19
+ # turned off in production servers to avoid the severe
20
+ # performance penalty.
21
+
22
+ setting :reload, :default => true, :doc => 'If true all code and templates are reloaded in each request'
23
+
24
+ # Action names with double underscores (__) are converted
25
+ # to subdirectories. Here are some example mappings:
26
+ #
27
+ # hello_world -> template_root/hello_world.xhtml
28
+ # this__is__my__hello_world -> template_root/this/is/my/hello_world
29
+
30
+ def template_for_action(action, template_root = Template.root, ext = Template.extension)
31
+ # attempt to find a template of the form
32
+ # template_root/action.xhtml
33
+
34
+ path = "#{template_root}/#{action.gsub(/__/, '/')}.#{ext}".squeeze('/')
35
+
36
+ unless File.exist?(path)
37
+ # attempt to find a template of the form
38
+ # template_root/action/index.xhtml
39
+
40
+ path = "#{template_root}/#{action.gsub(/__/, '/')}/#{Template.default}.#{ext}".squeeze('/')
41
+
42
+ unless File.exist?(path)
43
+ # No template found!
44
+ return nil
45
+ end
46
+ end
47
+
48
+ return path
49
+ end
50
+
51
+ # This is methods transforms the template. Typically
52
+ # template processors are added as aspects to this method
53
+ # to allow for customized template transformation prior
54
+ # to compilation.
55
+ #
56
+ # The default transformation extracts the Ruby code from
57
+ # processing instructions.
58
+
59
+ def transform_template(template)
60
+ Template.transform(template)
61
+ end
62
+
63
+ # Compile the template into a render method.
64
+
65
+ def compile_template(klass, action, path)
66
+ Logger.debug "Compiling template '#{klass}: #{path}'" if $DBG
67
+
68
+ template = File.read(path)
69
+
70
+ code = %{
71
+ def #{action}_template
72
+ #{transform_template(template)}
73
+ end
74
+ }
75
+
76
+ begin
77
+ klass.class_eval(code, path)
78
+ rescue SyntaxError => e
79
+ raise TemplateCompileError.new(code, template, e)
80
+ end
81
+ end
82
+
83
+ # Compiles an action.
84
+ #
85
+ # Passes the action name and the parent action name in the
86
+ # @action_name and @parent_action_name respectively.
87
+ #--
88
+ # TODO: cleanup this method.
89
+ #++
90
+
91
+ def compile_action(klass, action)
92
+ #--
93
+ # gmosx: Move elsewhere.
94
+ #++
95
+
96
+ Aspects.include_advice_modules(klass)
97
+
98
+ action = action.to_s.gsub(/_action$/, '')
99
+
100
+ return false unless action
101
+
102
+ Logger.debug "Compiling action '#{klass}##{action}'" if $DBG
103
+
104
+ valid = false
105
+
106
+ code = %{
107
+ def #{action}_action
108
+ @parent_action_name = @action_name
109
+ @action_name = '#{action}'
110
+ }
111
+
112
+ # Inject the pre advices.
113
+
114
+ code << Aspects.gen_advice_code(action, klass.advices, :pre)
115
+
116
+ # Call the action
117
+
118
+ if klass.action_methods.include?(action)
119
+ valid = true
120
+
121
+ # Annotated parameters.
122
+
123
+ if meta = klass.action_metadata[action.intern]
124
+ params = meta.params.keys
125
+ params = params.collect { |p| "@#{p} = @context['#{p}']" }
126
+ code << "#{params.join(';')}"
127
+ end
128
+
129
+ # Try to resolve action parameters.
130
+
131
+ param_count = klass.instance_method(action.intern).arity
132
+
133
+ # gmosx, FIXME: REIMPLEMENT THIS!!!!
134
+
135
+ if param_count > 0
136
+ code << %{
137
+ params = []
138
+ qs = context.query_string.split(/[&;]/)
139
+
140
+ #{param_count}.times do |i|
141
+ params << qs.shift.split(/=/).last
142
+ end
143
+
144
+ action_return_value = #{action}(*params)
145
+ }
146
+ else
147
+ code << %{
148
+ action_return_value = #{action}
149
+ }
150
+ end
151
+ code << %{
152
+ unless :stop == action_return_value
153
+ }
154
+ end
155
+
156
+ # Try to call the template method if it exists. It is a
157
+ # nice practice to put output related code in this method
158
+ # instead of the main action so that this method can be
159
+ # overloaded separately.
160
+ #
161
+ # If no template method exists, try to convert an external
162
+ # template file into a template method. It is an even
163
+ # better practice to place the output related code in an
164
+ # external template file.
165
+
166
+ # Take :view metadata into account.
167
+
168
+ view = nil
169
+ if md = klass.action_metadata[action.intern]
170
+ view = md[:view]
171
+ end
172
+ view ||= action
173
+
174
+ cklass = klass
175
+ template_path = nil
176
+
177
+ loop do
178
+ template_root = nil
179
+
180
+ if cklass.respond_to?(:template_root)
181
+ template_root = cklass.template_root
182
+ end
183
+
184
+ # Don't use a proto template if there is an action
185
+ # defined.
186
+
187
+ template_root ||= PROTO_TEMPLATE_ROOT unless valid
188
+
189
+ if template_root and template_path = template_for_action(view.to_s, template_root)
190
+ valid = true
191
+ code << %{
192
+ #{action}_template;
193
+ }
194
+ break
195
+ end
196
+
197
+ break unless cklass = cklass.superclass
198
+ end
199
+
200
+ return false unless valid
201
+
202
+ if klass.action_methods.include?(action)
203
+ code << %{
204
+ if @out.empty? and action_return_value.is_a?(String)
205
+ print(action_return_value)
206
+ end
207
+ end
208
+ }
209
+ end
210
+
211
+ if Render.redirect_on_empty
212
+ code << %{
213
+ redirect_referer if @out.empty?
214
+ }
215
+ end
216
+
217
+ # Inject the post advices.
218
+
219
+ code << Aspects.gen_advice_code(action, klass.advices, :post)
220
+
221
+ code << %{
222
+ @action_name = @parent_action_name
223
+ end
224
+ }
225
+
226
+ # First compile the action method.
227
+
228
+ # begin
229
+ klass.class_eval(code)
230
+ # rescue SyntaxError => e
231
+ # raise ActionCompileError.new(code, action, e)
232
+ # end
233
+
234
+ compile_template(klass, action, template_path) if template_path
235
+
236
+ return true
237
+
238
+ end
239
+
240
+ # Compiles an action method in the given (controller) class.
241
+ # A sync is used to make compilation thread safe.
242
+
243
+ def compile(klass, action)
244
+ compile_action(klass, action)
245
+ end
246
+
247
+ # :section: Helper methods.
248
+
249
+ class << self
250
+ # Helper method for manipulating the template transformation
251
+ # pipeline.
252
+
253
+ def setup_transform_template(&block)
254
+ send :define_method, :transform_template, block
255
+ end
256
+ alias_method :setup_template_transform, :setup_transform_template
257
+ alias_method :setup_template_transformation, :setup_transform_template
258
+ end
259
+
260
+ end
261
+
262
+ end