mojombo-grit 0.8.1 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +7 -0
- data/Manifest.txt +18 -1
- data/grit.gemspec +56 -10
- data/lib/{mojombo-grit.rb → grit.rb} +20 -4
- data/lib/grit/commit.rb +32 -11
- data/lib/grit/commit_stats.rb +104 -0
- data/lib/grit/git-ruby.rb +182 -0
- data/lib/grit/git-ruby/commit_db.rb +52 -0
- data/lib/grit/git-ruby/file_index.rb +186 -0
- data/lib/grit/git-ruby/git_object.rb +344 -0
- data/lib/grit/git-ruby/internal/loose.rb +136 -0
- data/lib/grit/git-ruby/internal/mmap.rb +58 -0
- data/lib/grit/git-ruby/internal/pack.rb +382 -0
- data/lib/grit/git-ruby/internal/raw_object.rb +37 -0
- data/lib/grit/git-ruby/object.rb +319 -0
- data/lib/grit/git-ruby/repository.rb +729 -0
- data/lib/grit/git.rb +33 -15
- data/lib/grit/head.rb +6 -15
- data/lib/grit/index.rb +121 -0
- data/lib/grit/ref.rb +95 -0
- data/lib/grit/repo.rb +95 -6
- data/lib/grit/status.rb +151 -0
- data/lib/grit/tree.rb +3 -2
- data/test/test_blob.rb +5 -0
- data/test/test_commit.rb +7 -5
- data/test/test_diff.rb +1 -1
- data/test/test_git.rb +20 -2
- data/test/test_grit.rb +32 -0
- data/test/test_head.rb +30 -5
- data/test/test_real.rb +8 -6
- data/test/test_remote.rb +14 -0
- data/test/test_repo.rb +86 -79
- data/test/test_tag.rb +2 -6
- data/test/test_tree.rb +5 -0
- metadata +40 -40
- data/test/fixtures/blame +0 -131
- data/test/fixtures/cat_file_blob +0 -1
- data/test/fixtures/cat_file_blob_size +0 -1
- data/test/fixtures/diff_2 +0 -54
- data/test/fixtures/diff_2f +0 -19
- data/test/fixtures/diff_f +0 -15
- data/test/fixtures/diff_i +0 -201
- data/test/fixtures/diff_mode_only +0 -1152
- data/test/fixtures/diff_new_mode +0 -17
- data/test/fixtures/diff_p +0 -610
- data/test/fixtures/for_each_ref +0 -0
- data/test/fixtures/for_each_ref_tags +0 -0
- data/test/fixtures/ls_tree_a +0 -7
- data/test/fixtures/ls_tree_b +0 -2
- data/test/fixtures/ls_tree_commit +0 -3
- data/test/fixtures/rev_list +0 -26
- data/test/fixtures/rev_list_count +0 -655
- data/test/fixtures/rev_list_single +0 -7
- data/test/fixtures/rev_parse +0 -1
- data/test/fixtures/show_empty_commit +0 -6
- data/test/fixtures/simple_config +0 -2
- data/test/helper.rb +0 -17
- data/test/profile.rb +0 -21
- data/test/suite.rb +0 -6
@@ -1,1152 +0,0 @@
|
|
1
|
-
diff --git a/bin/merb b/bin/merb
|
2
|
-
old mode 100644
|
3
|
-
new mode 100755
|
4
|
-
diff --git a/lib/merb.rb b/lib/merb.rb
|
5
|
-
index 76cb3e269e46fdf9b63cda7cb563c6cf40fdcb15..a2ab4ed47f9cb2ab942da5c46a2b561758a0d704 100644
|
6
|
-
--- a/lib/merb.rb
|
7
|
-
+++ b/lib/merb.rb
|
8
|
-
@@ -15,7 +15,7 @@ require 'merb_core/core_ext'
|
9
|
-
require 'merb_core/gem_ext/erubis'
|
10
|
-
require 'merb_core/logger'
|
11
|
-
require 'merb_core/version'
|
12
|
-
-
|
13
|
-
+require 'merb_core/controller/mime'
|
14
|
-
|
15
|
-
module Merb
|
16
|
-
class << self
|
17
|
-
@@ -23,6 +23,7 @@ module Merb
|
18
|
-
def start(argv=ARGV)
|
19
|
-
Merb::Config.parse_args(argv)
|
20
|
-
BootLoader.run
|
21
|
-
+
|
22
|
-
case Merb::Config[:adapter]
|
23
|
-
when "mongrel"
|
24
|
-
adapter = Merb::Rack::Mongrel
|
25
|
-
diff --git a/lib/merb_core/boot/bootloader.rb b/lib/merb_core/boot/bootloader.rb
|
26
|
-
index d873924860bf4da06ac93db5c6a188f63dd1c3cc..57da75f05e28e8a256922bf345ccd3902e0a0b02 100644
|
27
|
-
--- a/lib/merb_core/boot/bootloader.rb
|
28
|
-
+++ b/lib/merb_core/boot/bootloader.rb
|
29
|
-
@@ -20,7 +20,7 @@ module Merb
|
30
|
-
end
|
31
|
-
|
32
|
-
def run
|
33
|
-
- subclasses.each {|klass| Object.full_const_get(klass).new.run }
|
34
|
-
+ subclasses.each {|klass| Object.full_const_get(klass).run }
|
35
|
-
end
|
36
|
-
|
37
|
-
def after(klass)
|
38
|
-
@@ -37,95 +37,128 @@ module Merb
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
-class Merb::BootLoader::BuildFramework < Merb::BootLoader
|
43
|
-
- def run
|
44
|
-
- build_framework
|
45
|
-
+class Merb::BootLoader::LoadInit < Merb::BootLoader
|
46
|
-
+ def self.run
|
47
|
-
+ if Merb::Config[:init_file]
|
48
|
-
+ require Merb.root / Merb::Config[:init_file]
|
49
|
-
+ elsif File.exists?(Merb.root / "config" / "merb_init.rb")
|
50
|
-
+ require Merb.root / "config" / "merb_init"
|
51
|
-
+ elsif File.exists?(Merb.root / "merb_init.rb")
|
52
|
-
+ require Merb.root / "merb_init"
|
53
|
-
+ elsif File.exists?(Merb.root / "application.rb")
|
54
|
-
+ require Merb.root / "application"
|
55
|
-
+ end
|
56
|
-
+ end
|
57
|
-
+end
|
58
|
-
+
|
59
|
-
+class Merb::BootLoader::Environment < Merb::BootLoader
|
60
|
-
+ def self.run
|
61
|
-
+ Merb.environment = Merb::Config[:environment]
|
62
|
-
+ end
|
63
|
-
+end
|
64
|
-
+
|
65
|
-
+class Merb::BootLoader::Logger < Merb::BootLoader
|
66
|
-
+ def self.run
|
67
|
-
+ Merb.logger = Merb::Logger.new(Merb.dir_for(:log) / "test_log")
|
68
|
-
+ Merb.logger.level = Merb::Logger.const_get(Merb::Config[:log_level].upcase) rescue Merb::Logger::INFO
|
69
|
-
end
|
70
|
-
+end
|
71
|
-
+
|
72
|
-
+class Merb::BootLoader::BuildFramework < Merb::BootLoader
|
73
|
-
+ class << self
|
74
|
-
+ def run
|
75
|
-
+ build_framework
|
76
|
-
+ end
|
77
|
-
|
78
|
-
- # This method should be overridden in merb_init.rb before Merb.start to set up a different
|
79
|
-
- # framework structure
|
80
|
-
- def build_framework
|
81
|
-
- %[view model controller helper mailer part].each do |component|
|
82
|
-
- Merb.push_path(component.to_sym, Merb.root_path("app/#{component}s"))
|
83
|
-
+ # This method should be overridden in merb_init.rb before Merb.start to set up a different
|
84
|
-
+ # framework structure
|
85
|
-
+ def build_framework
|
86
|
-
+ %w[view model controller helper mailer part].each do |component|
|
87
|
-
+ Merb.push_path(component.to_sym, Merb.root_path("app/#{component}s"))
|
88
|
-
+ end
|
89
|
-
+ Merb.push_path(:application, Merb.root_path("app/controllers/application.rb"))
|
90
|
-
+ Merb.push_path(:config, Merb.root_path("config/router.rb"))
|
91
|
-
+ Merb.push_path(:lib, Merb.root_path("lib"))
|
92
|
-
end
|
93
|
-
- Merb.push_path(:application, Merb.root_path("app/controllers/application.rb"))
|
94
|
-
- Merb.push_path(:config, Merb.root_path("config/router.rb"))
|
95
|
-
- Merb.push_path(:lib, Merb.root_path("lib"))
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
class Merb::BootLoader::LoadPaths < Merb::BootLoader
|
100
|
-
LOADED_CLASSES = {}
|
101
|
-
|
102
|
-
- def run
|
103
|
-
- # Add models, controllers, and lib to the load path
|
104
|
-
- $LOAD_PATH.unshift Merb.load_paths[:model].first if Merb.load_paths[:model]
|
105
|
-
- $LOAD_PATH.unshift Merb.load_paths[:controller].first if Merb.load_paths[:controller]
|
106
|
-
- $LOAD_PATH.unshift Merb.load_paths[:lib].first if Merb.load_paths[:lib]
|
107
|
-
+ class << self
|
108
|
-
+ def run
|
109
|
-
+ # Add models, controllers, and lib to the load path
|
110
|
-
+ $LOAD_PATH.unshift Merb.load_paths[:model].first if Merb.load_paths[:model]
|
111
|
-
+ $LOAD_PATH.unshift Merb.load_paths[:controller].first if Merb.load_paths[:controller]
|
112
|
-
+ $LOAD_PATH.unshift Merb.load_paths[:lib].first if Merb.load_paths[:lib]
|
113
|
-
|
114
|
-
- # Require all the files in the registered load paths
|
115
|
-
- puts Merb.load_paths.inspect
|
116
|
-
- Merb.load_paths.each do |name, path|
|
117
|
-
- Dir[path.first / path.last].each do |file|
|
118
|
-
- klasses = ObjectSpace.classes.dup
|
119
|
-
- require f
|
120
|
-
- LOADED_CLASSES[file] = ObjectSpace.classes - klasses
|
121
|
-
+ # Require all the files in the registered load paths
|
122
|
-
+ puts Merb.load_paths.inspect
|
123
|
-
+ Merb.load_paths.each do |name, path|
|
124
|
-
+ Dir[path.first / path.last].each do |file|
|
125
|
-
+ klasses = ObjectSpace.classes.dup
|
126
|
-
+ require file
|
127
|
-
+ LOADED_CLASSES[file] = ObjectSpace.classes - klasses
|
128
|
-
+ end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
- end
|
132
|
-
|
133
|
-
- def reload(file)
|
134
|
-
- if klasses = LOADED_CLASSES[file]
|
135
|
-
- klasses.each do |klass|
|
136
|
-
- remove_constant(klass)
|
137
|
-
+ def reload(file)
|
138
|
-
+ if klasses = LOADED_CLASSES[file]
|
139
|
-
+ klasses.each do |klass|
|
140
|
-
+ remove_constant(klass)
|
141
|
-
+ end
|
142
|
-
end
|
143
|
-
+ load file
|
144
|
-
end
|
145
|
-
- load file
|
146
|
-
- end
|
147
|
-
|
148
|
-
- def remove_constant(const)
|
149
|
-
- # This is to support superclasses (like AbstractController) that track
|
150
|
-
- # their subclasses in a class variable. Classes that wish to use this
|
151
|
-
- # functionality are required to alias it to _subclasses_list. Plugins
|
152
|
-
- # for ORMs and other libraries should keep this in mind.
|
153
|
-
- if klass.superclass.respond_to?(:_subclasses_list)
|
154
|
-
- klass.superclass.send(:_subclasses_list).delete(klass)
|
155
|
-
- klass.superclass.send(:_subclasses_list).delete(klass.to_s)
|
156
|
-
- end
|
157
|
-
+ def remove_constant(const)
|
158
|
-
+ # This is to support superclasses (like AbstractController) that track
|
159
|
-
+ # their subclasses in a class variable. Classes that wish to use this
|
160
|
-
+ # functionality are required to alias it to _subclasses_list. Plugins
|
161
|
-
+ # for ORMs and other libraries should keep this in mind.
|
162
|
-
+ if klass.superclass.respond_to?(:_subclasses_list)
|
163
|
-
+ klass.superclass.send(:_subclasses_list).delete(klass)
|
164
|
-
+ klass.superclass.send(:_subclasses_list).delete(klass.to_s)
|
165
|
-
+ end
|
166
|
-
|
167
|
-
- parts = const.to_s.split("::")
|
168
|
-
- base = parts.size == 1 ? Object : Object.full_const_get(parts[0..-2].join("::"))
|
169
|
-
- object = parts[-1].intern
|
170
|
-
- Merb.logger.debugger("Removing constant #{object} from #{base}")
|
171
|
-
- base.send(:remove_const, object) if object
|
172
|
-
+ parts = const.to_s.split("::")
|
173
|
-
+ base = parts.size == 1 ? Object : Object.full_const_get(parts[0..-2].join("::"))
|
174
|
-
+ object = parts[-1].intern
|
175
|
-
+ Merb.logger.debugger("Removing constant #{object} from #{base}")
|
176
|
-
+ base.send(:remove_const, object) if object
|
177
|
-
+ end
|
178
|
-
end
|
179
|
-
|
180
|
-
end
|
181
|
-
|
182
|
-
class Merb::BootLoader::Templates < Merb::BootLoader
|
183
|
-
- def run
|
184
|
-
- template_paths.each do |path|
|
185
|
-
- Merb::Template.inline_template(path)
|
186
|
-
+ class << self
|
187
|
-
+ def run
|
188
|
-
+ template_paths.each do |path|
|
189
|
-
+ Merb::Template.inline_template(path)
|
190
|
-
+ end
|
191
|
-
end
|
192
|
-
- end
|
193
|
-
|
194
|
-
- def template_paths
|
195
|
-
- extension_glob = "{#{Merb::Template::EXTENSIONS.keys.join(',')}}"
|
196
|
-
+ def template_paths
|
197
|
-
+ extension_glob = "{#{Merb::Template::EXTENSIONS.keys.join(',')}}"
|
198
|
-
|
199
|
-
- # This gets all templates set in the controllers template roots
|
200
|
-
- # We separate the two maps because most of controllers will have
|
201
|
-
- # the same _template_root, so it's silly to be globbing the same
|
202
|
-
- # path over and over.
|
203
|
-
- template_paths = Merb::AbstractController._abstract_subclasses.map do |klass|
|
204
|
-
- Object.full_const_get(klass)._template_root
|
205
|
-
- end.uniq.map {|path| Dir["#{path}/**/*.#{extension_glob}"] }
|
206
|
-
+ # This gets all templates set in the controllers template roots
|
207
|
-
+ # We separate the two maps because most of controllers will have
|
208
|
-
+ # the same _template_root, so it's silly to be globbing the same
|
209
|
-
+ # path over and over.
|
210
|
-
+ template_paths = Merb::AbstractController._abstract_subclasses.map do |klass|
|
211
|
-
+ Object.full_const_get(klass)._template_root
|
212
|
-
+ end.uniq.compact.map {|path| Dir["#{path}/**/*.#{extension_glob}"] }
|
213
|
-
|
214
|
-
- # This gets the templates that might be created outside controllers
|
215
|
-
- # template roots. eg app/views/shared/*
|
216
|
-
- template_paths << Dir["#{Merb.dir_for(:view)}/**/*.#{extension_glob}"] if Merb.dir_for(:view)
|
217
|
-
+ # This gets the templates that might be created outside controllers
|
218
|
-
+ # template roots. eg app/views/shared/*
|
219
|
-
+ template_paths << Dir["#{Merb.dir_for(:view)}/**/*.#{extension_glob}"] if Merb.dir_for(:view)
|
220
|
-
|
221
|
-
- template_paths.flatten.compact.uniq
|
222
|
-
- end
|
223
|
-
+ template_paths.flatten.compact.uniq
|
224
|
-
+ end
|
225
|
-
+ end
|
226
|
-
end
|
227
|
-
|
228
|
-
class Merb::BootLoader::Libraries < Merb::BootLoader
|
229
|
-
@@ -145,18 +178,41 @@ class Merb::BootLoader::Libraries < Merb::BootLoader
|
230
|
-
def self.add_libraries(hsh)
|
231
|
-
@@libraries.merge!(hsh)
|
232
|
-
end
|
233
|
-
-
|
234
|
-
- def run
|
235
|
-
+
|
236
|
-
+ def self.run
|
237
|
-
@@libraries.each do |exclude, choices|
|
238
|
-
require_first_working(*choices) unless Merb::Config[exclude]
|
239
|
-
end
|
240
|
-
end
|
241
|
-
-
|
242
|
-
- def require_first_working(first, *rest)
|
243
|
-
+
|
244
|
-
+ def self.require_first_working(first, *rest)
|
245
|
-
p first, rest
|
246
|
-
require first
|
247
|
-
rescue LoadError
|
248
|
-
raise LoadError if rest.empty?
|
249
|
-
require_first_working rest.unshift, *rest
|
250
|
-
end
|
251
|
-
+end
|
252
|
-
+
|
253
|
-
+class Merb::BootLoader::MimeTypes < Merb::BootLoader
|
254
|
-
+ def self.run
|
255
|
-
+ # Sets the default mime-types
|
256
|
-
+ #
|
257
|
-
+ # By default, the mime-types include:
|
258
|
-
+ # :all:: no transform, */*
|
259
|
-
+ # :yaml:: to_yaml, application/x-yaml or text/yaml
|
260
|
-
+ # :text:: to_text, text/plain
|
261
|
-
+ # :html:: to_html, text/html or application/xhtml+xml or application/html
|
262
|
-
+ # :xml:: to_xml, application/xml or text/xml or application/x-xml, adds "Encoding: UTF-8" response header
|
263
|
-
+ # :js:: to_json, text/javascript ot application/javascript or application/x-javascript
|
264
|
-
+ # :json:: to_json, application/json or text/x-json
|
265
|
-
+ Merb.available_mime_types.clear
|
266
|
-
+ Merb.add_mime_type(:all, nil, %w[*/*])
|
267
|
-
+ Merb.add_mime_type(:yaml, :to_yaml, %w[application/x-yaml text/yaml])
|
268
|
-
+ Merb.add_mime_type(:text, :to_text, %w[text/plain])
|
269
|
-
+ Merb.add_mime_type(:html, :to_html, %w[text/html application/xhtml+xml application/html])
|
270
|
-
+ Merb.add_mime_type(:xml, :to_xml, %w[application/xml text/xml application/x-xml], :Encoding => "UTF-8")
|
271
|
-
+ Merb.add_mime_type(:js, :to_json, %w[text/javascript application/javascript application/x-javascript])
|
272
|
-
+ Merb.add_mime_type(:json, :to_json, %w[application/json text/x-json])
|
273
|
-
+ end
|
274
|
-
end
|
275
|
-
|
276
|
-
diff --git a/lib/merb_core/config.rb b/lib/merb_core/config.rb
|
277
|
-
index c92f2e6f071c234551ecb16a4716d47fa92f6c7b..ab0864e0174b54833c758f9f22a840d3b53c7653 100644
|
278
|
-
--- a/lib/merb_core/config.rb
|
279
|
-
+++ b/lib/merb_core/config.rb
|
280
|
-
@@ -92,6 +92,10 @@ module Merb
|
281
|
-
options[:cluster] = nodes
|
282
|
-
end
|
283
|
-
|
284
|
-
+ opts.on("-I", "--init-file FILE", "Name of the file to load first") do |init_file|
|
285
|
-
+ options[:init_file] = init_file
|
286
|
-
+ end
|
287
|
-
+
|
288
|
-
opts.on("-p", "--port PORTNUM", "Port to run merb on, defaults to 4000.") do |port|
|
289
|
-
options[:port] = port
|
290
|
-
end
|
291
|
-
@@ -261,29 +265,29 @@ module Merb
|
292
|
-
|
293
|
-
@configuration = Merb::Config.apply_configuration_from_file options, environment_merb_yml
|
294
|
-
|
295
|
-
- case Merb::Config[:environment].to_s
|
296
|
-
- when 'production'
|
297
|
-
- Merb::Config[:reloader] = Merb::Config.fetch(:reloader, false)
|
298
|
-
- Merb::Config[:exception_details] = Merb::Config.fetch(:exception_details, false)
|
299
|
-
- Merb::Config[:cache_templates] = true
|
300
|
-
- else
|
301
|
-
- Merb::Config[:reloader] = Merb::Config.fetch(:reloader, true)
|
302
|
-
- Merb::Config[:exception_details] = Merb::Config.fetch(:exception_details, true)
|
303
|
-
- end
|
304
|
-
-
|
305
|
-
- Merb::Config[:reloader_time] ||= 0.5 if Merb::Config[:reloader] == true
|
306
|
-
-
|
307
|
-
-
|
308
|
-
- if Merb::Config[:reloader]
|
309
|
-
- Thread.abort_on_exception = true
|
310
|
-
- Thread.new do
|
311
|
-
- loop do
|
312
|
-
- sleep( Merb::Config[:reloader_time] )
|
313
|
-
- ::Merb::BootLoader.reload if ::Merb::BootLoader.app_loaded?
|
314
|
-
- end
|
315
|
-
- Thread.exit
|
316
|
-
- end
|
317
|
-
- end
|
318
|
-
+ # case Merb::Config[:environment].to_s
|
319
|
-
+ # when 'production'
|
320
|
-
+ # Merb::Config[:reloader] = Merb::Config.fetch(:reloader, false)
|
321
|
-
+ # Merb::Config[:exception_details] = Merb::Config.fetch(:exception_details, false)
|
322
|
-
+ # Merb::Config[:cache_templates] = true
|
323
|
-
+ # else
|
324
|
-
+ # Merb::Config[:reloader] = Merb::Config.fetch(:reloader, true)
|
325
|
-
+ # Merb::Config[:exception_details] = Merb::Config.fetch(:exception_details, true)
|
326
|
-
+ # end
|
327
|
-
+ #
|
328
|
-
+ # Merb::Config[:reloader_time] ||= 0.5 if Merb::Config[:reloader] == true
|
329
|
-
+ #
|
330
|
-
+ #
|
331
|
-
+ # if Merb::Config[:reloader]
|
332
|
-
+ # Thread.abort_on_exception = true
|
333
|
-
+ # Thread.new do
|
334
|
-
+ # loop do
|
335
|
-
+ # sleep( Merb::Config[:reloader_time] )
|
336
|
-
+ # ::Merb::BootLoader.reload if ::Merb::BootLoader.app_loaded?
|
337
|
-
+ # end
|
338
|
-
+ # Thread.exit
|
339
|
-
+ # end
|
340
|
-
+ # end
|
341
|
-
@configuration
|
342
|
-
end
|
343
|
-
|
344
|
-
diff --git a/lib/merb_core/controller/abstract_controller.rb b/lib/merb_core/controller/abstract_controller.rb
|
345
|
-
index fbf83372793da6da4b803b799994f0e341fddf88..f5e9a59057d67a6d56377a516a726cf51aa03d6f 100644
|
346
|
-
--- a/lib/merb_core/controller/abstract_controller.rb
|
347
|
-
+++ b/lib/merb_core/controller/abstract_controller.rb
|
348
|
-
@@ -96,7 +96,7 @@ class Merb::AbstractController
|
349
|
-
# the superclass.
|
350
|
-
#---
|
351
|
-
# @public
|
352
|
-
- def _template_location(action, controller = controller_name, type = nil)
|
353
|
-
+ def _template_location(action, type = nil, controller = controller_name)
|
354
|
-
"#{controller}/#{action}"
|
355
|
-
end
|
356
|
-
|
357
|
-
@@ -106,6 +106,8 @@ class Merb::AbstractController
|
358
|
-
# own subclasses. We're using a Set so we don't have to worry about
|
359
|
-
# uniqueness.
|
360
|
-
self._abstract_subclasses = Set.new
|
361
|
-
+ self._template_root = Merb.dir_for(:view)
|
362
|
-
+
|
363
|
-
def self.subclasses_list() _abstract_subclasses end
|
364
|
-
|
365
|
-
class << self
|
366
|
-
@@ -114,7 +116,6 @@ class Merb::AbstractController
|
367
|
-
# The controller that is being inherited from Merb::AbstractController
|
368
|
-
def inherited(klass)
|
369
|
-
_abstract_subclasses << klass.to_s
|
370
|
-
- klass._template_root ||= Merb.dir_for(:view)
|
371
|
-
super
|
372
|
-
end
|
373
|
-
|
374
|
-
diff --git a/lib/merb_core/controller/merb_controller.rb b/lib/merb_core/controller/merb_controller.rb
|
375
|
-
index 7283f006bb0501b29f825da129600cf045264b62..98af6ef3330a6b3f46d7bb1f8643261e28155ae5 100644
|
376
|
-
--- a/lib/merb_core/controller/merb_controller.rb
|
377
|
-
+++ b/lib/merb_core/controller/merb_controller.rb
|
378
|
-
@@ -71,6 +71,10 @@ class Merb::Controller < Merb::AbstractController
|
379
|
-
end
|
380
|
-
end
|
381
|
-
|
382
|
-
+ def _template_location(action, type = nil, controller = controller_name)
|
383
|
-
+ "#{controller}/#{action}.#{type}"
|
384
|
-
+ end
|
385
|
-
+
|
386
|
-
# Sets the variables that came in through the dispatch as available to
|
387
|
-
# the controller. This is called by .build, so see it for more
|
388
|
-
# information.
|
389
|
-
@@ -107,9 +111,7 @@ class Merb::Controller < Merb::AbstractController
|
390
|
-
request.cookies[_session_id_key] = request.params[_session_id_key]
|
391
|
-
end
|
392
|
-
end
|
393
|
-
- @_request, @_response, @_status, @_headers =
|
394
|
-
- request, response, status, headers
|
395
|
-
-
|
396
|
-
+ @request, @response, @status, @headers = request, response, status, headers
|
397
|
-
nil
|
398
|
-
end
|
399
|
-
|
400
|
-
@@ -135,7 +137,8 @@ class Merb::Controller < Merb::AbstractController
|
401
|
-
@_benchmarks[:action_time] = Time.now - start
|
402
|
-
end
|
403
|
-
|
404
|
-
- _attr_reader :request, :response, :status, :headers
|
405
|
-
+ attr_reader :request, :response, :headers
|
406
|
-
+ attr_accessor :status
|
407
|
-
def params() request.params end
|
408
|
-
def cookies() request.cookies end
|
409
|
-
def session() request.session end
|
410
|
-
diff --git a/lib/merb_core/controller/mime.rb b/lib/merb_core/controller/mime.rb
|
411
|
-
index d17570786ca318cff7201c4b1e947ae229b01de8..ff9abe4d1c452aeabfcf5f7dc7a2c7cdd3f67035 100644
|
412
|
-
--- a/lib/merb_core/controller/mime.rb
|
413
|
-
+++ b/lib/merb_core/controller/mime.rb
|
414
|
-
@@ -8,7 +8,7 @@ module Merb
|
415
|
-
|
416
|
-
# Any specific outgoing headers should be included here. These are not
|
417
|
-
# the content-type header but anything in addition to it.
|
418
|
-
- # +tranform_method+ should be set to a symbol of the method used to
|
419
|
-
+ # +transform_method+ should be set to a symbol of the method used to
|
420
|
-
# transform a resource into this mime type.
|
421
|
-
# For example for the :xml mime type an object might be transformed by
|
422
|
-
# calling :to_xml, or for the :js mime type, :to_json.
|
423
|
-
@@ -71,27 +71,6 @@ module Merb
|
424
|
-
def mime_by_request_header(header)
|
425
|
-
available_mime_types.find {|key,info| info[request_headers].include?(header)}.first
|
426
|
-
end
|
427
|
-
-
|
428
|
-
- # Resets the default mime-types
|
429
|
-
- #
|
430
|
-
- # By default, the mime-types include:
|
431
|
-
- # :all:: no transform, */*
|
432
|
-
- # :yaml:: to_yaml, application/x-yaml or text/yaml
|
433
|
-
- # :text:: to_text, text/plain
|
434
|
-
- # :html:: to_html, text/html or application/xhtml+xml or application/html
|
435
|
-
- # :xml:: to_xml, application/xml or text/xml or application/x-xml, adds "Encoding: UTF-8" response header
|
436
|
-
- # :js:: to_json, text/javascript ot application/javascript or application/x-javascript
|
437
|
-
- # :json:: to_json, application/json or text/x-json
|
438
|
-
- def reset_default_mime_types!
|
439
|
-
- available_mime_types.clear
|
440
|
-
- Merb.add_mime_type(:all, nil, %w[*/*])
|
441
|
-
- Merb.add_mime_type(:yaml, :to_yaml, %w[application/x-yaml text/yaml])
|
442
|
-
- Merb.add_mime_type(:text, :to_text, %w[text/plain])
|
443
|
-
- Merb.add_mime_type(:html, :to_html, %w[text/html application/xhtml+xml application/html])
|
444
|
-
- Merb.add_mime_type(:xml, :to_xml, %w[application/xml text/xml application/x-xml], :Encoding => "UTF-8")
|
445
|
-
- Merb.add_mime_type(:js, :to_json, %w[text/javascript application/javascript application/x-javascript])
|
446
|
-
- Merb.add_mime_type(:json, :to_json, %w[application/json text/x-json])
|
447
|
-
- end
|
448
|
-
|
449
|
-
end
|
450
|
-
end
|
451
|
-
|
452
|
-
diff --git a/lib/merb_core/controller/mixins/render.rb b/lib/merb_core/controller/mixins/render.rb
|
453
|
-
index 8e096546d4647bb597ab2e00a4b15d09db35e9c9..a298263af7d655d9ce43007554f3827046831287 100644
|
454
|
-
--- a/lib/merb_core/controller/mixins/render.rb
|
455
|
-
+++ b/lib/merb_core/controller/mixins/render.rb
|
456
|
-
@@ -51,21 +51,22 @@ module Merb::RenderMixin
|
457
|
-
|
458
|
-
# If you don't specify a thing to render, assume they want to render the current action
|
459
|
-
thing ||= action_name.to_sym
|
460
|
-
-
|
461
|
-
+
|
462
|
-
# Content negotiation
|
463
|
-
opts[:format] ? (self.content_type = opts[:format]) : content_type
|
464
|
-
|
465
|
-
# Do we have a template to try to render?
|
466
|
-
if thing.is_a?(Symbol) || opts[:template]
|
467
|
-
-
|
468
|
-
+
|
469
|
-
# Find a template path to look up (_template_location adds flexibility here)
|
470
|
-
- template_location = _template_root / (opts[:template] || _template_location(thing))
|
471
|
-
+ template_location = _template_root / (opts[:template] || _template_location(thing, content_type))
|
472
|
-
+
|
473
|
-
# Get the method name from the previously inlined list
|
474
|
-
template_method = Merb::Template.template_for(template_location)
|
475
|
-
|
476
|
-
# Raise an error if there's no template
|
477
|
-
raise TemplateNotFound, "No template found at #{template_location}" unless
|
478
|
-
- self.respond_to?(template_method)
|
479
|
-
+ template_method && self.respond_to?(template_method)
|
480
|
-
|
481
|
-
# Call the method in question and throw the content for later consumption by the layout
|
482
|
-
throw_content(:for_layout, self.send(template_method))
|
483
|
-
diff --git a/lib/merb_core/controller/mixins/responder.rb b/lib/merb_core/controller/mixins/responder.rb
|
484
|
-
index e910b2b32c844ab51cf2a10d0ad26c314dbb3631..5ac67fb907aaf9f95effc7eb3cbb07b8963ce022 100644
|
485
|
-
--- a/lib/merb_core/controller/mixins/responder.rb
|
486
|
-
+++ b/lib/merb_core/controller/mixins/responder.rb
|
487
|
-
@@ -97,6 +97,8 @@ module Merb
|
488
|
-
# and none of the provides methods can be used.
|
489
|
-
module ResponderMixin
|
490
|
-
|
491
|
-
+ TYPES = {}
|
492
|
-
+
|
493
|
-
class ContentTypeAlreadySet < StandardError; end
|
494
|
-
|
495
|
-
# ==== Parameters
|
496
|
-
@@ -105,6 +107,7 @@ module Merb
|
497
|
-
base.extend(ClassMethods)
|
498
|
-
base.class_eval do
|
499
|
-
class_inheritable_accessor :class_provided_formats
|
500
|
-
+ self.class_provided_formats = []
|
501
|
-
end
|
502
|
-
base.reset_provides
|
503
|
-
end
|
504
|
-
@@ -178,171 +181,253 @@ module Merb
|
505
|
-
def reset_provides
|
506
|
-
only_provides(:html)
|
507
|
-
end
|
508
|
-
-
|
509
|
-
- # ==== Returns
|
510
|
-
- # The current list of formats provided for this instance of the controller.
|
511
|
-
- # It starts with what has been set in the controller (or :html by default)
|
512
|
-
- # but can be modifed on a per-action basis.
|
513
|
-
- def _provided_formats
|
514
|
-
- @_provided_formats ||= class_provided_formats.dup
|
515
|
-
+ end
|
516
|
-
+
|
517
|
-
+ # ==== Returns
|
518
|
-
+ # The current list of formats provided for this instance of the controller.
|
519
|
-
+ # It starts with what has been set in the controller (or :html by default)
|
520
|
-
+ # but can be modifed on a per-action basis.
|
521
|
-
+ def _provided_formats
|
522
|
-
+ @_provided_formats ||= class_provided_formats.dup
|
523
|
-
+ end
|
524
|
-
+
|
525
|
-
+ # Sets the provided formats for this action. Usually, you would
|
526
|
-
+ # use a combination of +provides+, +only_provides+ and +does_not_provide+
|
527
|
-
+ # to manage this, but you can set it directly.
|
528
|
-
+ #
|
529
|
-
+ # ==== Parameters
|
530
|
-
+ # *formats<Symbol>:: A list of formats to be passed to provides
|
531
|
-
+ #
|
532
|
-
+ # ==== Raises
|
533
|
-
+ # Merb::ResponderMixin::ContentTypeAlreadySet::
|
534
|
-
+ # Content negotiation already occured, and the content_type is set.
|
535
|
-
+ #
|
536
|
-
+ # ==== Returns
|
537
|
-
+ # Array:: List of formats passed in
|
538
|
-
+ def _set_provided_formats(*formats)
|
539
|
-
+ if @_content_type
|
540
|
-
+ raise ContentTypeAlreadySet, "Cannot modify provided_formats because content_type has already been set"
|
541
|
-
end
|
542
|
-
-
|
543
|
-
- # Sets the provided formats for this action. Usually, you would
|
544
|
-
- # use a combination of +provides+, +only_provides+ and +does_not_provide+
|
545
|
-
- # to manage this, but you can set it directly.
|
546
|
-
- #
|
547
|
-
- # ==== Parameters
|
548
|
-
- # *formats<Symbol>:: A list of formats to be passed to provides
|
549
|
-
- #
|
550
|
-
- # ==== Raises
|
551
|
-
- # Merb::ResponderMixin::ContentTypeAlreadySet::
|
552
|
-
- # Content negotiation already occured, and the content_type is set.
|
553
|
-
- #
|
554
|
-
- # ==== Returns
|
555
|
-
- # Array:: List of formats passed in
|
556
|
-
- def _set_provided_formats(*formats)
|
557
|
-
- if @_content_type
|
558
|
-
- raise ContentTypeAlreadySet, "Cannot modify provided_formats because content_type has already been set"
|
559
|
-
- end
|
560
|
-
- @_provided_formats = []
|
561
|
-
- provides(*formats)
|
562
|
-
+ @_provided_formats = []
|
563
|
-
+ provides(*formats)
|
564
|
-
+ end
|
565
|
-
+ alias :_provided_formats= :_set_provided_formats
|
566
|
-
+
|
567
|
-
+ # Adds formats to the list of provided formats for this particular
|
568
|
-
+ # request. Usually used to add formats to a single action. See also
|
569
|
-
+ # the controller-level provides that affects all actions in a controller.
|
570
|
-
+ #
|
571
|
-
+ # ==== Parameters
|
572
|
-
+ # *formats<Symbol>:: A list of formats to add to the per-action list
|
573
|
-
+ # of provided formats
|
574
|
-
+ #
|
575
|
-
+ # ==== Raises
|
576
|
-
+ # Merb::ResponderMixin::ContentTypeAlreadySet::
|
577
|
-
+ # Content negotiation already occured, and the content_type is set.
|
578
|
-
+ #
|
579
|
-
+ # ==== Returns
|
580
|
-
+ # Array:: List of formats passed in
|
581
|
-
+ #
|
582
|
-
+ #---
|
583
|
-
+ # @public
|
584
|
-
+ def provides(*formats)
|
585
|
-
+ if @_content_type
|
586
|
-
+ raise ContentTypeAlreadySet, "Cannot modify provided_formats because content_type has already been set"
|
587
|
-
end
|
588
|
-
- alias :_provided_formats= :_set_provided_formats
|
589
|
-
-
|
590
|
-
- # Adds formats to the list of provided formats for this particular
|
591
|
-
- # request. Usually used to add formats to a single action. See also
|
592
|
-
- # the controller-level provides that affects all actions in a controller.
|
593
|
-
- #
|
594
|
-
- # ==== Parameters
|
595
|
-
- # *formats<Symbol>:: A list of formats to add to the per-action list
|
596
|
-
- # of provided formats
|
597
|
-
- #
|
598
|
-
- # ==== Raises
|
599
|
-
- # Merb::ResponderMixin::ContentTypeAlreadySet::
|
600
|
-
- # Content negotiation already occured, and the content_type is set.
|
601
|
-
- #
|
602
|
-
- # ==== Returns
|
603
|
-
- # Array:: List of formats passed in
|
604
|
-
- #
|
605
|
-
- #---
|
606
|
-
- # @public
|
607
|
-
- def provides(*formats)
|
608
|
-
- if @_content_type
|
609
|
-
- raise ContentTypeAlreadySet, "Cannot modify provided_formats because content_type has already been set"
|
610
|
-
- end
|
611
|
-
- formats.each do |fmt|
|
612
|
-
- _provided_formats << fmt unless _provided_formats.include?(fmt)
|
613
|
-
- end
|
614
|
-
+ formats.each do |fmt|
|
615
|
-
+ _provided_formats << fmt unless _provided_formats.include?(fmt)
|
616
|
-
end
|
617
|
-
+ end
|
618
|
-
|
619
|
-
- # Sets list of provided formats for this particular
|
620
|
-
- # request. Usually used to limit formats to a single action. See also
|
621
|
-
- # the controller-level only_provides that affects all actions
|
622
|
-
- # in a controller.
|
623
|
-
- #
|
624
|
-
- # ==== Parameters
|
625
|
-
- # *formats<Symbol>:: A list of formats to use as the per-action list
|
626
|
-
- # of provided formats
|
627
|
-
- #
|
628
|
-
- # ==== Returns
|
629
|
-
- # Array:: List of formats passed in
|
630
|
-
- #
|
631
|
-
- #---
|
632
|
-
- # @public
|
633
|
-
- def only_provides(*formats)
|
634
|
-
- self._provided_formats = *formats
|
635
|
-
- end
|
636
|
-
-
|
637
|
-
- # Removes formats from the list of provided formats for this particular
|
638
|
-
- # request. Usually used to remove formats from a single action. See
|
639
|
-
- # also the controller-level does_not_provide that affects all actions in a
|
640
|
-
- # controller.
|
641
|
-
- #
|
642
|
-
- # ==== Parameters
|
643
|
-
- # *formats<Symbol>:: Registered mime-type
|
644
|
-
- #
|
645
|
-
- # ==== Returns
|
646
|
-
- # Array:: List of formats that remain after removing the ones not to provide
|
647
|
-
- #
|
648
|
-
- #---
|
649
|
-
- # @public
|
650
|
-
- def does_not_provide(*formats)
|
651
|
-
- formats.flatten!
|
652
|
-
- self._provided_formats -= formats
|
653
|
-
- end
|
654
|
-
-
|
655
|
-
- # Do the content negotiation:
|
656
|
-
- # 1. if params[:format] is there, and provided, use it
|
657
|
-
- # 2. Parse the Accept header
|
658
|
-
- # 3. If it's */*, use the first provided format
|
659
|
-
- # 4. Look for one that is provided, in order of request
|
660
|
-
- # 5. Raise 406 if none found
|
661
|
-
- def _perform_content_negotiation # :nodoc:
|
662
|
-
- raise Merb::ControllerExceptions::NotAcceptable if provided_formats.empty?
|
663
|
-
- if fmt = params[:format]
|
664
|
-
- return fmt.to_sym if provided_formats.include?(fmt.to_sym)
|
665
|
-
- else
|
666
|
-
- accepts = Responder.parse(request.accept).map {|t| t.to_sym}
|
667
|
-
- return provided_formats.first if accepts.include?(:all)
|
668
|
-
- return accepts.each { |type| break type if provided_formats.include?(type) }
|
669
|
-
- end
|
670
|
-
- raise Merb::ControllerExceptions::NotAcceptable
|
671
|
-
+ # Sets list of provided formats for this particular
|
672
|
-
+ # request. Usually used to limit formats to a single action. See also
|
673
|
-
+ # the controller-level only_provides that affects all actions
|
674
|
-
+ # in a controller.
|
675
|
-
+ #
|
676
|
-
+ # ==== Parameters
|
677
|
-
+ # *formats<Symbol>:: A list of formats to use as the per-action list
|
678
|
-
+ # of provided formats
|
679
|
-
+ #
|
680
|
-
+ # ==== Returns
|
681
|
-
+ # Array:: List of formats passed in
|
682
|
-
+ #
|
683
|
-
+ #---
|
684
|
-
+ # @public
|
685
|
-
+ def only_provides(*formats)
|
686
|
-
+ self._provided_formats = *formats
|
687
|
-
+ end
|
688
|
-
+
|
689
|
-
+ # Removes formats from the list of provided formats for this particular
|
690
|
-
+ # request. Usually used to remove formats from a single action. See
|
691
|
-
+ # also the controller-level does_not_provide that affects all actions in a
|
692
|
-
+ # controller.
|
693
|
-
+ #
|
694
|
-
+ # ==== Parameters
|
695
|
-
+ # *formats<Symbol>:: Registered mime-type
|
696
|
-
+ #
|
697
|
-
+ # ==== Returns
|
698
|
-
+ # Array:: List of formats that remain after removing the ones not to provide
|
699
|
-
+ #
|
700
|
-
+ #---
|
701
|
-
+ # @public
|
702
|
-
+ def does_not_provide(*formats)
|
703
|
-
+ formats.flatten!
|
704
|
-
+ self._provided_formats -= formats
|
705
|
-
+ end
|
706
|
-
+
|
707
|
-
+ # Do the content negotiation:
|
708
|
-
+ # 1. if params[:format] is there, and provided, use it
|
709
|
-
+ # 2. Parse the Accept header
|
710
|
-
+ # 3. If it's */*, use the first provided format
|
711
|
-
+ # 4. Look for one that is provided, in order of request
|
712
|
-
+ # 5. Raise 406 if none found
|
713
|
-
+ def _perform_content_negotiation # :nodoc:
|
714
|
-
+ raise Merb::ControllerExceptions::NotAcceptable if _provided_formats.empty?
|
715
|
-
+ if fmt = params[:format] && _provided_formats.include?(fmt.to_sym)
|
716
|
-
+ return fmt.to_sym
|
717
|
-
end
|
718
|
-
+ accepts = Responder.parse(request.accept).map {|t| t.to_sym}
|
719
|
-
+ return _provided_formats.first if accepts.include?(:all)
|
720
|
-
+ (accepts & _provided_formats).first || (raise Merb::ControllerExceptions::NotAcceptable)
|
721
|
-
+ end
|
722
|
-
|
723
|
-
- # Returns the output format for this request, based on the
|
724
|
-
- # provided formats, <tt>params[:format]</tt> and the client's HTTP
|
725
|
-
- # Accept header.
|
726
|
-
- #
|
727
|
-
- # The first time this is called, it triggers content negotiation
|
728
|
-
- # and caches the value. Once you call +content_type+ you can
|
729
|
-
- # not set or change the list of provided formats.
|
730
|
-
- #
|
731
|
-
- # Called automatically by +render+, so you should only call it if
|
732
|
-
- # you need the value, not to trigger content negotiation.
|
733
|
-
- #
|
734
|
-
- # ==== Parameters
|
735
|
-
- # fmt<String?>::
|
736
|
-
- # An optional format to use instead of performing content negotiation.
|
737
|
-
- # This can be used to pass in the values of opts[:format] from the
|
738
|
-
- # render function to short-circuit content-negotiation when it's not
|
739
|
-
- # necessary. This optional parameter should not be considered part
|
740
|
-
- # of the public API.
|
741
|
-
- #
|
742
|
-
- # ==== Returns
|
743
|
-
- # Symbol:: The content-type that will be used for this controller.
|
744
|
-
- #
|
745
|
-
- #---
|
746
|
-
- # @public
|
747
|
-
- def content_type(fmt = nil)
|
748
|
-
- self.content_type = (fmt || _perform_content_negotiation) unless @_content_type
|
749
|
-
- @_content_type
|
750
|
-
+ # Returns the output format for this request, based on the
|
751
|
-
+ # provided formats, <tt>params[:format]</tt> and the client's HTTP
|
752
|
-
+ # Accept header.
|
753
|
-
+ #
|
754
|
-
+ # The first time this is called, it triggers content negotiation
|
755
|
-
+ # and caches the value. Once you call +content_type+ you can
|
756
|
-
+ # not set or change the list of provided formats.
|
757
|
-
+ #
|
758
|
-
+ # Called automatically by +render+, so you should only call it if
|
759
|
-
+ # you need the value, not to trigger content negotiation.
|
760
|
-
+ #
|
761
|
-
+ # ==== Parameters
|
762
|
-
+ # fmt<String?>::
|
763
|
-
+ # An optional format to use instead of performing content negotiation.
|
764
|
-
+ # This can be used to pass in the values of opts[:format] from the
|
765
|
-
+ # render function to short-circuit content-negotiation when it's not
|
766
|
-
+ # necessary. This optional parameter should not be considered part
|
767
|
-
+ # of the public API.
|
768
|
-
+ #
|
769
|
-
+ # ==== Returns
|
770
|
-
+ # Symbol:: The content-type that will be used for this controller.
|
771
|
-
+ #
|
772
|
-
+ #---
|
773
|
-
+ # @public
|
774
|
-
+ def content_type(fmt = nil)
|
775
|
-
+ @_content_type = (fmt || _perform_content_negotiation) unless @_content_type
|
776
|
-
+ @_content_type
|
777
|
-
+ end
|
778
|
-
+
|
779
|
-
+ # Sets the content type of the current response to a value based on
|
780
|
-
+ # a passed in key. The Content-Type header will be set to the first
|
781
|
-
+ # registered header for the mime-type.
|
782
|
-
+ #
|
783
|
-
+ # ==== Parameters
|
784
|
-
+ # type<Symbol>:: A type that is in the list of registered mime-types.
|
785
|
-
+ #
|
786
|
-
+ # ==== Raises
|
787
|
-
+ # ArgumentError:: "type" is not in the list of registered mime-types.
|
788
|
-
+ #
|
789
|
-
+ # ==== Returns
|
790
|
-
+ # Symbol:: The content-type that was passed in.
|
791
|
-
+ #
|
792
|
-
+ #---
|
793
|
-
+ # @semipublic
|
794
|
-
+ def content_type=(type)
|
795
|
-
+ unless Merb.available_mime_types.has_key?(type)
|
796
|
-
+ raise Merb::ControllerExceptions::NotAcceptable.new("Unknown content_type for response: #{type}")
|
797
|
-
+ end
|
798
|
-
+ headers['Content-Type'] = Merb.available_mime_types[type].first
|
799
|
-
+ @_content_type = type
|
800
|
-
+ end
|
801
|
-
+
|
802
|
-
+ end
|
803
|
-
+
|
804
|
-
+ class Responder
|
805
|
-
+
|
806
|
-
+ protected
|
807
|
-
+ def self.parse(accept_header)
|
808
|
-
+ # parse the raw accept header into a unique, sorted array of AcceptType objects
|
809
|
-
+ list = accept_header.to_s.split(/,/).enum_for(:each_with_index).map do |entry,index|
|
810
|
-
+ AcceptType.new(entry,index += 1)
|
811
|
-
+ end.sort.uniq
|
812
|
-
+ # firefox (and possibly other browsers) send broken default accept headers.
|
813
|
-
+ # fix them up by sorting alternate xml forms (namely application/xhtml+xml)
|
814
|
-
+ # ahead of pure xml types (application/xml,text/xml).
|
815
|
-
+ if app_xml = list.detect{|e| e.super_range == 'application/xml'}
|
816
|
-
+ list.select{|e| e.to_s =~ /\+xml/}.each { |acc_type|
|
817
|
-
+ list[list.index(acc_type)],list[list.index(app_xml)] =
|
818
|
-
+ list[list.index(app_xml)],list[list.index(acc_type)] }
|
819
|
-
end
|
820
|
-
-
|
821
|
-
- # Sets the content type of the current response to a value based on
|
822
|
-
- # a passed in key. The Content-Type header will be set to the first
|
823
|
-
- # registered header for the mime-type.
|
824
|
-
- #
|
825
|
-
- # ==== Parameters
|
826
|
-
- # type<Symbol>:: A type that is in the list of registered mime-types.
|
827
|
-
- #
|
828
|
-
- # ==== Raises
|
829
|
-
- # ArgumentError:: "type" is not in the list of registered mime-types.
|
830
|
-
- #
|
831
|
-
- # ==== Returns
|
832
|
-
- # Symbol:: The content-type that was passed in.
|
833
|
-
- #
|
834
|
-
- #---
|
835
|
-
- # @semipublic
|
836
|
-
- def content_type=(type)
|
837
|
-
- unless Merb.available_mime_types.has_key?(type)
|
838
|
-
- raise Merb::ControllerExceptions::NotAcceptable.new("Unknown content_type for response: #{type}")
|
839
|
-
- end
|
840
|
-
- headers['Content-Type'] = Merb.available_mime_types[type].first
|
841
|
-
- @_content_type = type
|
842
|
-
+ list
|
843
|
-
+ end
|
844
|
-
+
|
845
|
-
+ public
|
846
|
-
+ def self.params_to_query_string(value, prefix = nil)
|
847
|
-
+ case value
|
848
|
-
+ when Array
|
849
|
-
+ value.map { |v|
|
850
|
-
+ params_to_query_string(v, "#{prefix}[]")
|
851
|
-
+ } * "&"
|
852
|
-
+ when Hash
|
853
|
-
+ value.map { |k, v|
|
854
|
-
+ params_to_query_string(v, prefix ? "#{prefix}[#{Merb::Request.escape(k)}]" : Merb::Request.escape(k))
|
855
|
-
+ } * "&"
|
856
|
-
+ else
|
857
|
-
+ "#{prefix}=#{Merb::Request.escape(value)}"
|
858
|
-
end
|
859
|
-
+ end
|
860
|
-
|
861
|
-
- end
|
862
|
-
+ end
|
863
|
-
+
|
864
|
-
+ class AcceptType
|
865
|
-
+
|
866
|
-
+ attr_reader :media_range, :quality, :index, :type, :sub_type
|
867
|
-
|
868
|
-
+ def initialize(entry,index)
|
869
|
-
+ @index = index
|
870
|
-
+ @media_range, quality = entry.split(/;\s*q=/).map{|a| a.strip }
|
871
|
-
+ @type, @sub_type = @media_range.split(/\//)
|
872
|
-
+ quality ||= 0.0 if @media_range == '*/*'
|
873
|
-
+ @quality = ((quality || 1.0).to_f * 100).to_i
|
874
|
-
+ end
|
875
|
-
+
|
876
|
-
+ def <=>(entry)
|
877
|
-
+ c = entry.quality <=> quality
|
878
|
-
+ c = index <=> entry.index if c == 0
|
879
|
-
+ c
|
880
|
-
+ end
|
881
|
-
+
|
882
|
-
+ def eql?(entry)
|
883
|
-
+ synonyms.include?(entry.media_range)
|
884
|
-
+ end
|
885
|
-
+
|
886
|
-
+ def ==(entry); eql?(entry); end
|
887
|
-
+
|
888
|
-
+ def hash; super_range.hash; end
|
889
|
-
+
|
890
|
-
+ def synonyms
|
891
|
-
+ @syns ||= Merb.available_mime_types.values.map do |e|
|
892
|
-
+ e[:request_headers] if e[:request_headers].include?(@media_range)
|
893
|
-
+ end.compact.flatten
|
894
|
-
+ end
|
895
|
-
+
|
896
|
-
+ def super_range
|
897
|
-
+ synonyms.first || @media_range
|
898
|
-
+ end
|
899
|
-
+
|
900
|
-
+ def to_sym
|
901
|
-
+ Merb.available_mime_types.select{|k,v|
|
902
|
-
+ v[:request_headers] == synonyms || v[:request_headers][0] == synonyms[0]}.flatten.first
|
903
|
-
+ end
|
904
|
-
+
|
905
|
-
+ def to_s
|
906
|
-
+ @media_range
|
907
|
-
+ end
|
908
|
-
+
|
909
|
-
end
|
910
|
-
+
|
911
|
-
|
912
|
-
end
|
913
|
-
|
914
|
-
diff --git a/lib/merb_core/dispatch/dispatcher.rb b/lib/merb_core/dispatch/dispatcher.rb
|
915
|
-
index c458c9f9ad454d3b0c3055d6b2a8e88b17712b44..f7fed0f539a20f9cce08b72c551725ad0563bf37 100644
|
916
|
-
--- a/lib/merb_core/dispatch/dispatcher.rb
|
917
|
-
+++ b/lib/merb_core/dispatch/dispatcher.rb
|
918
|
-
@@ -33,10 +33,10 @@ class Merb::Dispatcher
|
919
|
-
|
920
|
-
# this is the custom dispatch_exception; it allows failures to still be dispatched
|
921
|
-
# to the error controller
|
922
|
-
- rescue => exception
|
923
|
-
- Merb.logger.error(Merb.exception(exception))
|
924
|
-
- exception = controller_exception(exception)
|
925
|
-
- dispatch_exception(request, response, exception)
|
926
|
-
+ # rescue => exception
|
927
|
-
+ # Merb.logger.error(Merb.exception(exception))
|
928
|
-
+ # exception = controller_exception(exception)
|
929
|
-
+ # dispatch_exception(request, response, exception)
|
930
|
-
end
|
931
|
-
|
932
|
-
private
|
933
|
-
@@ -49,10 +49,10 @@ class Merb::Dispatcher
|
934
|
-
def dispatch_action(klass, action, request, response, status=200)
|
935
|
-
# build controller
|
936
|
-
controller = klass.build(request, response, status)
|
937
|
-
- if @@use_mutex
|
938
|
-
- @@mutex.synchronize { controller.dispatch(action) }
|
939
|
-
+ if use_mutex
|
940
|
-
+ @@mutex.synchronize { controller._dispatch(action) }
|
941
|
-
else
|
942
|
-
- controller.dispatch(action)
|
943
|
-
+ controller._dispatch(action)
|
944
|
-
end
|
945
|
-
[controller, action]
|
946
|
-
end
|
947
|
-
diff --git a/lib/merb_core/rack/adapter.rb b/lib/merb_core/rack/adapter.rb
|
948
|
-
index ffc7117e9733e83b0567bbe4a43fac7663800b7d..217399a5382d0b3878aaea3d3e302173c5b5f119 100644
|
949
|
-
--- a/lib/merb_core/rack/adapter.rb
|
950
|
-
+++ b/lib/merb_core/rack/adapter.rb
|
951
|
-
@@ -40,7 +40,7 @@ module Merb
|
952
|
-
begin
|
953
|
-
controller, action = ::Merb::Dispatcher.handle(request, response)
|
954
|
-
rescue Object => e
|
955
|
-
- return [500, {"Content-Type"=>"text/html"}, "Internal Server Error"]
|
956
|
-
+ return [500, {"Content-Type"=>"text/html"}, e.message + "<br/>" + e.backtrace.join("<br/>")]
|
957
|
-
end
|
958
|
-
[controller.status, controller.headers, controller.body]
|
959
|
-
end
|
960
|
-
diff --git a/lib/merb_core/test/request_helper.rb b/lib/merb_core/test/request_helper.rb
|
961
|
-
index 10a9fb3ace56eaf1db0fa300df3fb2ab88a7118a..f302a3b71539182ba142cd208fe6d6aae171b1a1 100644
|
962
|
-
--- a/lib/merb_core/test/request_helper.rb
|
963
|
-
+++ b/lib/merb_core/test/request_helper.rb
|
964
|
-
@@ -26,8 +26,10 @@ module Merb::Test::RequestHelper
|
965
|
-
Merb::Test::FakeRequest.new(env, StringIO.new(req))
|
966
|
-
end
|
967
|
-
|
968
|
-
- def dispatch_to(controller_klass, action, env = {}, opt = {}, &blk)
|
969
|
-
- request = fake_request(env, opt)
|
970
|
-
+ def dispatch_to(controller_klass, action, params = {}, env = {}, &blk)
|
971
|
-
+ request = fake_request(env,
|
972
|
-
+ :query_string => Merb::Responder.params_to_query_string(params))
|
973
|
-
+
|
974
|
-
controller = controller_klass.build(request)
|
975
|
-
controller.instance_eval(&blk) if block_given?
|
976
|
-
controller._dispatch(action)
|
977
|
-
diff --git a/spec/public/abstract_controller/spec_helper.rb b/spec/public/abstract_controller/spec_helper.rb
|
978
|
-
index df759008d14e7572b5c44de24f77f828f83f1682..694cee2592a210a5c1fa40ca7846beeaa09725fe 100644
|
979
|
-
--- a/spec/public/abstract_controller/spec_helper.rb
|
980
|
-
+++ b/spec/public/abstract_controller/spec_helper.rb
|
981
|
-
@@ -1,12 +1,10 @@
|
982
|
-
__DIR__ = File.dirname(__FILE__)
|
983
|
-
require File.join(__DIR__, "..", "..", "spec_helper")
|
984
|
-
|
985
|
-
-# The framework structure *must* be set up before loading in framework
|
986
|
-
-# files.
|
987
|
-
require File.join(__DIR__, "controllers", "filters")
|
988
|
-
require File.join(__DIR__, "controllers", "render")
|
989
|
-
|
990
|
-
-Merb::BootLoader::Templates.new.run
|
991
|
-
+Merb::BootLoader::Templates.run
|
992
|
-
|
993
|
-
module Merb::Test::Behaviors
|
994
|
-
def dispatch_should_make_body(klass, body, action = :index)
|
995
|
-
diff --git a/spec/public/controller/base_spec.rb b/spec/public/controller/base_spec.rb
|
996
|
-
index 1709e612629ed2c2b6af4579a8b89684aca9aa3c..5bcdb59948cc22592639b1aee9bd233ff2c306fa 100644
|
997
|
-
--- a/spec/public/controller/base_spec.rb
|
998
|
-
+++ b/spec/public/controller/base_spec.rb
|
999
|
-
@@ -10,11 +10,11 @@ describe Merb::Controller, " callable actions" do
|
1000
|
-
end
|
1001
|
-
|
1002
|
-
it "should dispatch to callable actions" do
|
1003
|
-
- dispatch_to(Merb::Test::Fixtures::TestFoo, :index).body.should == "index"
|
1004
|
-
+ dispatch_to(Merb::Test::Fixtures::TestBase, :index).body.should == "index"
|
1005
|
-
end
|
1006
|
-
|
1007
|
-
it "should not dispatch to hidden actions" do
|
1008
|
-
- calling { dispatch_to(Merb::Test::Fixtures::TestFoo, :hidden) }.
|
1009
|
-
+ calling { dispatch_to(Merb::Test::Fixtures::TestBase, :hidden) }.
|
1010
|
-
should raise_error(Merb::ControllerExceptions::ActionNotFound)
|
1011
|
-
end
|
1012
|
-
|
1013
|
-
diff --git a/spec/public/controller/controllers/base.rb b/spec/public/controller/controllers/base.rb
|
1014
|
-
index a1b3beb27899df781d943427d9b23945f02e14de..c4b69a440a9da3c3486208d2cb95ccb8bdb974b9 100644
|
1015
|
-
--- a/spec/public/controller/controllers/base.rb
|
1016
|
-
+++ b/spec/public/controller/controllers/base.rb
|
1017
|
-
@@ -3,7 +3,7 @@ module Merb::Test::Fixtures
|
1018
|
-
self._template_root = File.dirname(__FILE__) / "views"
|
1019
|
-
end
|
1020
|
-
|
1021
|
-
- class TestFoo < ControllerTesting
|
1022
|
-
+ class TestBase < ControllerTesting
|
1023
|
-
def index
|
1024
|
-
"index"
|
1025
|
-
end
|
1026
|
-
diff --git a/spec/public/controller/controllers/responder.rb b/spec/public/controller/controllers/responder.rb
|
1027
|
-
new file mode 100644
|
1028
|
-
index 0000000000000000000000000000000000000000..867192e8f6e995a43fd5cd3daffa0ec11b3d31e5
|
1029
|
-
--- /dev/null
|
1030
|
-
+++ b/spec/public/controller/controllers/responder.rb
|
1031
|
-
@@ -0,0 +1,25 @@
|
1032
|
-
+module Merb::Test::Fixtures
|
1033
|
-
+ class ControllerTesting < Merb::Controller
|
1034
|
-
+ self._template_root = File.dirname(__FILE__) / "views"
|
1035
|
-
+ end
|
1036
|
-
+
|
1037
|
-
+ class TestResponder < ControllerTesting
|
1038
|
-
+ def index
|
1039
|
-
+ render
|
1040
|
-
+ end
|
1041
|
-
+ end
|
1042
|
-
+
|
1043
|
-
+ class TestHtmlDefault < TestResponder; end
|
1044
|
-
+
|
1045
|
-
+ class TestClassProvides < TestResponder;
|
1046
|
-
+ provides :xml
|
1047
|
-
+ end
|
1048
|
-
+
|
1049
|
-
+ class TestLocalProvides < TestResponder;
|
1050
|
-
+ def index
|
1051
|
-
+ provides :xml
|
1052
|
-
+ render
|
1053
|
-
+ end
|
1054
|
-
+ end
|
1055
|
-
+
|
1056
|
-
+end
|
1057
|
-
|
1058
|
-
diff --git a/spec/public/controller/controllers/views/merb/test/fixtures/test_class_provides/index.html.erb b/spec/public/controller/controllers/views/merb/test/fixtures/test_class_provides/index.html.erb
|
1059
|
-
new file mode 100644
|
1060
|
-
index 0000000000000000000000000000000000000000..1bfb77d4a44c444bba6888ae7740f7df4b074c58
|
1061
|
-
--- /dev/null
|
1062
|
-
+++ b/spec/public/controller/controllers/views/merb/test/fixtures/test_class_provides/index.html.erb
|
1063
|
-
@@ -0,0 +1 @@
|
1064
|
-
+This should not be rendered
|
1065
|
-
|
1066
|
-
diff --git a/spec/public/controller/controllers/views/merb/test/fixtures/test_class_provides/index.xml.erb b/spec/public/controller/controllers/views/merb/test/fixtures/test_class_provides/index.xml.erb
|
1067
|
-
new file mode 100644
|
1068
|
-
index 0000000000000000000000000000000000000000..7c91f633987348e87e5e34e1d9e87d9dd0e5100c
|
1069
|
-
--- /dev/null
|
1070
|
-
+++ b/spec/public/controller/controllers/views/merb/test/fixtures/test_class_provides/index.xml.erb
|
1071
|
-
@@ -0,0 +1 @@
|
1072
|
-
+<XML:Class provides='true' />
|
1073
|
-
|
1074
|
-
diff --git a/spec/public/controller/controllers/views/merb/test/fixtures/test_html_default/index.html.erb b/spec/public/controller/controllers/views/merb/test/fixtures/test_html_default/index.html.erb
|
1075
|
-
new file mode 100644
|
1076
|
-
index 0000000000000000000000000000000000000000..eb4b52bf5a7aaba8f1706de419f42789c05684a2
|
1077
|
-
--- /dev/null
|
1078
|
-
+++ b/spec/public/controller/controllers/views/merb/test/fixtures/test_html_default/index.html.erb
|
1079
|
-
@@ -0,0 +1 @@
|
1080
|
-
+HTML: Default
|
1081
|
-
|
1082
|
-
diff --git a/spec/public/controller/controllers/views/merb/test/fixtures/test_local_provides/index.html.erb b/spec/public/controller/controllers/views/merb/test/fixtures/test_local_provides/index.html.erb
|
1083
|
-
new file mode 100644
|
1084
|
-
index 0000000000000000000000000000000000000000..a3a841a89c62e6174038935a42da9cd24ff54413
|
1085
|
-
--- /dev/null
|
1086
|
-
+++ b/spec/public/controller/controllers/views/merb/test/fixtures/test_local_provides/index.html.erb
|
1087
|
-
@@ -0,0 +1 @@
|
1088
|
-
+This should not render
|
1089
|
-
|
1090
|
-
diff --git a/spec/public/controller/controllers/views/merb/test/fixtures/test_local_provides/index.xml.erb b/spec/public/controller/controllers/views/merb/test/fixtures/test_local_provides/index.xml.erb
|
1091
|
-
new file mode 100644
|
1092
|
-
index 0000000000000000000000000000000000000000..c1384ec6af0357b585cc367035d1bc3a30347ade
|
1093
|
-
--- /dev/null
|
1094
|
-
+++ b/spec/public/controller/controllers/views/merb/test/fixtures/test_local_provides/index.xml.erb
|
1095
|
-
@@ -0,0 +1 @@
|
1096
|
-
+<XML:Local provides='true' />
|
1097
|
-
|
1098
|
-
diff --git a/spec/public/controller/responder_spec.rb b/spec/public/controller/responder_spec.rb
|
1099
|
-
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..bcf18532442e5965cf6ca8501770d7b7a1eb2429 100644
|
1100
|
-
--- a/spec/public/controller/responder_spec.rb
|
1101
|
-
+++ b/spec/public/controller/responder_spec.rb
|
1102
|
-
@@ -0,0 +1,31 @@
|
1103
|
-
+require File.join(File.dirname(__FILE__), "spec_helper")
|
1104
|
-
+
|
1105
|
-
+describe Merb::Controller, " responds" do
|
1106
|
-
+
|
1107
|
-
+ before do
|
1108
|
-
+ Merb.push_path(:layout, File.dirname(__FILE__) / "controllers" / "views" / "layouts")
|
1109
|
-
+ Merb::Router.prepare do |r|
|
1110
|
-
+ r.default_routes
|
1111
|
-
+ end
|
1112
|
-
+ end
|
1113
|
-
+
|
1114
|
-
+ it "should default the mime-type to HTML" do
|
1115
|
-
+ dispatch_to(Merb::Test::Fixtures::TestHtmlDefault, :index).body.should == "HTML: Default"
|
1116
|
-
+ end
|
1117
|
-
+
|
1118
|
-
+ it "should use other mime-types if they are provided on the class level" do
|
1119
|
-
+ controller = dispatch_to(Merb::Test::Fixtures::TestClassProvides, :index, {}, :http_accept => "application/xml")
|
1120
|
-
+ controller.body.should == "<XML:Class provides='true' />"
|
1121
|
-
+ end
|
1122
|
-
+
|
1123
|
-
+ it "should fail if none of the acceptable mime-types are available" do
|
1124
|
-
+ calling { dispatch_to(Merb::Test::Fixtures::TestClassProvides, :index, {}, :http_accept => "application/json") }.
|
1125
|
-
+ should raise_error(Merb::ControllerExceptions::NotAcceptable)
|
1126
|
-
+ end
|
1127
|
-
+
|
1128
|
-
+ it "should use mime-types that are provided at the local level" do
|
1129
|
-
+ controller = dispatch_to(Merb::Test::Fixtures::TestLocalProvides, :index, {}, :http_accept => "application/xml")
|
1130
|
-
+ controller.body.should == "<XML:Local provides='true' />"
|
1131
|
-
+ end
|
1132
|
-
+
|
1133
|
-
+end
|
1134
|
-
|
1135
|
-
diff --git a/spec/public/controller/spec_helper.rb b/spec/public/controller/spec_helper.rb
|
1136
|
-
index f68628a63740f4ce0235a15d71c5889e55ecaf78..e360194c1fbaf72c3298c61543c2d3a19b512b41 100644
|
1137
|
-
--- a/spec/public/controller/spec_helper.rb
|
1138
|
-
+++ b/spec/public/controller/spec_helper.rb
|
1139
|
-
@@ -1,4 +1,10 @@
|
1140
|
-
__DIR__ = File.dirname(__FILE__)
|
1141
|
-
+require 'ruby-debug'
|
1142
|
-
+
|
1143
|
-
require File.join(__DIR__, "..", "..", "spec_helper")
|
1144
|
-
|
1145
|
-
-require File.join(__DIR__, "controllers", "base")
|
1146
|
-
|
1147
|
-
+require File.join(__DIR__, "controllers", "base")
|
1148
|
-
+require File.join(__DIR__, "controllers", "responder")
|
1149
|
-
+
|
1150
|
-
+Merb::BootLoader::Templates.run
|
1151
|
-
+Merb::BootLoader::MimeTypes.run
|
1152
|
-
|