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.
- 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/merb_yaml_store.rb
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
require 'yaml/store'
|
|
2
|
-
|
|
3
|
-
module Merb
|
|
4
|
-
# thanks to Michael Fellinger from Ramaze
|
|
5
|
-
class SimpleModel
|
|
6
|
-
attr_accessor :db
|
|
7
|
-
|
|
8
|
-
def initialize(filename = "#{DIST_ROOT}/schema/db.yaml")
|
|
9
|
-
FileUtils.touch(filename)
|
|
10
|
-
@db = YAML::Store.new(filename)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def method_missing(meth, *args, &block)
|
|
14
|
-
@db.transaction do
|
|
15
|
-
@db.send(meth, *args, &block)
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def [](key)
|
|
20
|
-
@db.transaction do
|
|
21
|
-
@db[key]
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def []=(key, value)
|
|
26
|
-
@db.transaction do
|
|
27
|
-
@db[key] = value
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
module Merb
|
|
2
|
-
|
|
3
|
-
module RenderMixin
|
|
4
|
-
|
|
5
|
-
def self.included(base)
|
|
6
|
-
base.class_eval {
|
|
7
|
-
class_inheritable_accessor :_template_root,
|
|
8
|
-
:_layout
|
|
9
|
-
|
|
10
|
-
@@template_extensions = { }
|
|
11
|
-
self._layout = :application
|
|
12
|
-
self._template_root = File.expand_path(MERB_VIEW_ROOT)
|
|
13
|
-
# This method is called by templating-engines to register themselves with
|
|
14
|
-
# a list of extensions that will be looked up on #render of an action.
|
|
15
|
-
def self.register_engine(engine, *extensions)
|
|
16
|
-
[extensions].flatten.uniq.each do |ext|
|
|
17
|
-
@@template_extensions[ext] = engine
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# universal render method. Template handlers are registered
|
|
25
|
-
# by template extension. So you can use the same render method
|
|
26
|
-
# for any kind of template that implements an adapter module.
|
|
27
|
-
# out of the box Merb support Erubis, Haml, Markaby and Builder templates
|
|
28
|
-
#
|
|
29
|
-
# Erubis template ext: .herb .jerb .erb
|
|
30
|
-
# Markaby template ext: .mab
|
|
31
|
-
# Builder template ext: .rxml .builder .xerb
|
|
32
|
-
# Haml template ext: .haml
|
|
33
|
-
#
|
|
34
|
-
# Examples:
|
|
35
|
-
#
|
|
36
|
-
# render
|
|
37
|
-
#
|
|
38
|
-
# Looks for views/controllername/actionname.* and renders
|
|
39
|
-
# the template with the proper engine based on its file extension.
|
|
40
|
-
#
|
|
41
|
-
# render :layout => :none
|
|
42
|
-
#
|
|
43
|
-
# Renders the current template with no layout. XMl Builder templates
|
|
44
|
-
# are exempt from layout by default.
|
|
45
|
-
#
|
|
46
|
-
# render :action => 'foo'
|
|
47
|
-
#
|
|
48
|
-
# Renders views/controllername/foo.*
|
|
49
|
-
#
|
|
50
|
-
# render :nothing => 200
|
|
51
|
-
#
|
|
52
|
-
# Renders nothing with a status of 200
|
|
53
|
-
#
|
|
54
|
-
# render :template => 'shared/message'
|
|
55
|
-
#
|
|
56
|
-
# Renders views/shared/message
|
|
57
|
-
#
|
|
58
|
-
# render :js => "$('some-div').toggle();"
|
|
59
|
-
#
|
|
60
|
-
# If the right hand side of :js => is a string then the proper
|
|
61
|
-
# javascript headers will be set and the string will be returned
|
|
62
|
-
# verbatim as js.
|
|
63
|
-
#
|
|
64
|
-
# render :js => :spinner
|
|
65
|
-
#
|
|
66
|
-
# When the rhs of :js => is a Symbol, it will be used as the
|
|
67
|
-
# action/template name so: views/controllername/spinner.jerb
|
|
68
|
-
# will be rendered as javascript
|
|
69
|
-
#
|
|
70
|
-
# render :js => true
|
|
71
|
-
#
|
|
72
|
-
# This will just look for the current controller/action template
|
|
73
|
-
# with the .jerb extension and render it as javascript
|
|
74
|
-
#
|
|
75
|
-
# XML can be rendered with the same options as Javascript.
|
|
76
|
-
#
|
|
77
|
-
# render :xml => @posts.to_xml
|
|
78
|
-
# render :xml => "<foo><bar>Hi!</bar></foo>"
|
|
79
|
-
#
|
|
80
|
-
# This will set the appropriate xml headers and render the rhs
|
|
81
|
-
# of :xml => as a string. SO you can pass any xml string to this
|
|
82
|
-
# to be rendered.
|
|
83
|
-
#
|
|
84
|
-
# render :xml => :hello
|
|
85
|
-
#
|
|
86
|
-
# Renders the hello.xrb template for the current controller.
|
|
87
|
-
#
|
|
88
|
-
# render :xml => true
|
|
89
|
-
# render :xml => true, :action => "buffalo"
|
|
90
|
-
#
|
|
91
|
-
# Renders the buffalo.xerb template for the current controller.
|
|
92
|
-
#
|
|
93
|
-
def render(opts={}, &blk)
|
|
94
|
-
|
|
95
|
-
action = if kind_of?(Merb::ControllerExceptions::Base)
|
|
96
|
-
self.class.name.snake_case.split('::').last
|
|
97
|
-
else
|
|
98
|
-
opts[:action] || params[:action]
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
opts[:layout] ||= _layout
|
|
102
|
-
|
|
103
|
-
case
|
|
104
|
-
when status = opts[:nothing]
|
|
105
|
-
return render_nothing(status)
|
|
106
|
-
when partial = opts[:partial]
|
|
107
|
-
template = find_partial(partial, opts)
|
|
108
|
-
opts[:layout] = :none
|
|
109
|
-
|
|
110
|
-
# Add an instance variable that can be used to create the locals in the
|
|
111
|
-
# partial
|
|
112
|
-
if opts[:locals]
|
|
113
|
-
@_merb_partial_locals = opts[:locals]
|
|
114
|
-
end
|
|
115
|
-
opts[:clean_context] = true
|
|
116
|
-
when js = opts[:js]
|
|
117
|
-
headers['Content-Type'] = "text/javascript"
|
|
118
|
-
opts[:layout] = :none
|
|
119
|
-
case js
|
|
120
|
-
when String
|
|
121
|
-
return js
|
|
122
|
-
when Symbol
|
|
123
|
-
template = find_template(:action => js, :ext => 'jerb')
|
|
124
|
-
else
|
|
125
|
-
template = find_template(:action => action, :ext => 'jerb')
|
|
126
|
-
end
|
|
127
|
-
when xml = opts[:xml]
|
|
128
|
-
headers['Content-Type'] = 'application/xml'
|
|
129
|
-
headers['Encoding'] = 'UTF-8'
|
|
130
|
-
# TODO This is the same as the js logic above. Can it be refactored?
|
|
131
|
-
case xml
|
|
132
|
-
when String
|
|
133
|
-
return xml
|
|
134
|
-
when Symbol
|
|
135
|
-
template = find_template(:action => xml, :ext => 'rxml,xerb,builder')
|
|
136
|
-
else
|
|
137
|
-
template = find_template(:action => action, :ext => 'rxml,xerb,builder')
|
|
138
|
-
end
|
|
139
|
-
when template = opts[:template]
|
|
140
|
-
template = find_template(:template => template)
|
|
141
|
-
else
|
|
142
|
-
template = find_template(:action => action)
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
engine = engine_for(template)
|
|
146
|
-
options = {
|
|
147
|
-
:file => template,
|
|
148
|
-
:view_context => (opts[:clean_context] ? clean_view_context : cached_view_context),
|
|
149
|
-
:opts => opts
|
|
150
|
-
}
|
|
151
|
-
content = engine.transform(options)
|
|
152
|
-
if engine.exempt_from_layout? || opts[:layout] == :none
|
|
153
|
-
content
|
|
154
|
-
else
|
|
155
|
-
wrap_layout(content, opts)
|
|
156
|
-
end
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
# does a render with no layout. Also sets the
|
|
162
|
-
# content type header to text/javascript. Use
|
|
163
|
-
# this when you want to render a template with
|
|
164
|
-
# .jerb extension.
|
|
165
|
-
def render_js(template=nil)
|
|
166
|
-
render :js => true, :action => (template || params[:action])
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
# renders nothing but sets the status, defaults
|
|
170
|
-
# to 200. does send one ' ' space char, this is for
|
|
171
|
-
# safari and flash uploaders to work.
|
|
172
|
-
def render_nothing(status=200)
|
|
173
|
-
@_status = status
|
|
174
|
-
return " "
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
def set_status(status)
|
|
178
|
-
@_status = status
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
def render_no_layout(opts={})
|
|
182
|
-
render opts.update({:layout => :none})
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
# This is merb's partial render method. You name your
|
|
186
|
-
# partials _partialname.* , and then call it like
|
|
187
|
-
# partial(:partialname). If there is no '/' character
|
|
188
|
-
# in the argument passed in it will look for the partial
|
|
189
|
-
# in the view directory that corresponds to the current
|
|
190
|
-
# controller name. If you pass a string with a path in it
|
|
191
|
-
# you can render partials in other view directories. So
|
|
192
|
-
# if you create a views/shared directory then you can call
|
|
193
|
-
# partials that live there like partial('shared/foo')
|
|
194
|
-
def partial(template, locals={})
|
|
195
|
-
render :partial => template, :locals => locals
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
# +catch_content+ catches the thrown content from another template
|
|
199
|
-
# So when you throw_content(:foo) {...} you can catch_content :foo
|
|
200
|
-
# in another view or the layout.
|
|
201
|
-
def catch_content(name)
|
|
202
|
-
cached_view_context.instance_variable_get("@_#{name}_content")
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
private
|
|
206
|
-
|
|
207
|
-
# this returns a ViewContext object populated with all
|
|
208
|
-
# the instance variables in your controller. This is used
|
|
209
|
-
# as the view context object for the Erubis templates.
|
|
210
|
-
def cached_view_context
|
|
211
|
-
@_view_context_cache ||= ViewContext.new(self)
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
def clean_view_context
|
|
215
|
-
ViewContext.new(self)
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
def wrap_layout(content, opts={})
|
|
219
|
-
if opts[:layout] != :application
|
|
220
|
-
layout_choice = find_template(:layout => opts[:layout])
|
|
221
|
-
else
|
|
222
|
-
if name = find_template(:layout => self.class.name.snake_case.split('::').join('/'))
|
|
223
|
-
layout_choice = name
|
|
224
|
-
else
|
|
225
|
-
layout_choice = find_template(:layout => :application)
|
|
226
|
-
end
|
|
227
|
-
end
|
|
228
|
-
|
|
229
|
-
cached_view_context.instance_variable_set('@_layout_content', content)
|
|
230
|
-
engine = engine_for(layout_choice)
|
|
231
|
-
options = {
|
|
232
|
-
:file => layout_choice,
|
|
233
|
-
:view_context => cached_view_context,
|
|
234
|
-
:opts => opts
|
|
235
|
-
}
|
|
236
|
-
engine.transform(options)
|
|
237
|
-
end
|
|
238
|
-
|
|
239
|
-
# OPTIMIZE : combine find_template and find_partial ?
|
|
240
|
-
def find_template(opts={})
|
|
241
|
-
if template = opts[:template]
|
|
242
|
-
path = _template_root / template
|
|
243
|
-
elsif opts[:action] and kind_of?(Merb::ControllerExceptions::Base)
|
|
244
|
-
path = _template_root / 'exceptions' / opts[:action]
|
|
245
|
-
elsif action = opts[:action]
|
|
246
|
-
segment = self.class.name.snake_case.split('::').join('/')
|
|
247
|
-
path = _template_root / segment / action
|
|
248
|
-
elsif _layout = opts[:layout]
|
|
249
|
-
path = _template_root / 'layout' / _layout
|
|
250
|
-
else
|
|
251
|
-
raise "called find_template without an :action or :layout"
|
|
252
|
-
end
|
|
253
|
-
extensions = [@@template_extensions.keys].flatten.uniq
|
|
254
|
-
glob = "#{path}.{#{opts[:ext] || extensions.join(',')}}"
|
|
255
|
-
Dir[glob].first
|
|
256
|
-
end
|
|
257
|
-
|
|
258
|
-
def find_partial(template, opts={})
|
|
259
|
-
if template =~ /\//
|
|
260
|
-
t = template.split('/')
|
|
261
|
-
template = t.pop
|
|
262
|
-
path = _template_root / t.join('/') / "_#{template}"
|
|
263
|
-
else
|
|
264
|
-
segment = self.class.name.snake_case.split('::').join('/')
|
|
265
|
-
path = _template_root / segment / "_#{template}"
|
|
266
|
-
end
|
|
267
|
-
extensions = [@@template_extensions.keys].flatten.uniq
|
|
268
|
-
glob = "#{path}.{#{opts[:ext] || extensions.join(',')}}"
|
|
269
|
-
Dir[glob].first
|
|
270
|
-
end
|
|
271
|
-
|
|
272
|
-
# lookup the template_extensions for the extname of the filename
|
|
273
|
-
# you pass. Answers with the engine that matches the extension, Template::Erubis
|
|
274
|
-
# is used if none matches.
|
|
275
|
-
def engine_for(file)
|
|
276
|
-
extension = File.extname(file)[1..-1]
|
|
277
|
-
@@template_extensions[extension]
|
|
278
|
-
rescue
|
|
279
|
-
::Merb::Template::Erubis
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
end
|
|
283
|
-
end
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
require 'enumerator'
|
|
2
|
-
|
|
3
|
-
module Merb
|
|
4
|
-
# use this in your controllers to switch output based on
|
|
5
|
-
# the HTTP_ACCEPT header. like so:
|
|
6
|
-
# respond_to do |type|
|
|
7
|
-
# type.js { render_js }
|
|
8
|
-
# type.html { render }
|
|
9
|
-
# type.xml { @foo.to_xml }
|
|
10
|
-
# type.yaml { @foo.to_yaml }
|
|
11
|
-
# end
|
|
12
|
-
module ResponderMixin
|
|
13
|
-
|
|
14
|
-
def respond_to(&block)
|
|
15
|
-
responder = Rest::Responder.new(request.env['HTTP_ACCEPT'], params)
|
|
16
|
-
block.call(responder)
|
|
17
|
-
responder.respond(headers)
|
|
18
|
-
@_status = responder.status if responder.status
|
|
19
|
-
responder.body
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
module Rest
|
|
23
|
-
|
|
24
|
-
TYPES = {
|
|
25
|
-
:all => %w[*/*],
|
|
26
|
-
:yaml => %w[application/x-yaml text/yaml],
|
|
27
|
-
:text => %w[text/plain],
|
|
28
|
-
:html => %w[text/html application/xhtml+xml application/html],
|
|
29
|
-
:xml => %w[application/xml text/xml application/x-xml],
|
|
30
|
-
:js => %w[application/json text/x-json text/javascript application/javascript application/x-javascript]
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
class Responder
|
|
34
|
-
|
|
35
|
-
attr_reader :body, :type, :status
|
|
36
|
-
|
|
37
|
-
def initialize(accept_header, params={})
|
|
38
|
-
MERB_LOGGER.info accept_header
|
|
39
|
-
@accepts = Responder.parse(accept_header)
|
|
40
|
-
@params = params
|
|
41
|
-
@stack = {}
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def method_missing(symbol, &block)
|
|
45
|
-
raise "respond_to expects a block" unless block_given?
|
|
46
|
-
# the first method we encounter here will be used for the catch all mime-type */*
|
|
47
|
-
@stack[:all] = block unless @stack[:all]
|
|
48
|
-
@stack[symbol] = block
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def respond(headers)
|
|
52
|
-
unless @stack.keys.all?{|k| TYPES.has_key?(k) }
|
|
53
|
-
raise "unrecognized mime type in respond_to block"
|
|
54
|
-
end
|
|
55
|
-
mime_type = negotiate_content
|
|
56
|
-
if mime_type
|
|
57
|
-
headers['Content-Type'] = mime_type.super_range
|
|
58
|
-
@body = @stack[mime_type.to_sym].call
|
|
59
|
-
else
|
|
60
|
-
raise ControllerExceptions::NotAcceptable
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
protected
|
|
65
|
-
|
|
66
|
-
def self.parse(accept_header)
|
|
67
|
-
# parse the raw accept header into a unique, sorted array of AcceptType objects
|
|
68
|
-
returning( accept_header.split(/,/).enum_for(:each_with_index).map do |entry,index|
|
|
69
|
-
AcceptType.new(entry,index += 1)
|
|
70
|
-
end.sort.uniq ) do |list|
|
|
71
|
-
# firefox (and possibly other browsers) send broken default accept headers.
|
|
72
|
-
# fix them up by sorting alternate xml forms (namely application/xhtml+xml)
|
|
73
|
-
# ahead of pure xml types (application/xml,text/xml).
|
|
74
|
-
if app_xml = list.detect{|e| e.super_range == 'application/xml'}
|
|
75
|
-
list.select{|e| e.to_s =~ /\+xml/}.each { |acc_type|
|
|
76
|
-
list[list.index(acc_type)],list[list.index(app_xml)] =
|
|
77
|
-
list[list.index(app_xml)],list[list.index(acc_type)] }
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
private
|
|
83
|
-
|
|
84
|
-
def negotiate_content
|
|
85
|
-
if @params[:format]
|
|
86
|
-
negotiate_by_format
|
|
87
|
-
elsif (@stack.keys & @accepts.map(&:to_sym)).size > 0
|
|
88
|
-
negotiate_by_accept_header
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def negotiate_by_format
|
|
93
|
-
format = @params[:format].to_sym
|
|
94
|
-
if @stack[format]
|
|
95
|
-
if @accepts.map(&:to_sym).include?(format)
|
|
96
|
-
@accepts.detect{|a| a.to_sym == format }
|
|
97
|
-
else
|
|
98
|
-
AcceptType.new(TYPES[format].first,0)
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def negotiate_by_accept_header
|
|
104
|
-
@accepts.each do |accept|
|
|
105
|
-
return accept if @stack[accept.to_sym] || accept.to_sym == :all
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
class AcceptType
|
|
112
|
-
|
|
113
|
-
attr_reader :media_range, :quality, :index, :type, :sub_type
|
|
114
|
-
|
|
115
|
-
def initialize(entry,index)
|
|
116
|
-
@index = index
|
|
117
|
-
@media_range, quality = entry.split(/;\s*q=/).map(&:strip)
|
|
118
|
-
@type, @sub_type = @media_range.split(/\//)
|
|
119
|
-
quality ||= 0.0 if @media_range == '*/*'
|
|
120
|
-
@quality = ((quality || 1.0).to_f * 100).to_i
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
def <=>(entry)
|
|
124
|
-
returning((entry.quality <=> quality).to_s) do |c|
|
|
125
|
-
c.replace((index <=> entry.index).to_s) if c == '0'
|
|
126
|
-
end.to_i
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
def eql?(entry)
|
|
130
|
-
synonyms.include?(entry.media_range)
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
def ==(entry); eql?(entry); end
|
|
134
|
-
|
|
135
|
-
def hash; super_range.hash; end
|
|
136
|
-
|
|
137
|
-
def synonyms
|
|
138
|
-
TYPES.values.select{|e| e.include?(@media_range)}.flatten
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
def super_range
|
|
142
|
-
synonyms.first || @media_range
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
def to_sym
|
|
146
|
-
TYPES.select{|k,v| v == synonyms }.flatten.first
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
def to_s
|
|
150
|
-
@media_range
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
end
|