git-trip 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/History.txt +21 -0
- data/Manifest.txt +89 -0
- data/README.txt +60 -0
- data/Rakefile +31 -0
- data/bin/git-trip +0 -0
- data/doc/USAGE.txt +54 -0
- data/lib/core_ext/hash.rb +15 -0
- data/lib/git-trip.rb +23 -0
- data/lib/git-trip/errors.rb +22 -0
- data/lib/git-trip/gitter.rb +10 -0
- data/lib/git-trip/gitter/base.rb +18 -0
- data/lib/git-trip/gitter/dir.rb +32 -0
- data/lib/git-trip/gitter/uri.rb +40 -0
- data/lib/git-trip/paint_mode.rb +52 -0
- data/lib/git-trip/painter.rb +167 -0
- data/spec/core_ext/hash_spec.rb +25 -0
- data/spec/git-trip/errors_spec.rb +43 -0
- data/spec/git-trip/gitter/base_spec.rb +15 -0
- data/spec/git-trip/gitter/dir_spec.rb +37 -0
- data/spec/git-trip/gitter/uri_spec.rb +25 -0
- data/spec/git-trip/gitter_spec.rb +11 -0
- data/spec/git-trip/paint_mode_spec.rb +56 -0
- data/spec/git-trip/painter_spec.rb +173 -0
- data/spec/git_trip_spec.rb +23 -0
- data/spec/rcov.opts +1 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +15 -0
- data/tasks/ditz.rake +42 -0
- data/tasks/docs.rake +68 -0
- data/tasks/gittrip.rake +63 -0
- data/tasks/rspec.rake +22 -0
- data/tasks/site.rake +48 -0
- data/tasks/util.rake +44 -0
- data/vendor/grit/History.txt +6 -0
- data/vendor/grit/Manifest.txt +53 -0
- data/vendor/grit/README.txt +213 -0
- data/vendor/grit/Rakefile +29 -0
- data/vendor/grit/grit.gemspec +16 -0
- data/vendor/grit/lib/grit.rb +37 -0
- data/vendor/grit/lib/grit/actor.rb +36 -0
- data/vendor/grit/lib/grit/blob.rb +117 -0
- data/vendor/grit/lib/grit/commit.rb +208 -0
- data/vendor/grit/lib/grit/config.rb +44 -0
- data/vendor/grit/lib/grit/diff.rb +70 -0
- data/vendor/grit/lib/grit/errors.rb +7 -0
- data/vendor/grit/lib/grit/git.rb +116 -0
- data/vendor/grit/lib/grit/index.rb +77 -0
- data/vendor/grit/lib/grit/lazy.rb +31 -0
- data/vendor/grit/lib/grit/ref.rb +110 -0
- data/vendor/grit/lib/grit/repo.rb +318 -0
- data/vendor/grit/lib/grit/tree.rb +99 -0
- data/vendor/grit/test/fixtures/blame +131 -0
- data/vendor/grit/test/fixtures/cat_file_blob +1 -0
- data/vendor/grit/test/fixtures/cat_file_blob_size +1 -0
- data/vendor/grit/test/fixtures/diff_2 +54 -0
- data/vendor/grit/test/fixtures/diff_2f +19 -0
- data/vendor/grit/test/fixtures/diff_f +15 -0
- data/vendor/grit/test/fixtures/diff_i +201 -0
- data/vendor/grit/test/fixtures/diff_mode_only +1152 -0
- data/vendor/grit/test/fixtures/diff_new_mode +17 -0
- data/vendor/grit/test/fixtures/diff_p +610 -0
- data/vendor/grit/test/fixtures/for_each_ref +0 -0
- data/vendor/grit/test/fixtures/for_each_ref_remotes +0 -0
- data/vendor/grit/test/fixtures/for_each_ref_tags +0 -0
- data/vendor/grit/test/fixtures/ls_tree_a +7 -0
- data/vendor/grit/test/fixtures/ls_tree_b +2 -0
- data/vendor/grit/test/fixtures/ls_tree_commit +3 -0
- data/vendor/grit/test/fixtures/rev_list +26 -0
- data/vendor/grit/test/fixtures/rev_list_count +655 -0
- data/vendor/grit/test/fixtures/rev_list_single +7 -0
- data/vendor/grit/test/fixtures/rev_parse +1 -0
- data/vendor/grit/test/fixtures/show_empty_commit +6 -0
- data/vendor/grit/test/fixtures/simple_config +2 -0
- data/vendor/grit/test/helper.rb +17 -0
- data/vendor/grit/test/profile.rb +21 -0
- data/vendor/grit/test/suite.rb +6 -0
- data/vendor/grit/test/test_actor.rb +35 -0
- data/vendor/grit/test/test_blob.rb +74 -0
- data/vendor/grit/test/test_commit.rb +182 -0
- data/vendor/grit/test/test_config.rb +58 -0
- data/vendor/grit/test/test_diff.rb +18 -0
- data/vendor/grit/test/test_git.rb +52 -0
- data/vendor/grit/test/test_head.rb +22 -0
- data/vendor/grit/test/test_real.rb +19 -0
- data/vendor/grit/test/test_reality.rb +17 -0
- data/vendor/grit/test/test_remote.rb +15 -0
- data/vendor/grit/test/test_repo.rb +278 -0
- data/vendor/grit/test/test_tag.rb +29 -0
- data/vendor/grit/test/test_tree.rb +91 -0
- metadata +179 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1 @@
|
|
1
|
+
Hello world
|
@@ -0,0 +1 @@
|
|
1
|
+
11
|
@@ -0,0 +1,54 @@
|
|
1
|
+
diff --git a/lib/grit/commit.rb b/lib/grit/commit.rb
|
2
|
+
index a093bb1db8e884cccf396b297259181d1caebed4..80fd3d527f269ecbd570b65b8e21fd85baedb6e9 100644
|
3
|
+
--- a/lib/grit/commit.rb
|
4
|
+
+++ b/lib/grit/commit.rb
|
5
|
+
@@ -156,12 +156,8 @@ module Grit
|
6
|
+
|
7
|
+
def diffs
|
8
|
+
if parents.empty?
|
9
|
+
- diff = @repo.git.show({:full_index => true, :pretty => 'raw'}, @id)
|
10
|
+
- if diff =~ /diff --git a/
|
11
|
+
- diff = diff.sub(/.+?(diff --git a)/m, '\1')
|
12
|
+
- else
|
13
|
+
- diff = ''
|
14
|
+
- end
|
15
|
+
+ diff = @repo.git.show({:full_index => true, :pretty => 'raw'}, @id)
|
16
|
+
+ diff = diff.sub(/.+?(diff --git a)/m, '\1')
|
17
|
+
Diff.list_from_string(@repo, diff)
|
18
|
+
else
|
19
|
+
self.class.diff(@repo, parents.first.id, @id)
|
20
|
+
diff --git a/test/fixtures/show_empty_commit b/test/fixtures/show_empty_commit
|
21
|
+
deleted file mode 100644
|
22
|
+
index ea25e32a409fdf74c1b9268820108d1c16dcc553..0000000000000000000000000000000000000000
|
23
|
+
--- a/test/fixtures/show_empty_commit
|
24
|
+
+++ /dev/null
|
25
|
+
@@ -1,6 +0,0 @@
|
26
|
+
-commit 1e3824339762bd48316fe87bfafc853732d43264
|
27
|
+
-tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904
|
28
|
+
-author Tom Preston-Werner <tom@mojombo.com> 1157392833 +0000
|
29
|
+
-committer Tom Preston-Werner <tom@mojombo.com> 1157392833 +0000
|
30
|
+
-
|
31
|
+
- initial directory structure
|
32
|
+
diff --git a/test/test_commit.rb b/test/test_commit.rb
|
33
|
+
index fdeb9000089b052f0b31a845e0173e9b089e06a0..bdbc450e08084d7d611e985cfa12fb424cab29b2 100644
|
34
|
+
--- a/test/test_commit.rb
|
35
|
+
+++ b/test/test_commit.rb
|
36
|
+
@@ -98,18 +98,6 @@ class TestCommit < Test::Unit::TestCase
|
37
|
+
assert_equal true, diffs[5].new_file
|
38
|
+
end
|
39
|
+
|
40
|
+
- def test_diffs_on_initial_import_with_empty_commit
|
41
|
+
- Git.any_instance.expects(:show).with(
|
42
|
+
- {:full_index => true, :pretty => 'raw'},
|
43
|
+
- '634396b2f541a9f2d58b00be1a07f0c358b999b3'
|
44
|
+
- ).returns(fixture('show_empty_commit'))
|
45
|
+
-
|
46
|
+
- @c = Commit.create(@r, :id => '634396b2f541a9f2d58b00be1a07f0c358b999b3')
|
47
|
+
- diffs = @c.diffs
|
48
|
+
-
|
49
|
+
- assert_equal [], diffs
|
50
|
+
- end
|
51
|
+
-
|
52
|
+
# to_s
|
53
|
+
|
54
|
+
def test_to_s
|
@@ -0,0 +1,19 @@
|
|
1
|
+
diff --git a/lib/grit/commit.rb b/lib/grit/commit.rb
|
2
|
+
index a093bb1db8e884cccf396b297259181d1caebed4..80fd3d527f269ecbd570b65b8e21fd85baedb6e9 100644
|
3
|
+
--- a/lib/grit/commit.rb
|
4
|
+
+++ b/lib/grit/commit.rb
|
5
|
+
@@ -156,12 +156,8 @@ module Grit
|
6
|
+
|
7
|
+
def diffs
|
8
|
+
if parents.empty?
|
9
|
+
- diff = @repo.git.show({:full_index => true, :pretty => 'raw'}, @id)
|
10
|
+
- if diff =~ /diff --git a/
|
11
|
+
- diff = diff.sub(/.+?(diff --git a)/m, '\1')
|
12
|
+
- else
|
13
|
+
- diff = ''
|
14
|
+
- end
|
15
|
+
+ diff = @repo.git.show({:full_index => true, :pretty => 'raw'}, @id)
|
16
|
+
+ diff = diff.sub(/.+?(diff --git a)/m, '\1')
|
17
|
+
Diff.list_from_string(@repo, diff)
|
18
|
+
else
|
19
|
+
self.class.diff(@repo, parents.first.id, @id)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
diff --git a/lib/grit/diff.rb b/lib/grit/diff.rb
|
2
|
+
index 537955bb86a8ceaa19aea89e75ccbea5ce6f2698..00b0b4a67eca9242db5f8991e99625acd55f040c 100644
|
3
|
+
--- a/lib/grit/diff.rb
|
4
|
+
+++ b/lib/grit/diff.rb
|
5
|
+
@@ -27,6 +27,10 @@ module Grit
|
6
|
+
while !lines.empty?
|
7
|
+
m, a_path, b_path = *lines.shift.match(%r{^diff --git a/(\S+) b/(\S+)$})
|
8
|
+
|
9
|
+
+ if lines.first =~ /^old mode/
|
10
|
+
+ 2.times { lines.shift }
|
11
|
+
+ end
|
12
|
+
+
|
13
|
+
new_file = false
|
14
|
+
deleted_file = false
|
15
|
+
|
@@ -0,0 +1,201 @@
|
|
1
|
+
commit 634396b2f541a9f2d58b00be1a07f0c358b999b3
|
2
|
+
Author: Tom Preston-Werner <tom@mojombo.com>
|
3
|
+
Date: Tue Oct 9 23:18:20 2007 -0700
|
4
|
+
|
5
|
+
initial grit setup
|
6
|
+
|
7
|
+
diff --git a/History.txt b/History.txt
|
8
|
+
new file mode 100644
|
9
|
+
index 0000000000000000000000000000000000000000..81d2c27608b352814cbe979a6acd678d30219678
|
10
|
+
--- /dev/null
|
11
|
+
+++ b/History.txt
|
12
|
+
@@ -0,0 +1,5 @@
|
13
|
+
+== 1.0.0 / 2007-10-09
|
14
|
+
+
|
15
|
+
+* 1 major enhancement
|
16
|
+
+ * Birthday!
|
17
|
+
+
|
18
|
+
diff --git a/Manifest.txt b/Manifest.txt
|
19
|
+
new file mode 100644
|
20
|
+
index 0000000000000000000000000000000000000000..641972d82c6d1b51122274ae8f6a0ecdfb56ee22
|
21
|
+
--- /dev/null
|
22
|
+
+++ b/Manifest.txt
|
23
|
+
@@ -0,0 +1,7 @@
|
24
|
+
+History.txt
|
25
|
+
+Manifest.txt
|
26
|
+
+README.txt
|
27
|
+
+Rakefile
|
28
|
+
+bin/grit
|
29
|
+
+lib/grit.rb
|
30
|
+
+test/test_grit.rb
|
31
|
+
|
32
|
+
diff --git a/README.txt b/README.txt
|
33
|
+
new file mode 100644
|
34
|
+
index 0000000000000000000000000000000000000000..8b1e02c0fb554eed2ce2ef737a68bb369d7527df
|
35
|
+
--- /dev/null
|
36
|
+
+++ b/README.txt
|
37
|
+
@@ -0,0 +1,48 @@
|
38
|
+
+grit
|
39
|
+
+ by FIX (your name)
|
40
|
+
+ FIX (url)
|
41
|
+
+
|
42
|
+
+== DESCRIPTION:
|
43
|
+
+
|
44
|
+
+FIX (describe your package)
|
45
|
+
+
|
46
|
+
+== FEATURES/PROBLEMS:
|
47
|
+
+
|
48
|
+
+* FIX (list of features or problems)
|
49
|
+
+
|
50
|
+
+== SYNOPSIS:
|
51
|
+
+
|
52
|
+
+ FIX (code sample of usage)
|
53
|
+
+
|
54
|
+
+== REQUIREMENTS:
|
55
|
+
+
|
56
|
+
+* FIX (list of requirements)
|
57
|
+
+
|
58
|
+
+== INSTALL:
|
59
|
+
+
|
60
|
+
+* FIX (sudo gem install, anything else)
|
61
|
+
+
|
62
|
+
+== LICENSE:
|
63
|
+
+
|
64
|
+
+(The MIT License)
|
65
|
+
+
|
66
|
+
+Copyright (c) 2007 FIX
|
67
|
+
+
|
68
|
+
+Permission is hereby granted, free of charge, to any person obtaining
|
69
|
+
+a copy of this software and associated documentation files (the
|
70
|
+
+'Software'), to deal in the Software without restriction, including
|
71
|
+
+without limitation the rights to use, copy, modify, merge, publish,
|
72
|
+
+distribute, sublicense, and/or sell copies of the Software, and to
|
73
|
+
+permit persons to whom the Software is furnished to do so, subject to
|
74
|
+
+the following conditions:
|
75
|
+
+
|
76
|
+
+The above copyright notice and this permission notice shall be
|
77
|
+
+included in all copies or substantial portions of the Software.
|
78
|
+
+
|
79
|
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
80
|
+
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
81
|
+
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
82
|
+
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
83
|
+
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
84
|
+
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
85
|
+
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
86
|
+
diff --git a/Rakefile b/Rakefile
|
87
|
+
new file mode 100644
|
88
|
+
index 0000000000000000000000000000000000000000..ff69c3684a18592c741332b290492aa39d980e02
|
89
|
+
--- /dev/null
|
90
|
+
+++ b/Rakefile
|
91
|
+
@@ -0,0 +1,17 @@
|
92
|
+
+# -*- ruby -*-
|
93
|
+
+
|
94
|
+
+require 'rubygems'
|
95
|
+
+require 'hoe'
|
96
|
+
+require './lib/grit.rb'
|
97
|
+
+
|
98
|
+
+Hoe.new('grit', Grit::VERSION) do |p|
|
99
|
+
+ p.rubyforge_name = 'grit'
|
100
|
+
+ # p.author = 'FIX'
|
101
|
+
+ # p.email = 'FIX'
|
102
|
+
+ # p.summary = 'FIX'
|
103
|
+
+ # p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
|
104
|
+
+ # p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
|
105
|
+
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
106
|
+
+end
|
107
|
+
+
|
108
|
+
+# vim: syntax=Ruby
|
109
|
+
diff --git a/bin/grit b/bin/grit
|
110
|
+
new file mode 100644
|
111
|
+
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
|
112
|
+
diff --git a/lib/grit.rb b/lib/grit.rb
|
113
|
+
new file mode 100644
|
114
|
+
index 0000000000000000000000000000000000000000..32cec87d1e78946a827ddf6a8776be4d81dcf1d1
|
115
|
+
--- /dev/null
|
116
|
+
+++ b/lib/grit.rb
|
117
|
+
@@ -0,0 +1,12 @@
|
118
|
+
+$:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
|
119
|
+
+
|
120
|
+
+# core
|
121
|
+
+
|
122
|
+
+# stdlib
|
123
|
+
+
|
124
|
+
+# internal requires
|
125
|
+
+require 'grit/grit'
|
126
|
+
+
|
127
|
+
+class Grit
|
128
|
+
+ VERSION = '1.0.0'
|
129
|
+
+end
|
130
|
+
|
131
|
+
diff --git a/lib/grit/errors.rb b/lib/grit/errors.rb
|
132
|
+
new file mode 100644
|
133
|
+
index 0000000000000000000000000000000000000000..b3be31553741937607a89be8b6a2ab1df208852e
|
134
|
+
--- /dev/null
|
135
|
+
+++ b/lib/grit/errors.rb
|
136
|
+
@@ -0,0 +1,4 @@
|
137
|
+
+class Grit
|
138
|
+
+ class InvalidGitRepositoryError < StandardError
|
139
|
+
+ end
|
140
|
+
+end
|
141
|
+
|
142
|
+
diff --git a/lib/grit/grit.rb b/lib/grit/grit.rb
|
143
|
+
new file mode 100644
|
144
|
+
index 0000000000000000000000000000000000000000..48fd36e16081ec09903f7a0e2253b3d16f9efb01
|
145
|
+
--- /dev/null
|
146
|
+
+++ b/lib/grit/grit.rb
|
147
|
+
@@ -0,0 +1,24 @@
|
148
|
+
+class Grit
|
149
|
+
+ attr_accessor :path
|
150
|
+
+
|
151
|
+
+ # Create a new Grit instance
|
152
|
+
+ # +path+ is the path to either the root git directory or the bare git repo
|
153
|
+
+ #
|
154
|
+
+ # Examples
|
155
|
+
+ # g = Grit.new("/Users/tom/dev/grit")
|
156
|
+
+ # g = Grit.new("/Users/tom/public/grit.git")
|
157
|
+
+ def initialize(path)
|
158
|
+
+ if File.exist?(File.join(path, '.git'))
|
159
|
+
+ self.path = File.join(path, '.git')
|
160
|
+
+ elsif File.exist?(path) && path =~ /\.git$/
|
161
|
+
+ self.path = path
|
162
|
+
+ else
|
163
|
+
+ raise InvalidGitRepositoryError.new(path) unless File.exist?(path)
|
164
|
+
+ end
|
165
|
+
+ end
|
166
|
+
+
|
167
|
+
+ # Return the project's description. Taken verbatim from REPO/description
|
168
|
+
+ def description
|
169
|
+
+ File.open(File.join(self.path, 'description')).read.chomp
|
170
|
+
+ end
|
171
|
+
+end
|
172
|
+
|
173
|
+
diff --git a/test/helper.rb b/test/helper.rb
|
174
|
+
new file mode 100644
|
175
|
+
index 0000000000000000000000000000000000000000..56e21da6b4ce3021d2754775dfa589947a4e37e5
|
176
|
+
--- /dev/null
|
177
|
+
+++ b/test/helper.rb
|
178
|
+
@@ -0,0 +1,5 @@
|
179
|
+
+require File.join(File.dirname(__FILE__), *%w[.. lib grit])
|
180
|
+
+
|
181
|
+
+require 'test/unit'
|
182
|
+
+
|
183
|
+
+GRIT_REPO = File.join(File.dirname(__FILE__), *%w[..])
|
184
|
+
diff --git a/test/test_grit.rb b/test/test_grit.rb
|
185
|
+
new file mode 100644
|
186
|
+
index 0000000000000000000000000000000000000000..93aa481b37629797df739380306ae689e13f2855
|
187
|
+
--- /dev/null
|
188
|
+
+++ b/test/test_grit.rb
|
189
|
+
@@ -0,0 +1,11 @@
|
190
|
+
+require File.dirname(__FILE__) + '/helper'
|
191
|
+
+
|
192
|
+
+class TestGrit < Test::Unit::TestCase
|
193
|
+
+ def setup
|
194
|
+
+ @g = Grit.new(GRIT_REPO)
|
195
|
+
+ end
|
196
|
+
+
|
197
|
+
+ def test_description
|
198
|
+
+ assert_equal "Grit is a ruby library for interfacing with git repositories.", @g.description
|
199
|
+
+ end
|
200
|
+
+end
|
201
|
+
|
@@ -0,0 +1,1152 @@
|
|
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
|
+
|