nitro 0.20.0 → 0.21.0

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 (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