merb 0.3.7 → 0.4.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 (173) hide show
  1. data/README +25 -26
  2. data/Rakefile +48 -36
  3. data/app_generators/merb/USAGE +5 -0
  4. data/app_generators/merb/merb_generator.rb +107 -0
  5. data/app_generators/merb/templates/Rakefile +99 -0
  6. data/{examples/skeleton/dist → app_generators/merb/templates}/app/controllers/application.rb +1 -1
  7. data/app_generators/merb/templates/app/controllers/exceptions.rb +13 -0
  8. data/{examples/skeleton/dist → app_generators/merb/templates}/app/helpers/global_helper.rb +0 -0
  9. data/{examples/skeleton/dist/app/mailers → app_generators/merb/templates/app/mailers/views}/layout/application.erb +0 -0
  10. data/app_generators/merb/templates/app/views/exceptions/internal_server_error.html.erb +207 -0
  11. data/app_generators/merb/templates/app/views/exceptions/not_acceptable.html.erb +38 -0
  12. data/app_generators/merb/templates/app/views/exceptions/not_found.html.erb +40 -0
  13. data/app_generators/merb/templates/app/views/layout/application.html.erb +11 -0
  14. data/app_generators/merb/templates/config/boot.rb +11 -0
  15. data/app_generators/merb/templates/config/dependencies.rb +41 -0
  16. data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/development.rb +0 -0
  17. data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/production.rb +0 -0
  18. data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/test.rb +0 -0
  19. data/app_generators/merb/templates/config/merb.yml +64 -0
  20. data/app_generators/merb/templates/config/merb_init.rb +16 -0
  21. data/app_generators/merb/templates/config/plugins.yml +1 -0
  22. data/app_generators/merb/templates/config/router.rb +32 -0
  23. data/{lib/merb/core_ext/merb_array.rb → app_generators/merb/templates/config/upload.conf} +0 -0
  24. data/app_generators/merb/templates/public/images/merb.jpg +0 -0
  25. data/app_generators/merb/templates/public/merb.fcgi +6 -0
  26. data/app_generators/merb/templates/public/stylesheets/master.css +119 -0
  27. data/app_generators/merb/templates/script/destroy +28 -0
  28. data/app_generators/merb/templates/script/generate +28 -0
  29. data/{examples/skeleton → app_generators/merb/templates}/script/stop_merb +0 -0
  30. data/app_generators/merb/templates/script/win_script.cmd +1 -0
  31. data/app_generators/merb/templates/spec/spec.opts +6 -0
  32. data/app_generators/merb/templates/spec/spec_helper.rb +10 -0
  33. data/app_generators/merb/templates/test/test_helper.rb +13 -0
  34. data/app_generators/merb_plugin/USAGE +5 -0
  35. data/app_generators/merb_plugin/merb_plugin_generator.rb +64 -0
  36. data/app_generators/merb_plugin/templates/LICENSE +20 -0
  37. data/app_generators/merb_plugin/templates/README +4 -0
  38. data/app_generators/merb_plugin/templates/Rakefile +35 -0
  39. data/app_generators/merb_plugin/templates/TODO +5 -0
  40. data/app_generators/merb_plugin/templates/merbtasks.rb +6 -0
  41. data/app_generators/merb_plugin/templates/sampleplugin.rb +10 -0
  42. data/app_generators/merb_plugin/templates/sampleplugin_spec.rb +7 -0
  43. data/app_generators/merb_plugin/templates/spec_helper.rb +2 -0
  44. data/bin/merb +1 -1
  45. data/lib/autotest/discover.rb +3 -0
  46. data/lib/autotest/merb_rspec.rb +79 -0
  47. data/lib/merb.rb +72 -93
  48. data/lib/merb/{merb_abstract_controller.rb → abstract_controller.rb} +28 -5
  49. data/lib/merb/caching/action_cache.rb +65 -29
  50. data/lib/merb/caching/fragment_cache.rb +9 -4
  51. data/lib/merb/caching/store/file_cache.rb +22 -14
  52. data/lib/merb/caching/store/memory_cache.rb +26 -8
  53. data/lib/merb/{merb_constants.rb → constants.rb} +9 -7
  54. data/lib/merb/controller.rb +178 -0
  55. data/lib/merb/core_ext.rb +13 -11
  56. data/lib/merb/core_ext/array.rb +0 -0
  57. data/lib/merb/core_ext/{merb_class.rb → class.rb} +0 -0
  58. data/lib/merb/core_ext/{merb_enumerable.rb → enumerable.rb} +0 -0
  59. data/lib/merb/core_ext/get_args.rb +52 -0
  60. data/lib/merb/core_ext/{merb_hash.rb → hash.rb} +40 -11
  61. data/lib/merb/core_ext/{merb_inflections.rb → inflections.rb} +0 -0
  62. data/lib/merb/core_ext/{merb_inflector.rb → inflector.rb} +1 -1
  63. data/lib/merb/core_ext/{merb_kernel.rb → kernel.rb} +56 -3
  64. data/lib/merb/core_ext/mash.rb +88 -0
  65. data/lib/merb/core_ext/{merb_module.rb → module.rb} +0 -0
  66. data/lib/merb/core_ext/{merb_numeric.rb → numeric.rb} +0 -0
  67. data/lib/merb/core_ext/{merb_object.rb → object.rb} +10 -47
  68. data/lib/merb/core_ext/string.rb +56 -0
  69. data/lib/merb/core_ext/{merb_symbol.rb → symbol.rb} +0 -0
  70. data/lib/merb/dispatcher.rb +109 -0
  71. data/lib/merb/{merb_drb_server.rb → drb_server.rb} +0 -0
  72. data/lib/merb/erubis_ext.rb +10 -0
  73. data/lib/merb/exceptions.rb +173 -0
  74. data/lib/merb/generators/merb_app/merb_app.rb +5 -25
  75. data/lib/merb/generators/merb_generator_helpers.rb +317 -0
  76. data/lib/merb/generators/merb_plugin.rb +19 -0
  77. data/lib/merb/logger.rb +65 -0
  78. data/lib/merb/{merb_mail_controller.rb → mail_controller.rb} +102 -49
  79. data/lib/merb/{merb_mailer.rb → mailer.rb} +31 -27
  80. data/lib/merb/mixins/{basic_authentication_mixin.rb → basic_authentication.rb} +3 -3
  81. data/lib/merb/mixins/{controller_mixin.rb → controller.rb} +131 -112
  82. data/lib/merb/mixins/{erubis_capture_mixin.rb → erubis_capture.rb} +12 -21
  83. data/lib/merb/mixins/{form_control_mixin.rb → form_control.rb} +6 -12
  84. data/lib/merb/mixins/render.rb +401 -0
  85. data/lib/merb/mixins/responder.rb +378 -0
  86. data/lib/merb/mixins/{view_context_mixin.rb → view_context.rb} +65 -10
  87. data/lib/merb/mixins/web_controller.rb +29 -0
  88. data/lib/merb/{merb_handler.rb → mongrel_handler.rb} +59 -38
  89. data/lib/merb/part_controller.rb +19 -0
  90. data/lib/merb/plugins.rb +16 -0
  91. data/lib/merb/rack_adapter.rb +37 -0
  92. data/lib/merb/request.rb +421 -0
  93. data/lib/merb/router.rb +576 -0
  94. data/lib/merb/{merb_server.rb → server.rb} +275 -71
  95. data/lib/merb/session.rb +10 -10
  96. data/lib/merb/session/cookie_store.rb +125 -0
  97. data/lib/merb/session/{merb_mem_cache_session.rb → mem_cache_session.rb} +22 -9
  98. data/lib/merb/session/{merb_memory_session.rb → memory_session.rb} +15 -11
  99. data/lib/merb/template.rb +35 -8
  100. data/lib/merb/template/erubis.rb +16 -10
  101. data/lib/merb/template/haml.rb +33 -20
  102. data/lib/merb/template/markaby.rb +16 -14
  103. data/lib/merb/template/xml_builder.rb +8 -4
  104. data/lib/merb/test/{merb_fake_request.rb → fake_request.rb} +11 -5
  105. data/lib/merb/test/helper.rb +31 -0
  106. data/lib/merb/test/hpricot.rb +136 -0
  107. data/lib/merb/test/{merb_multipart.rb → multipart.rb} +1 -1
  108. data/lib/merb/test/rspec.rb +93 -0
  109. data/lib/merb/{merb_upload_handler.rb → upload_handler.rb} +5 -6
  110. data/lib/merb/{merb_upload_progress.rb → upload_progress.rb} +1 -1
  111. data/lib/merb/{merb_view_context.rb → view_context.rb} +27 -42
  112. data/lib/{merb_tasks.rb → tasks.rb} +0 -0
  113. data/lib/tasks/merb.rake +21 -11
  114. data/merb_default_generators/model/USAGE +0 -0
  115. data/merb_default_generators/model/model_generator.rb +16 -0
  116. data/merb_default_generators/model/templates/new_model_template.erb +5 -0
  117. data/merb_default_generators/resource_controller/USAGE +0 -0
  118. data/merb_default_generators/resource_controller/resource_controller_generator.rb +26 -0
  119. data/merb_default_generators/resource_controller/templates/controller.rb +30 -0
  120. data/merb_default_generators/resource_controller/templates/edit.html.erb +1 -0
  121. data/merb_default_generators/resource_controller/templates/helper.rb +5 -0
  122. data/merb_default_generators/resource_controller/templates/index.html.erb +1 -0
  123. data/merb_default_generators/resource_controller/templates/new.html.erb +1 -0
  124. data/merb_default_generators/resource_controller/templates/show.html.erb +1 -0
  125. data/merb_generators/controller/USAGE +5 -0
  126. data/merb_generators/controller/controller_generator.rb +16 -0
  127. data/merb_generators/controller/templates/controller.rb +8 -0
  128. data/merb_generators/controller/templates/helper.rb +5 -0
  129. data/merb_generators/controller/templates/index.html.erb +3 -0
  130. data/merb_generators/resource/USAGE +0 -0
  131. data/merb_generators/resource/resource_generator.rb +60 -0
  132. data/rspec_generators/merb_controller_test/merb_controller_test_generator.rb +67 -0
  133. data/rspec_generators/merb_controller_test/templates/controller_spec.rb +8 -0
  134. data/rspec_generators/merb_controller_test/templates/edit_spec.rb +12 -0
  135. data/rspec_generators/merb_controller_test/templates/helper_spec.rb +5 -0
  136. data/rspec_generators/merb_controller_test/templates/index_spec.rb +12 -0
  137. data/rspec_generators/merb_controller_test/templates/new_spec.rb +12 -0
  138. data/rspec_generators/merb_controller_test/templates/show_spec.rb +5 -0
  139. data/rspec_generators/merb_model_test/merb_model_test_generator.rb +26 -0
  140. data/rspec_generators/merb_model_test/templates/model_spec_template.erb +7 -0
  141. data/script/destroy +14 -0
  142. data/script/generate +14 -0
  143. data/test_unit_generators/merb_controller_test/merb_controller_test_generator.rb +53 -0
  144. data/test_unit_generators/merb_controller_test/templates/functional_test.rb +17 -0
  145. data/test_unit_generators/merb_controller_test/templates/helper_test.rb +9 -0
  146. data/test_unit_generators/merb_model_test/merb_model_test_generator.rb +29 -0
  147. data/test_unit_generators/merb_model_test/templates/model_test_unit_template.erb +9 -0
  148. metadata +172 -94
  149. data/examples/README_EXAMPLES +0 -10
  150. data/examples/skeleton/Rakefile +0 -68
  151. data/examples/skeleton/dist/app/views/layout/application.herb +0 -12
  152. data/examples/skeleton/dist/conf/database.yml +0 -23
  153. data/examples/skeleton/dist/conf/merb.yml +0 -57
  154. data/examples/skeleton/dist/conf/merb_init.rb +0 -24
  155. data/examples/skeleton/dist/conf/router.rb +0 -22
  156. data/examples/skeleton/dist/conf/upload.conf +0 -5
  157. data/examples/skeleton/dist/schema/migrations/001_add_sessions_table.rb +0 -14
  158. data/examples/skeleton/script/new_migration +0 -21
  159. data/lib/merb/core_ext/merb_string.rb +0 -18
  160. data/lib/merb/merb_controller.rb +0 -206
  161. data/lib/merb/merb_dispatcher.rb +0 -87
  162. data/lib/merb/merb_exceptions.rb +0 -319
  163. data/lib/merb/merb_part_controller.rb +0 -42
  164. data/lib/merb/merb_plugins.rb +0 -293
  165. data/lib/merb/merb_request.rb +0 -165
  166. data/lib/merb/merb_router.rb +0 -309
  167. data/lib/merb/merb_yaml_store.rb +0 -31
  168. data/lib/merb/mixins/render_mixin.rb +0 -283
  169. data/lib/merb/mixins/responder_mixin.rb +0 -159
  170. data/lib/merb/session/merb_ar_session.rb +0 -131
  171. data/lib/merb/vendor/paginator/README.txt +0 -84
  172. data/lib/merb/vendor/paginator/paginator.rb +0 -124
  173. data/lib/tasks/db.rake +0 -55
@@ -2,16 +2,16 @@ module Merb
2
2
  module SessionMixin
3
3
 
4
4
  def rand_uuid
5
- sid = "%04x%04x%04x%04x%04x%06x%06x" % [
6
- rand(0x0010000),
7
- rand(0x0010000),
8
- rand(0x0010000),
9
- rand(0x0010000),
10
- rand(0x0010000),
11
- rand(0x1000000),
12
- rand(0x1000000),
13
- ]
14
- sid
5
+ values = [
6
+ rand(0x0010000),
7
+ rand(0x0010000),
8
+ rand(0x0010000),
9
+ rand(0x0010000),
10
+ rand(0x0010000),
11
+ rand(0x1000000),
12
+ rand(0x1000000),
13
+ ]
14
+ "%04x%04x%04x%04x%04x%06x%06x" % values
15
15
  end
16
16
 
17
17
  def needs_new_cookie!
@@ -0,0 +1,125 @@
1
+ require 'base64' # to convert Marshal.dump to ASCII
2
+ require 'openssl' # to generate the HMAC message digest
3
+
4
+ # Most of this code is taken from bitsweat's implementation in rails
5
+
6
+ module Merb
7
+
8
+ module SessionMixin
9
+ def setup_session
10
+ MERB_LOGGER.info("Setting Cookie Store Sessions")
11
+ unless secret = Merb::Server.config[:session_secret_key]
12
+ raise 'You must set :session_secret_key in config/merb.yml for cookie sessions'
13
+ end
14
+ request.session = Merb::CookieStore.new(cookies[_session_id_key], secret)
15
+ end
16
+
17
+ def finalize_session
18
+ MERB_LOGGER.info("Finalize Cookie Store Session")
19
+ if request.session.modified?
20
+ set_cookie(_session_id_key, request.session.read_cookie, _session_expiry)
21
+ end
22
+ end
23
+
24
+ def session_store_type
25
+ "cookie"
26
+ end
27
+ end
28
+
29
+ # If you have more than 4K of session data or don't want your data to be
30
+ # visible to the user, pick another session store.
31
+ #
32
+ # CookieOverflow is raised if you attempt to store more than 4K of data.
33
+ # TamperedWithCookie is raised if the data integrity check fails.
34
+ #
35
+ # A message digest is included with the cookie to ensure data integrity:
36
+ # a user cannot alter his user_id without knowing the secret key included in
37
+ # the hash.
38
+ #
39
+ # To use Cookie Sessions, set in config/merb.yml
40
+ # :session_secret_key - your secret digest key
41
+ # :cookie_store_session - to true
42
+ class CookieStore
43
+ # TODO (maybe):
44
+ # include request ip address
45
+ # AES encrypt marshaled data
46
+
47
+ # Raised when storing more than 4K of session data.
48
+ class CookieOverflow < StandardError; end
49
+
50
+ # Raised when the cookie fails its integrity check.
51
+ class TamperedWithCookie < StandardError; end
52
+
53
+ # Cookies can typically store 4096 bytes.
54
+ MAX = 4096
55
+ DIGEST = OpenSSL::Digest::Digest.new('SHA1') # or MD5, RIPEMD160, SHA256?
56
+
57
+ attr_reader :data
58
+
59
+ def initialize(cookie, secret)
60
+ if secret.nil? or secret.blank?
61
+ raise ArgumentError, 'A secret is required to generate an integrity hash for cookie session data.'
62
+ end
63
+ @secret = secret
64
+ @data = unmarshal(cookie) || Hash.new
65
+ @modified = false
66
+ end
67
+
68
+ # return a cookie value. raises CookieOverflow if session contains too
69
+ # much information
70
+ def read_cookie
71
+ unless @data.nil? or @data.empty?
72
+ updated = marshal(@data)
73
+ raise CookieOverflow if updated.size > MAX
74
+ updated
75
+ end
76
+ end
77
+
78
+ # returns true if the session has been modified since initialization
79
+ def modified?; @modified; end
80
+
81
+ # assigns a key value pair
82
+ def []=(k, v)
83
+ unless @data[k]==v
84
+ @modified = true
85
+ @data[k] = v
86
+ end
87
+ end
88
+
89
+ def [](k)
90
+ @data[k]
91
+ end
92
+
93
+ # delete a key
94
+ def delete(key)
95
+ if @data.has_key(key)
96
+ @modified = true
97
+ @data.delete(key)
98
+ end
99
+ end
100
+
101
+ private
102
+
103
+ # Generate the HMAC keyed message digest. Uses SHA1.
104
+ def generate_digest(data)
105
+ OpenSSL::HMAC.hexdigest(DIGEST, @secret, data)
106
+ end
107
+
108
+ # Marshal a session hash into safe cookie data. Include an integrity hash.
109
+ def marshal(session)
110
+ data = Base64.encode64(Marshal.dump(session)).chop
111
+ Mongrel::HttpRequest.escape "#{data}--#{generate_digest(data)}"
112
+ end
113
+
114
+ # Unmarshal cookie data to a hash and verify its integrity.
115
+ def unmarshal(cookie)
116
+ if cookie
117
+ data, digest = Mongrel::HttpRequest.unescape(cookie).split('--')
118
+ unless digest == generate_digest(data)
119
+ raise TamperedWithCookie, "Maybe the site's session_secret_key has changed?"
120
+ end
121
+ Marshal.load(Base64.decode64(data))
122
+ end
123
+ end
124
+ end
125
+ end
@@ -6,18 +6,23 @@ module Merb
6
6
 
7
7
  def setup_session
8
8
  MERB_LOGGER.info("Setting up session")
9
- before = @_cookies[_session_id_key]
10
- @_session, @_cookies[_session_id_key] = Merb::MemCacheSession.persist(@_cookies[_session_id_key])
11
- @_fingerprint = Marshal.dump(@_session.data).hash
9
+ before = cookies[_session_id_key]
10
+ request.session, cookies[_session_id_key] = Merb::MemCacheSession.persist(cookies[_session_id_key])
11
+ @_fingerprint = Marshal.dump(request.session.data).hash
12
12
  @_new_cookie = cookies[_session_id_key] != before
13
13
  end
14
14
 
15
15
  def finalize_session
16
16
  MERB_LOGGER.info("Finalize session")
17
- ::Cache.put("session:#{@_session.session_id}", @_session) if @_fingerprint != Marshal.dump(@_session.data).hash
18
- set_cookie(_session_id_key, @_session.session_id, _session_expiry) if (@_new_cookie || @_session.needs_new_cookie)
17
+ if @_fingerprint != Marshal.dump(request.session.data).hash
18
+ ::Cache.put("session:#{@_session.session_id}", request.session.data)
19
+ end
20
+ set_cookie(_session_id_key, request.session.session_id, _session_expiry) if (@_new_cookie || request.session.needs_new_cookie)
19
21
  end
20
22
 
23
+ def session_store_type
24
+ "memcache"
25
+ end
21
26
  end
22
27
 
23
28
  ##
@@ -25,12 +30,12 @@ module Merb
25
30
  #
26
31
  # Requires setup in your +merb_init.rb+:
27
32
  #
28
- # require 'memcache_util'
33
+ # require 'memcache'
29
34
  # CACHE = MemCache.new('127.0.0.1:11211', { :namespace => 'my_app' })
30
35
  #
31
36
  # And a setting in +merb.yml+:
32
37
  #
33
- # :mem_cache_session: true
38
+ # :session_store: mem_cache
34
39
 
35
40
  class MemCacheSession
36
41
 
@@ -53,7 +58,7 @@ module Merb
53
58
  # Gets the existing session based on the <tt>session_id</tt> available in cookies.
54
59
  # If none is found, generates a new session.
55
60
  def persist(session_id)
56
- if session_id
61
+ unless session_id.blank?
57
62
  session = ::Cache.get("session:#{session_id}")
58
63
  if session.nil?
59
64
  # Not in memcached, but assume that cookie exists
@@ -63,7 +68,15 @@ module Merb
63
68
  # No cookie...make a new session_id
64
69
  session = generate
65
70
  end
66
- [session, session.session_id]
71
+ if session.is_a?( MemCacheSession )
72
+ [session, session.session_id]
73
+ else
74
+ # recreate using the rails session as the data
75
+ session_object = MemCacheSession.new(session_id)
76
+ session_object.data = session
77
+ [session_object, session_object.session_id]
78
+ end
79
+
67
80
  end
68
81
 
69
82
  # Don't try to reload in dev mode.
@@ -4,16 +4,19 @@ module Merb
4
4
 
5
5
  def setup_session
6
6
  MERB_LOGGER.info("Setting up session")
7
- before = @_cookies[_session_id_key]
8
- @_session , @_cookies[_session_id_key] = Merb::MemorySession.persist(@_cookies[_session_id_key])
9
- @_new_cookie = @_cookies[_session_id_key] != before
7
+ before = cookies[_session_id_key]
8
+ request.session , cookies[_session_id_key] = Merb::MemorySession.persist(cookies[_session_id_key])
9
+ @_new_cookie = cookies[_session_id_key] != before
10
10
  end
11
11
 
12
12
  def finalize_session
13
13
  MERB_LOGGER.info("Finalize session")
14
- set_cookie(_session_id_key, @_session.session_id, _session_expiry) if (@_new_cookie || @_session.needs_new_cookie)
15
- end
16
-
14
+ set_cookie(_session_id_key, request.session.session_id, _session_expiry) if (@_new_cookie || request.session.needs_new_cookie)
15
+ end
16
+
17
+ def session_store_type
18
+ "memory"
19
+ end
17
20
  end
18
21
 
19
22
  class MemorySession
@@ -38,7 +41,7 @@ module Merb
38
41
  # If none is found, generates a new session.
39
42
  def persist(session_id)
40
43
  if session_id
41
- session = session = MemorySessionContainer[session_id]
44
+ session = MemorySessionContainer[session_id]
42
45
  end
43
46
  unless session
44
47
  session = generate
@@ -87,12 +90,11 @@ module Merb
87
90
  class MemorySessionContainer
88
91
  class << self
89
92
 
90
- def setup(opts={})
91
- @opts = opts
93
+ def setup(ttl=nil)
92
94
  @sessions = Hash.new
93
95
  @timestamps = Hash.new
94
96
  @mutex = Mutex.new
95
- @session_ttl = opts.fetch(:session_ttl, 60*60) # default 1 hour
97
+ @session_ttl = ttl || 60*60 # default 1 hour
96
98
  start_timer
97
99
  self
98
100
  end
@@ -148,4 +150,6 @@ module Merb
148
150
  end # end singleton class
149
151
 
150
152
  end # end MemorySessionContainer
151
- end
153
+ end
154
+
155
+ Merb::MemorySessionContainer.setup(Merb::Server.config[:memory_session_ttl])
@@ -1,10 +1,37 @@
1
1
  module Merb
2
2
  module Template
3
- # TODO : pull up common methods from template engines.
4
- end
5
- end
6
-
7
- template = __DIR__+'/merb/template'
8
-
9
- %w[ erubis markaby xml_builder haml
10
- ].each {|fn| require File.join(template, fn)}
3
+ autoload :Erubis, 'merb/template/erubis'
4
+ autoload :Haml, 'merb/template/haml'
5
+ autoload :Markaby, 'merb/template/markaby'
6
+ autoload :XMLBuilder, 'merb/template/xml_builder'
7
+
8
+ EXTENSIONS = {} unless defined?(EXTENSIONS)
9
+
10
+ # lookup the template_extensions for the extname of the filename
11
+ # you pass. Answers with the engine that matches the extension
12
+ def self.engine_for(file)
13
+ engine_for_extension(File.extname(file)[1..-1])
14
+ end
15
+
16
+ def self.engine_for_extension(ext)
17
+ const_get EXTENSIONS[ext]
18
+ end
19
+
20
+ def self.register_extensions(engine,extensions)
21
+ raise ArgumentError unless engine.is_a?(Symbol) && extensions.is_a?(Array)
22
+ extensions.each{ |ext| EXTENSIONS[ext] = engine }
23
+ end
24
+
25
+ # Register the default extensions. They must be here
26
+ # since the template engines will not be loaded until they
27
+ # are directly referenced, or a file with their extension is found.
28
+ # If these are declared inside the template engine then
29
+ # they will never be found :(
30
+ register_extensions( :Erubis, %w[erb herb jerb rhtml])
31
+ register_extensions( :Haml, %w[haml])
32
+ register_extensions( :Markaby, %w[mab])
33
+ register_extensions( :XMLBuilder, %w[builder rxml xerb])
34
+
35
+ end
36
+
37
+ end
@@ -1,10 +1,13 @@
1
1
  module Merb # :nodoc:
2
2
  module Template # :nodoc:
3
3
 
4
+ class ErubisViewContext < ViewContext
5
+ include ::Merb::ErubisCaptureMixin
6
+ end
7
+
4
8
  # Module to allow you to use Embedded Ruby templates through Erubis["http://www.kuwata-lab.com/erubis/"].
5
9
  # Your template must end in .herb (HTML and ERb), .jerb (JavaScript ERb), .erb (Embedded Ruby), or .rhtml (Ruby HTML) for Merb to use it.
6
10
  module Erubis
7
- ::Merb::AbstractController.register_engine self, %w[ herb jerb erb rhtml html.erb js.erb ]
8
11
  class << self
9
12
 
10
13
  @@erbs = {}
@@ -21,24 +24,27 @@ module Merb # :nodoc:
21
24
  # by calling <tt>new_eruby_obj</tt>, which will compile the template and return an Erubis
22
25
  # object holding the parsed template.
23
26
  def transform(options = {})
24
- opts, file, view_context = options.values_at(:opts, :file, :view_context)
25
- eruby = new_eruby_obj(file)
26
- view_context.extend(::Merb::ErubisCaptureMixin)
27
+ opts, text, file, view_context = options.values_at(:opts, :text, :file, :view_context)
28
+ eruby = text ? ::Erubis::MEruby.new(text) : new_eruby_obj(file)
27
29
  eruby.evaluate(view_context)
28
30
  end
29
31
 
32
+ def view_context_klass
33
+ ErubisViewContext
34
+ end
35
+
30
36
  # Creates a new Erubis object to parse the template given in +path+.
31
37
  def new_eruby_obj(path)
32
38
  if @@erbs[path] && !cache_template?(path)
33
39
  return @@erbs[path]
34
40
  else
35
41
  begin
36
- returning ::Erubis::MEruby.new(IO.read(path)) do |eruby|
37
- eruby.init_evaluator :filename => path
38
- if cache_template?(path)
39
- @@erbs[path], @@mtimes[path] = eruby, Time.now
40
- end
41
- end
42
+ eruby = ::Erubis::MEruby.new(IO.read(path))
43
+ eruby.init_evaluator :filename => path
44
+ if cache_template?(path)
45
+ @@erbs[path], @@mtimes[path] = eruby, Time.now
46
+ end
47
+ eruby
42
48
  rescue Errno::ENOENT
43
49
  raise "No template found at path: #{path}"
44
50
  end
@@ -1,18 +1,27 @@
1
-
2
-
3
1
  begin
4
2
  require 'haml/engine'
5
3
  rescue LoadError
6
4
  puts "you must install the haml gem to use .haml templates"
7
5
  end
6
+ require File.join( File.dirname(__FILE__), "..", "template")
8
7
 
8
+ module Haml
9
+ module Helpers
10
+
11
+ def _buffer( binding )
12
+ @_buffer ||= eval( "_erbout", binding )
13
+ end
14
+
15
+ alias_method :capture, :capture_haml
16
+
17
+ end
18
+ end
9
19
 
10
20
  module Merb
11
21
  module Template
12
- module Haml
13
-
14
- ::Merb::AbstractController.register_engine self, %w[ haml ]
15
22
 
23
+ module Haml
24
+
16
25
  class << self
17
26
 
18
27
  @@hamls ||= {}
@@ -23,23 +32,27 @@ module Merb
23
32
  end
24
33
 
25
34
  def transform(options = {})
26
- opts, file, view_context = options.values_at(:opts, :file, :view_context)
35
+ opts, text, file, view_context = options.values_at(:opts, :text, :file, :view_context)
27
36
 
28
- begin
29
- locals_code = build_locals(opts[:locals])
30
- opts[:locals] = {}
31
-
32
- template = load_template(file)
33
-
34
- haml = ::Haml::Engine.new("#{locals_code}#{template}", opts)
35
- haml.to_html(view_context)
36
- rescue
37
- # ::Haml::Engine often inserts a bogus "(haml):#{line_number}" entry in the backtrace.
38
- # Let's replace it with the path of the actual template
39
- $@[0].sub! /\(haml\)/, file
40
- raise # Raise the exception again
37
+ begin
38
+ locals_code = build_locals(opts[:locals])
39
+ opts[:locals] = {}
40
+
41
+ template = text ? text : load_template(file)
42
+
43
+ haml = ::Haml::Engine.new("#{locals_code}#{template}", opts)
44
+ haml.to_html(view_context)
45
+ rescue
46
+ # ::Haml::Engine often inserts a bogus "(haml):#{line_number}" entry in the backtrace.
47
+ # Let's replace it with the path of the actual template
48
+ $@[0].sub! /\(haml\)/, file
49
+ raise # Raise the exception again
41
50
  end
42
51
  end
52
+
53
+ def view_context_klass
54
+ ::Merb::ViewContext
55
+ end
43
56
 
44
57
  private
45
58
  def load_template(file)
@@ -57,7 +70,7 @@ module Merb
57
70
 
58
71
  def build_locals(locals)
59
72
  locals_code = ""
60
- if locals
73
+ if locals
61
74
  locals.keys.each do |key|
62
75
  locals_code << "- #{key} = @_merb_partial_locals[:#{key}]\n"
63
76
  end