merb 0.3.7 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +25 -26
- data/Rakefile +48 -36
- data/app_generators/merb/USAGE +5 -0
- data/app_generators/merb/merb_generator.rb +107 -0
- data/app_generators/merb/templates/Rakefile +99 -0
- data/{examples/skeleton/dist → app_generators/merb/templates}/app/controllers/application.rb +1 -1
- data/app_generators/merb/templates/app/controllers/exceptions.rb +13 -0
- data/{examples/skeleton/dist → app_generators/merb/templates}/app/helpers/global_helper.rb +0 -0
- data/{examples/skeleton/dist/app/mailers → app_generators/merb/templates/app/mailers/views}/layout/application.erb +0 -0
- data/app_generators/merb/templates/app/views/exceptions/internal_server_error.html.erb +207 -0
- data/app_generators/merb/templates/app/views/exceptions/not_acceptable.html.erb +38 -0
- data/app_generators/merb/templates/app/views/exceptions/not_found.html.erb +40 -0
- data/app_generators/merb/templates/app/views/layout/application.html.erb +11 -0
- data/app_generators/merb/templates/config/boot.rb +11 -0
- data/app_generators/merb/templates/config/dependencies.rb +41 -0
- data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/development.rb +0 -0
- data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/production.rb +0 -0
- data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/test.rb +0 -0
- data/app_generators/merb/templates/config/merb.yml +64 -0
- data/app_generators/merb/templates/config/merb_init.rb +16 -0
- data/app_generators/merb/templates/config/plugins.yml +1 -0
- data/app_generators/merb/templates/config/router.rb +32 -0
- data/{lib/merb/core_ext/merb_array.rb → app_generators/merb/templates/config/upload.conf} +0 -0
- data/app_generators/merb/templates/public/images/merb.jpg +0 -0
- data/app_generators/merb/templates/public/merb.fcgi +6 -0
- data/app_generators/merb/templates/public/stylesheets/master.css +119 -0
- data/app_generators/merb/templates/script/destroy +28 -0
- data/app_generators/merb/templates/script/generate +28 -0
- data/{examples/skeleton → app_generators/merb/templates}/script/stop_merb +0 -0
- data/app_generators/merb/templates/script/win_script.cmd +1 -0
- data/app_generators/merb/templates/spec/spec.opts +6 -0
- data/app_generators/merb/templates/spec/spec_helper.rb +10 -0
- data/app_generators/merb/templates/test/test_helper.rb +13 -0
- data/app_generators/merb_plugin/USAGE +5 -0
- data/app_generators/merb_plugin/merb_plugin_generator.rb +64 -0
- data/app_generators/merb_plugin/templates/LICENSE +20 -0
- data/app_generators/merb_plugin/templates/README +4 -0
- data/app_generators/merb_plugin/templates/Rakefile +35 -0
- data/app_generators/merb_plugin/templates/TODO +5 -0
- data/app_generators/merb_plugin/templates/merbtasks.rb +6 -0
- data/app_generators/merb_plugin/templates/sampleplugin.rb +10 -0
- data/app_generators/merb_plugin/templates/sampleplugin_spec.rb +7 -0
- data/app_generators/merb_plugin/templates/spec_helper.rb +2 -0
- data/bin/merb +1 -1
- data/lib/autotest/discover.rb +3 -0
- data/lib/autotest/merb_rspec.rb +79 -0
- data/lib/merb.rb +72 -93
- data/lib/merb/{merb_abstract_controller.rb → abstract_controller.rb} +28 -5
- data/lib/merb/caching/action_cache.rb +65 -29
- data/lib/merb/caching/fragment_cache.rb +9 -4
- data/lib/merb/caching/store/file_cache.rb +22 -14
- data/lib/merb/caching/store/memory_cache.rb +26 -8
- data/lib/merb/{merb_constants.rb → constants.rb} +9 -7
- data/lib/merb/controller.rb +178 -0
- data/lib/merb/core_ext.rb +13 -11
- data/lib/merb/core_ext/array.rb +0 -0
- data/lib/merb/core_ext/{merb_class.rb → class.rb} +0 -0
- data/lib/merb/core_ext/{merb_enumerable.rb → enumerable.rb} +0 -0
- data/lib/merb/core_ext/get_args.rb +52 -0
- data/lib/merb/core_ext/{merb_hash.rb → hash.rb} +40 -11
- data/lib/merb/core_ext/{merb_inflections.rb → inflections.rb} +0 -0
- data/lib/merb/core_ext/{merb_inflector.rb → inflector.rb} +1 -1
- data/lib/merb/core_ext/{merb_kernel.rb → kernel.rb} +56 -3
- data/lib/merb/core_ext/mash.rb +88 -0
- data/lib/merb/core_ext/{merb_module.rb → module.rb} +0 -0
- data/lib/merb/core_ext/{merb_numeric.rb → numeric.rb} +0 -0
- data/lib/merb/core_ext/{merb_object.rb → object.rb} +10 -47
- data/lib/merb/core_ext/string.rb +56 -0
- data/lib/merb/core_ext/{merb_symbol.rb → symbol.rb} +0 -0
- data/lib/merb/dispatcher.rb +109 -0
- data/lib/merb/{merb_drb_server.rb → drb_server.rb} +0 -0
- data/lib/merb/erubis_ext.rb +10 -0
- data/lib/merb/exceptions.rb +173 -0
- data/lib/merb/generators/merb_app/merb_app.rb +5 -25
- data/lib/merb/generators/merb_generator_helpers.rb +317 -0
- data/lib/merb/generators/merb_plugin.rb +19 -0
- data/lib/merb/logger.rb +65 -0
- data/lib/merb/{merb_mail_controller.rb → mail_controller.rb} +102 -49
- data/lib/merb/{merb_mailer.rb → mailer.rb} +31 -27
- data/lib/merb/mixins/{basic_authentication_mixin.rb → basic_authentication.rb} +3 -3
- data/lib/merb/mixins/{controller_mixin.rb → controller.rb} +131 -112
- data/lib/merb/mixins/{erubis_capture_mixin.rb → erubis_capture.rb} +12 -21
- data/lib/merb/mixins/{form_control_mixin.rb → form_control.rb} +6 -12
- data/lib/merb/mixins/render.rb +401 -0
- data/lib/merb/mixins/responder.rb +378 -0
- data/lib/merb/mixins/{view_context_mixin.rb → view_context.rb} +65 -10
- data/lib/merb/mixins/web_controller.rb +29 -0
- data/lib/merb/{merb_handler.rb → mongrel_handler.rb} +59 -38
- data/lib/merb/part_controller.rb +19 -0
- data/lib/merb/plugins.rb +16 -0
- data/lib/merb/rack_adapter.rb +37 -0
- data/lib/merb/request.rb +421 -0
- data/lib/merb/router.rb +576 -0
- data/lib/merb/{merb_server.rb → server.rb} +275 -71
- data/lib/merb/session.rb +10 -10
- data/lib/merb/session/cookie_store.rb +125 -0
- data/lib/merb/session/{merb_mem_cache_session.rb → mem_cache_session.rb} +22 -9
- data/lib/merb/session/{merb_memory_session.rb → memory_session.rb} +15 -11
- data/lib/merb/template.rb +35 -8
- data/lib/merb/template/erubis.rb +16 -10
- data/lib/merb/template/haml.rb +33 -20
- data/lib/merb/template/markaby.rb +16 -14
- data/lib/merb/template/xml_builder.rb +8 -4
- data/lib/merb/test/{merb_fake_request.rb → fake_request.rb} +11 -5
- data/lib/merb/test/helper.rb +31 -0
- data/lib/merb/test/hpricot.rb +136 -0
- data/lib/merb/test/{merb_multipart.rb → multipart.rb} +1 -1
- data/lib/merb/test/rspec.rb +93 -0
- data/lib/merb/{merb_upload_handler.rb → upload_handler.rb} +5 -6
- data/lib/merb/{merb_upload_progress.rb → upload_progress.rb} +1 -1
- data/lib/merb/{merb_view_context.rb → view_context.rb} +27 -42
- data/lib/{merb_tasks.rb → tasks.rb} +0 -0
- data/lib/tasks/merb.rake +21 -11
- data/merb_default_generators/model/USAGE +0 -0
- data/merb_default_generators/model/model_generator.rb +16 -0
- data/merb_default_generators/model/templates/new_model_template.erb +5 -0
- data/merb_default_generators/resource_controller/USAGE +0 -0
- data/merb_default_generators/resource_controller/resource_controller_generator.rb +26 -0
- data/merb_default_generators/resource_controller/templates/controller.rb +30 -0
- data/merb_default_generators/resource_controller/templates/edit.html.erb +1 -0
- data/merb_default_generators/resource_controller/templates/helper.rb +5 -0
- data/merb_default_generators/resource_controller/templates/index.html.erb +1 -0
- data/merb_default_generators/resource_controller/templates/new.html.erb +1 -0
- data/merb_default_generators/resource_controller/templates/show.html.erb +1 -0
- data/merb_generators/controller/USAGE +5 -0
- data/merb_generators/controller/controller_generator.rb +16 -0
- data/merb_generators/controller/templates/controller.rb +8 -0
- data/merb_generators/controller/templates/helper.rb +5 -0
- data/merb_generators/controller/templates/index.html.erb +3 -0
- data/merb_generators/resource/USAGE +0 -0
- data/merb_generators/resource/resource_generator.rb +60 -0
- data/rspec_generators/merb_controller_test/merb_controller_test_generator.rb +67 -0
- data/rspec_generators/merb_controller_test/templates/controller_spec.rb +8 -0
- data/rspec_generators/merb_controller_test/templates/edit_spec.rb +12 -0
- data/rspec_generators/merb_controller_test/templates/helper_spec.rb +5 -0
- data/rspec_generators/merb_controller_test/templates/index_spec.rb +12 -0
- data/rspec_generators/merb_controller_test/templates/new_spec.rb +12 -0
- data/rspec_generators/merb_controller_test/templates/show_spec.rb +5 -0
- data/rspec_generators/merb_model_test/merb_model_test_generator.rb +26 -0
- data/rspec_generators/merb_model_test/templates/model_spec_template.erb +7 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/test_unit_generators/merb_controller_test/merb_controller_test_generator.rb +53 -0
- data/test_unit_generators/merb_controller_test/templates/functional_test.rb +17 -0
- data/test_unit_generators/merb_controller_test/templates/helper_test.rb +9 -0
- data/test_unit_generators/merb_model_test/merb_model_test_generator.rb +29 -0
- data/test_unit_generators/merb_model_test/templates/model_test_unit_template.erb +9 -0
- metadata +172 -94
- data/examples/README_EXAMPLES +0 -10
- data/examples/skeleton/Rakefile +0 -68
- data/examples/skeleton/dist/app/views/layout/application.herb +0 -12
- data/examples/skeleton/dist/conf/database.yml +0 -23
- data/examples/skeleton/dist/conf/merb.yml +0 -57
- data/examples/skeleton/dist/conf/merb_init.rb +0 -24
- data/examples/skeleton/dist/conf/router.rb +0 -22
- data/examples/skeleton/dist/conf/upload.conf +0 -5
- data/examples/skeleton/dist/schema/migrations/001_add_sessions_table.rb +0 -14
- data/examples/skeleton/script/new_migration +0 -21
- data/lib/merb/core_ext/merb_string.rb +0 -18
- data/lib/merb/merb_controller.rb +0 -206
- data/lib/merb/merb_dispatcher.rb +0 -87
- data/lib/merb/merb_exceptions.rb +0 -319
- data/lib/merb/merb_part_controller.rb +0 -42
- data/lib/merb/merb_plugins.rb +0 -293
- data/lib/merb/merb_request.rb +0 -165
- data/lib/merb/merb_router.rb +0 -309
- data/lib/merb/merb_yaml_store.rb +0 -31
- data/lib/merb/mixins/render_mixin.rb +0 -283
- data/lib/merb/mixins/responder_mixin.rb +0 -159
- data/lib/merb/session/merb_ar_session.rb +0 -131
- data/lib/merb/vendor/paginator/README.txt +0 -84
- data/lib/merb/vendor/paginator/paginator.rb +0 -124
- data/lib/tasks/db.rake +0 -55
data/lib/merb/session.rb
CHANGED
@@ -2,16 +2,16 @@ module Merb
|
|
2
2
|
module SessionMixin
|
3
3
|
|
4
4
|
def rand_uuid
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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 =
|
10
|
-
|
11
|
-
@_fingerprint = Marshal.dump(
|
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
|
-
|
18
|
-
|
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 '
|
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
|
-
# :
|
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
|
-
|
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
|
-
|
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 =
|
8
|
-
|
9
|
-
@_new_cookie =
|
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,
|
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 =
|
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(
|
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 =
|
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])
|
data/lib/merb/template.rb
CHANGED
@@ -1,10 +1,37 @@
|
|
1
1
|
module Merb
|
2
2
|
module Template
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
data/lib/merb/template/erubis.rb
CHANGED
@@ -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
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
data/lib/merb/template/haml.rb
CHANGED
@@ -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
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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
|
-
|
73
|
+
if locals
|
61
74
|
locals.keys.each do |key|
|
62
75
|
locals_code << "- #{key} = @_merb_partial_locals[:#{key}]\n"
|
63
76
|
end
|