merb 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README +22 -4
- data/Rakefile +15 -3
- data/TODO +2 -3
- data/bin/merb +61 -36
- data/examples/sample_app/dist/app/controllers/files.rb +31 -0
- data/examples/sample_app/dist/app/controllers/posts.rb +26 -2
- data/examples/sample_app/dist/app/controllers/test.rb +7 -1
- data/examples/sample_app/dist/app/views/files/progress.jerb +3 -0
- data/examples/sample_app/dist/app/views/files/start.herb +62 -0
- data/examples/sample_app/dist/app/views/files/upload.herb +6 -0
- data/examples/sample_app/dist/app/views/layout/{application.rhtml → application.herb} +2 -3
- data/examples/sample_app/dist/app/views/layout/{foo.rhtml → foo.herb} +0 -0
- data/examples/sample_app/dist/app/views/posts/{_comments.rhtml → _comments.herb} +0 -0
- data/examples/sample_app/dist/app/views/posts/comment.jerb +1 -0
- data/examples/sample_app/dist/app/views/posts/{list.rhtml → list.herb} +0 -0
- data/examples/sample_app/dist/app/views/posts/{new.rhtml → new.herb} +0 -0
- data/examples/sample_app/dist/app/views/posts/{show.rhtml → show.herb} +0 -0
- data/examples/sample_app/dist/app/views/posts/xml_test.xerb +3 -0
- data/examples/sample_app/dist/app/views/test/{foo.rhtml → foo.herb} +0 -0
- data/examples/sample_app/dist/app/views/test/{hello.rhtml → hello.herb} +0 -0
- data/examples/sample_app/dist/app/views/test/json.jerb +1 -0
- data/examples/sample_app/dist/conf/merb.yml +11 -0
- data/examples/sample_app/dist/conf/merb_init.rb +1 -1
- data/examples/sample_app/dist/conf/mup.conf +11 -0
- data/examples/sample_app/dist/public/javascripts/mup.js +113 -0
- data/examples/sample_app/script/merb_stop +7 -3
- data/examples/sample_app/script/startdrb +8 -0
- data/lib/merb.rb +37 -2
- data/lib/merb/merb_class_extensions.rb +21 -22
- data/lib/merb/merb_controller.rb +101 -33
- data/lib/merb/merb_handler.rb +26 -25
- data/lib/merb/merb_router.rb +1 -1
- data/lib/merb/merb_utils.rb +35 -37
- data/lib/merb/mixins/basic_authentication_mixin.rb +39 -0
- data/lib/merb/mixins/controller_mixin.rb +119 -115
- data/lib/merb/mixins/javascript_mixin.rb +63 -0
- data/lib/merb/mixins/render_mixin.rb +85 -69
- data/lib/merb/mixins/responder_mixin.rb +38 -0
- data/lib/merb/session/merb_drb_server.rb +107 -0
- data/lib/merb/session/merb_drb_session.rb +71 -0
- data/lib/merb/session/merb_session.rb +1 -0
- data/lib/merb/vendor/paginator/README.txt +84 -0
- data/lib/merb/vendor/paginator/paginator.rb +121 -0
- data/lib/mutex_hotfix.rb +34 -0
- metadata +41 -63
- data/doc/rdoc/classes/ControllerMixin.html +0 -676
- data/doc/rdoc/classes/Hash.html +0 -148
- data/doc/rdoc/classes/Merb.html +0 -140
- data/doc/rdoc/classes/Merb/Controller.html +0 -338
- data/doc/rdoc/classes/Merb/RouteMatcher.html +0 -388
- data/doc/rdoc/classes/Merb/Server.html +0 -148
- data/doc/rdoc/classes/Merb/Session.html +0 -201
- data/doc/rdoc/classes/Merb/SessionMixin.html +0 -199
- data/doc/rdoc/classes/MerbControllerError.html +0 -111
- data/doc/rdoc/classes/MerbHandler.html +0 -430
- data/doc/rdoc/classes/MerbHash.html +0 -469
- data/doc/rdoc/classes/MerbHash/Mutex.html +0 -198
- data/doc/rdoc/classes/Noroutefound.html +0 -153
- data/doc/rdoc/classes/Object.html +0 -149
- data/doc/rdoc/classes/RenderMixin.html +0 -362
- data/doc/rdoc/classes/String.html +0 -212
- data/doc/rdoc/classes/Symbol.html +0 -179
- data/doc/rdoc/created.rid +0 -1
- data/doc/rdoc/files/LICENSE.html +0 -129
- data/doc/rdoc/files/README.html +0 -417
- data/doc/rdoc/files/TODO.html +0 -151
- data/doc/rdoc/files/lib/merb/merb_class_extensions_rb.html +0 -101
- data/doc/rdoc/files/lib/merb/merb_controller_rb.html +0 -101
- data/doc/rdoc/files/lib/merb/merb_handler_rb.html +0 -101
- data/doc/rdoc/files/lib/merb/merb_router_rb.html +0 -101
- data/doc/rdoc/files/lib/merb/merb_utils_rb.html +0 -108
- data/doc/rdoc/files/lib/merb/mixins/controller_mixin_rb.html +0 -101
- data/doc/rdoc/files/lib/merb/mixins/render_mixin_rb.html +0 -101
- data/doc/rdoc/files/lib/merb/session/merb_session_rb.html +0 -101
- data/doc/rdoc/files/lib/merb_rb.html +0 -140
- data/doc/rdoc/files/lib/merb_tasks_rb.html +0 -101
- data/doc/rdoc/fr_class_index.html +0 -43
- data/doc/rdoc/fr_file_index.html +0 -40
- data/doc/rdoc/fr_method_index.html +0 -104
- data/doc/rdoc/index.html +0 -24
- data/doc/rdoc/rdoc-style.css +0 -208
- data/examples/sample_app/dist/app/controllers/upload.rb +0 -29
- data/examples/sample_app/dist/app/views/posts/comment.merbjs +0 -1
- data/examples/sample_app/dist/app/views/upload/start.rhtml +0 -15
- data/examples/sample_app/dist/app/views/upload/upload.rhtml +0 -4
- data/examples/sample_app/dist/public/files/README +0 -35
- data/examples/sample_app/dist/public/files/setup.rb +0 -1346
- data/examples/sample_app/log/merb.log +0 -778
@@ -4,9 +4,8 @@
|
|
4
4
|
<head>
|
5
5
|
<title>Merb: Mongrel + Erb</title>
|
6
6
|
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
7
|
-
|
8
|
-
|
9
|
-
<script src="/javascripts/effects.js" type="text/javascript"></script>
|
7
|
+
<%= require_css :merb %>
|
8
|
+
<%= require_js :prototype, :effects %>
|
10
9
|
</head>
|
11
10
|
|
12
11
|
<body>
|
File without changes
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
$('comments').update(<%=js partial(:comments) %>);
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= @post.attributes.inspect.to_json %>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
uri "/",
|
2
|
+
:handler => plugin("/handlers/upload", :path_info => '/files/upload'),
|
3
|
+
:in_front => true,
|
4
|
+
:frequency => 1
|
5
|
+
|
6
|
+
#uri "/",
|
7
|
+
# :handler => plugin("/handlers/upload",
|
8
|
+
# :path_info => '/files/upload',
|
9
|
+
# :frequency => 1,
|
10
|
+
# :drb => 'druby://0.0.0.0:2999'),
|
11
|
+
# :in_front => true
|
@@ -0,0 +1,113 @@
|
|
1
|
+
var UploadProgress = {
|
2
|
+
uploading: null,
|
3
|
+
monitor: function(upid) {
|
4
|
+
if(!this.periodicExecuter) {
|
5
|
+
this.periodicExecuter = new PeriodicalExecuter(function() {
|
6
|
+
if(!UploadProgress.uploading) return;
|
7
|
+
new Ajax.Request('/files/progress?upload_id=' + upid);
|
8
|
+
}, 3);
|
9
|
+
}
|
10
|
+
|
11
|
+
this.uploading = true;
|
12
|
+
this.StatusBar.create();
|
13
|
+
},
|
14
|
+
|
15
|
+
update: function(total, current) {
|
16
|
+
if(!this.uploading) return;
|
17
|
+
var status = current / total;
|
18
|
+
var statusHTML = status.toPercentage();
|
19
|
+
$('results').innerHTML = statusHTML + "<br /><small>" + current.toHumanSize() + ' of ' + total.toHumanSize() + " uploaded.</small>";
|
20
|
+
this.StatusBar.update(status, statusHTML);
|
21
|
+
},
|
22
|
+
|
23
|
+
finish: function() {
|
24
|
+
this.uploading = false;
|
25
|
+
this.StatusBar.finish();
|
26
|
+
$('results').innerHTML = 'finished!';
|
27
|
+
},
|
28
|
+
|
29
|
+
cancel: function(msg) {
|
30
|
+
if(!this.uploading) return;
|
31
|
+
this.uploading = false;
|
32
|
+
if(this.StatusBar.statusText) this.StatusBar.statusText.innerHTML = msg || 'canceled';
|
33
|
+
},
|
34
|
+
|
35
|
+
StatusBar: {
|
36
|
+
statusBar: null,
|
37
|
+
statusText: null,
|
38
|
+
statusBarWidth: 500,
|
39
|
+
|
40
|
+
create: function() {
|
41
|
+
this.statusBar = this._createStatus('status-bar');
|
42
|
+
this.statusText = this._createStatus('status-text');
|
43
|
+
this.statusText.innerHTML = '0%';
|
44
|
+
this.statusBar.style.width = '0';
|
45
|
+
},
|
46
|
+
|
47
|
+
update: function(status, statusHTML) {
|
48
|
+
this.statusText.innerHTML = statusHTML;
|
49
|
+
this.statusBar.style.width = Math.floor(this.statusBarWidth * status);
|
50
|
+
},
|
51
|
+
|
52
|
+
finish: function() {
|
53
|
+
this.statusText.innerHTML = '100%';
|
54
|
+
this.statusBar.style.width = '100%';
|
55
|
+
},
|
56
|
+
|
57
|
+
_createStatus: function(id) {
|
58
|
+
el = $(id);
|
59
|
+
if(!el) {
|
60
|
+
el = document.createElement('span');
|
61
|
+
el.setAttribute('id', id);
|
62
|
+
$('progress-bar').appendChild(el);
|
63
|
+
}
|
64
|
+
return el;
|
65
|
+
}
|
66
|
+
},
|
67
|
+
|
68
|
+
FileField: {
|
69
|
+
add: function() {
|
70
|
+
new Insertion.Bottom('file-fields', '<p style="display:none"><input id="data" name="data" type="file" /> <a href="#" onclick="UploadProgress.FileField.remove(this);return false;">x</a></p>')
|
71
|
+
$$('#file-fields p').last().visualEffect('blind_down', {duration:0.3});
|
72
|
+
},
|
73
|
+
|
74
|
+
remove: function(anchor) {
|
75
|
+
anchor.parentNode.visualEffect('drop_out', {duration:0.25});
|
76
|
+
}
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
Number.prototype.bytes = function() { return this; };
|
81
|
+
Number.prototype.kilobytes = function() { return this * 1024; };
|
82
|
+
Number.prototype.megabytes = function() { return this * (1024).kilobytes(); };
|
83
|
+
Number.prototype.gigabytes = function() { return this * (1024).megabytes(); };
|
84
|
+
Number.prototype.terabytes = function() { return this * (1024).gigabytes(); };
|
85
|
+
Number.prototype.petabytes = function() { return this * (1024).terabytes(); };
|
86
|
+
Number.prototype.exabytes = function() { return this * (1024).petabytes(); };
|
87
|
+
['byte', 'kilobyte', 'megabyte', 'gigabyte', 'terabyte', 'petabyte', 'exabyte'].each(function(meth) {
|
88
|
+
Number.prototype[meth] = Number.prototype[meth+'s'];
|
89
|
+
});
|
90
|
+
|
91
|
+
Number.prototype.toPrecision = function() {
|
92
|
+
var precision = arguments[0] || 2;
|
93
|
+
var s = Math.round(this * Math.pow(10, precision)).toString();
|
94
|
+
var pos = s.length - precision;
|
95
|
+
var last = s.substr(pos, precision);
|
96
|
+
return s.substr(0, pos) + (last.match("^0{" + precision + "}$") ? '' : '.' + last);
|
97
|
+
}
|
98
|
+
|
99
|
+
// (1/10).toPercentage()
|
100
|
+
// # => '10%'
|
101
|
+
Number.prototype.toPercentage = function() {
|
102
|
+
return (this * 100).toPrecision() + '%';
|
103
|
+
}
|
104
|
+
|
105
|
+
Number.prototype.toHumanSize = function() {
|
106
|
+
if(this < (1).kilobyte()) return this + " Bytes";
|
107
|
+
if(this < (1).megabyte()) return (this / (1).kilobyte()).toPrecision() + ' KB';
|
108
|
+
if(this < (1).gigabytes()) return (this / (1).megabyte()).toPrecision() + ' MB';
|
109
|
+
if(this < (1).terabytes()) return (this / (1).gigabytes()).toPrecision() + ' GB';
|
110
|
+
if(this < (1).petabytes()) return (this / (1).terabytes()).toPrecision() + ' TB';
|
111
|
+
if(this < (1).exabytes()) return (this / (1).petabytes()).toPrecision() + ' PB';
|
112
|
+
return (this / (1).exabytes()).toPrecision() + ' EB';
|
113
|
+
}
|
@@ -1,9 +1,13 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'fileutils'
|
3
|
-
pids = IO.readlines(File.dirname(__FILE__)+"/../log/merb.pid").map{|p| p.to_i}
|
4
3
|
|
5
|
-
pids
|
4
|
+
pids=[]
|
5
|
+
|
6
|
+
port_or_star = ARGV[0] || '*'
|
7
|
+
|
8
|
+
Dir[File.dirname(__FILE__)+"/../log/merb.#{port_or_star}.pid"].each do |f|
|
9
|
+
pid = IO.read(f).chomp.to_i
|
6
10
|
puts "killing PID: #{pid}"
|
7
11
|
Process.kill(9, pid)
|
12
|
+
FileUtils.rm f
|
8
13
|
end
|
9
|
-
FileUtils.rm File.dirname(__FILE__)+"/../log/merb.pid"
|
data/lib/merb.rb
CHANGED
@@ -5,7 +5,7 @@ require 'erubis'
|
|
5
5
|
require 'logger'
|
6
6
|
|
7
7
|
module Merb
|
8
|
-
VERSION='0.0.
|
8
|
+
VERSION='0.0.7' unless defined?VERSION
|
9
9
|
class Server
|
10
10
|
def self.config
|
11
11
|
@@merb_opts ||= {}
|
@@ -16,8 +16,43 @@ end
|
|
16
16
|
class MerbControllerError < RuntimeError; end
|
17
17
|
|
18
18
|
MERB_FRAMEWORK_ROOT = File.dirname(__FILE__)
|
19
|
+
|
20
|
+
begin
|
21
|
+
require 'thread'
|
22
|
+
require 'fastthread'
|
23
|
+
puts 'Using FastThread'
|
24
|
+
rescue LoadError
|
25
|
+
require 'mutex_hotfix'
|
26
|
+
end
|
27
|
+
|
28
|
+
begin
|
29
|
+
require 'fjson'
|
30
|
+
puts "using fjson"
|
31
|
+
rescue LoadError
|
32
|
+
require 'json'
|
33
|
+
end
|
34
|
+
|
19
35
|
MERB_ROOT = Merb::Server.config[:merb_root] || Dir.pwd
|
20
36
|
DIST_ROOT = Merb::Server.config[:dist_root] || Dir.pwd+'/dist'
|
21
|
-
|
37
|
+
|
38
|
+
MERB_LOGGER = Logger.new("#{MERB_ROOT}/log/merb.log")
|
39
|
+
# DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN
|
40
|
+
MERB_LOGGER.level = case (Merb::Server.config[:log_level].downcase rescue '')
|
41
|
+
when 'debug'
|
42
|
+
Logger::DEBUG
|
43
|
+
when 'info'
|
44
|
+
Logger::INFO
|
45
|
+
when 'warn'
|
46
|
+
Logger::WARN
|
47
|
+
when 'error'
|
48
|
+
Logger::ERROR
|
49
|
+
when 'fatal'
|
50
|
+
Logger::FATAL
|
51
|
+
when 'unknown'
|
52
|
+
Logger::UNKNOWN
|
53
|
+
else
|
54
|
+
Logger::INFO
|
55
|
+
end
|
56
|
+
|
22
57
|
lib = File.join(File.dirname(__FILE__), 'merb')
|
23
58
|
Dir.entries(lib).sort.each {|fn| require File.join(lib, fn) if fn =~ /\.rb$/}
|
@@ -1,9 +1,9 @@
|
|
1
1
|
class Class # :nodoc:
|
2
|
-
def
|
2
|
+
def meta_reader(*syms)
|
3
3
|
syms.each do |sym|
|
4
4
|
class_eval <<-EOS
|
5
5
|
def self.#{sym}
|
6
|
-
|
6
|
+
read_meta_attribute(:#{sym})
|
7
7
|
end
|
8
8
|
|
9
9
|
def #{sym}
|
@@ -13,11 +13,11 @@ class Class # :nodoc:
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
16
|
+
def meta_writer(*syms)
|
17
17
|
syms.each do |sym|
|
18
18
|
class_eval <<-EOS
|
19
19
|
def self.#{sym}=(obj)
|
20
|
-
|
20
|
+
write_meta_attribute(:#{sym}, obj)
|
21
21
|
end
|
22
22
|
|
23
23
|
def #{sym}=(obj)
|
@@ -27,39 +27,38 @@ class Class # :nodoc:
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
inheritable_writer(*syms)
|
30
|
+
def meta_accessor(*syms)
|
31
|
+
meta_reader(*syms)
|
32
|
+
meta_writer(*syms)
|
34
33
|
end
|
35
34
|
|
36
|
-
def
|
37
|
-
@
|
35
|
+
def meta_attributes
|
36
|
+
@meta_attributes ||= {}
|
38
37
|
end
|
39
38
|
|
40
|
-
def
|
41
|
-
|
39
|
+
def write_meta_attribute(key, value)
|
40
|
+
meta_attributes[key] = value
|
42
41
|
end
|
43
42
|
|
44
|
-
def
|
45
|
-
|
43
|
+
def read_meta_attribute(key)
|
44
|
+
meta_attributes[key]
|
46
45
|
end
|
47
46
|
|
48
|
-
def
|
49
|
-
|
47
|
+
def reset_meta_attributes
|
48
|
+
meta_attributes.clear
|
50
49
|
end
|
51
50
|
|
52
51
|
private
|
53
|
-
def
|
54
|
-
|
52
|
+
def inherited_with_meta_attributes(child)
|
53
|
+
inherited_without_meta_attributes(child) if respond_to?(:inherited_without_meta_attributes)
|
55
54
|
|
56
|
-
|
55
|
+
new_meta_attributes = meta_attributes.inject({}) do |memo, (key, value)|
|
57
56
|
memo.update(key => (value.dup rescue value))
|
58
57
|
end
|
59
58
|
|
60
|
-
child.instance_variable_set('@
|
59
|
+
child.instance_variable_set('@meta_attributes', new_meta_attributes)
|
61
60
|
end
|
62
61
|
|
63
|
-
alias
|
64
|
-
alias inherited
|
62
|
+
alias inherited_without_meta_attributes inherited
|
63
|
+
alias inherited inherited_with_meta_attributes
|
65
64
|
end
|
data/lib/merb/merb_controller.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require File.dirname(__FILE__)+'/mixins/controller_mixin'
|
2
2
|
require File.dirname(__FILE__)+'/mixins/render_mixin'
|
3
|
+
require File.dirname(__FILE__)+'/mixins/javascript_mixin'
|
4
|
+
require File.dirname(__FILE__)+'/mixins/responder_mixin'
|
3
5
|
|
4
6
|
module Merb
|
5
7
|
|
@@ -10,30 +12,36 @@ module Merb
|
|
10
12
|
# to your controller via params. It also parses the ?query=string and
|
11
13
|
# puts that into params as well.
|
12
14
|
class Controller
|
13
|
-
include ::ControllerMixin
|
14
|
-
include ::RenderMixin
|
15
|
+
include Merb::ControllerMixin
|
16
|
+
include Merb::RenderMixin
|
17
|
+
include Merb::JavascriptMixin
|
18
|
+
include Merb::ResponderMixin
|
15
19
|
|
16
20
|
if Merb::Server.config[:session]
|
17
|
-
require
|
21
|
+
require "drb"
|
22
|
+
DRb.start_service('druby://localhost:0')
|
23
|
+
Merb.const_set :DRbSession, DRbObject.new(nil, "druby://#{Merb::Server.config[:host]}:#{Merb::Server.config[:session]}")
|
24
|
+
require File.dirname(__FILE__)+"/session/merb_drb_session"
|
18
25
|
include ::Merb::SessionMixin
|
19
|
-
puts "session mixed in"
|
26
|
+
puts "drb session mixed in"
|
20
27
|
end
|
21
28
|
|
22
|
-
attr_accessor :status
|
29
|
+
attr_accessor :status, :body
|
23
30
|
|
24
31
|
# parses the http request into params, headers and cookies
|
25
32
|
# that you can use in your controller classes. Also handles
|
26
33
|
# file uploads by writing a tempfile and passing a reference
|
27
34
|
# in params.
|
28
|
-
def initialize(req, env, args, method=(env['REQUEST_METHOD']||
|
35
|
+
def initialize(req, env, args, method=(env['REQUEST_METHOD']||'GET'))
|
29
36
|
env = MerbHash[env.to_hash]
|
30
|
-
@layout =
|
31
|
-
@status, @method, @env, @headers, @root = 200, method.downcase, env,
|
32
|
-
{'Content-Type'=>'text/html'}, env['SCRIPT_NAME'].sub(/\/$/,'')
|
37
|
+
@layout = :application
|
38
|
+
@status, @method, @env, @headers, @root = 200, method.downcase.to_sym, env,
|
39
|
+
{'Content-Type' =>'text/html'}, env['SCRIPT_NAME'].sub(/\/$/,'')
|
33
40
|
@k = query_parse(env['HTTP_COOKIE'], ';,')
|
34
41
|
qs = query_parse(env['QUERY_STRING'])
|
42
|
+
#puts req.read; req.rewind
|
35
43
|
@in = req
|
36
|
-
if %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)|n
|
44
|
+
if %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)|n =~ (env['CONTENT_TYPE'])
|
37
45
|
b = /(?:\r?\n|\A)#{Regexp::quote("--#$1")}(?:--)?\r$/
|
38
46
|
until @in.eof?
|
39
47
|
fh=MerbHash[]
|
@@ -65,21 +73,39 @@ module Merb
|
|
65
73
|
qs[fn]=fh if fn
|
66
74
|
fh[:tempfile].rewind if fh.is_a?MerbHash
|
67
75
|
end
|
68
|
-
elsif @method ==
|
69
|
-
|
76
|
+
elsif @method == :post
|
77
|
+
if ['application/json', 'text/x-json'].include?(env['CONTENT_TYPE'])
|
78
|
+
MERB_LOGGER.info("JSON Request")
|
79
|
+
json = JSON.parse(@in.read || "") || {}
|
80
|
+
json = MerbHash.new(json) if json.is_a? Hash
|
81
|
+
qs.merge!(json)
|
82
|
+
else
|
83
|
+
qs.merge!(query_parse(@in.read))
|
84
|
+
end
|
70
85
|
end
|
71
86
|
@cookies, @params = @k.dup, qs.dup.merge(args)
|
87
|
+
@cookies.merge!(:sess_id => @params.delete(:sess_id)) if @params.has_key?:sess_id
|
72
88
|
MERB_LOGGER.info("Params: #{params.inspect}")
|
73
89
|
end
|
74
90
|
|
75
|
-
def dispatch(action
|
91
|
+
def dispatch(action=:to_s)
|
92
|
+
start = Time.now
|
76
93
|
setup_session if respond_to?:setup_session
|
77
|
-
call_filters(before_filters)
|
78
|
-
|
94
|
+
if catch(:halt) { call_filters(before_filters) }
|
95
|
+
@body = send(action)
|
96
|
+
else
|
97
|
+
@body = filters_halted
|
98
|
+
end
|
79
99
|
finalize_session if respond_to?:finalize_session
|
80
|
-
|
100
|
+
MERB_LOGGER.info("Time spent in #{action} action: #{Time.now - start} seconds")
|
81
101
|
end
|
82
|
-
|
102
|
+
|
103
|
+
# override this method on your controller classes to specialize
|
104
|
+
# the output when the filter chain is halted.
|
105
|
+
def filters_halted
|
106
|
+
"<html><body><h1>Filter Chain Halted!</h1></body></html>"
|
107
|
+
end
|
108
|
+
|
83
109
|
# accessor for @params. Please use params and
|
84
110
|
# never @params directly.
|
85
111
|
def params
|
@@ -98,28 +124,70 @@ module Merb
|
|
98
124
|
@headers
|
99
125
|
end
|
100
126
|
|
101
|
-
|
127
|
+
# meta_accessor sets up a class instance variable that can
|
128
|
+
# be unique for each class but also inherits the meta attrs
|
129
|
+
# from its superclasses. Since @@class variables are almost
|
130
|
+
# global vars within an inheritance tree
|
131
|
+
meta_accessor :before_filters
|
102
132
|
|
103
133
|
def call_filters(filter_set)
|
104
|
-
(filter_set || []).each do |filter|
|
134
|
+
(filter_set || []).each do |(filter, rule)|
|
135
|
+
ok = false
|
136
|
+
if rule.has_key?(:include)
|
137
|
+
if rule[:include].include?(params[:action].intern)
|
138
|
+
ok = true
|
139
|
+
end
|
140
|
+
elsif rule.has_key?(:exclude)
|
141
|
+
if !rule[:exclude].include?(params[:action].intern)
|
142
|
+
ok = true
|
143
|
+
end
|
144
|
+
else
|
145
|
+
ok = true
|
146
|
+
end
|
105
147
|
case filter
|
106
|
-
when Symbol
|
107
|
-
|
148
|
+
when Symbol, String
|
149
|
+
send(filter) if ok
|
108
150
|
when Proc
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
151
|
+
filter.call(self) if ok
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# #before is a class method that allows you to specify before
|
157
|
+
# filters in your controllers. Filters can either before a symbol
|
158
|
+
# or string that corresponds to a method name or a proc object.
|
159
|
+
# if it is a method name that method will be called and if it
|
160
|
+
# is a proc it will be called with an argument of self. When
|
161
|
+
# you use a proc as a filter it needs to take one parameter.
|
162
|
+
def self.before(filter, opts={})
|
163
|
+
raise(ArgumentError,
|
164
|
+
"You can specify either :include or :exclude but
|
165
|
+
not both at the same time for the same filter."
|
166
|
+
) if opts.has_key?(:include) && opts.has_key?(:exclude)
|
167
|
+
|
168
|
+
if opts[:include] && opts[:include].is_a?(Symbol)
|
169
|
+
opts[:include] = [opts[:include]]
|
170
|
+
end
|
171
|
+
if opts[:exclude] && opts[:exclude].is_a?(Symbol)
|
172
|
+
opts[:exclude] = [opts[:exclude]]
|
173
|
+
end
|
174
|
+
|
175
|
+
case filter
|
176
|
+
when Symbol, String, Proc
|
177
|
+
(self.before_filters ||= []) << [filter, opts]
|
178
|
+
else
|
179
|
+
raise(MerbControllerError,
|
180
|
+
'filters need to be either a Symbol, String or a Proc'
|
181
|
+
)
|
116
182
|
end
|
117
|
-
end
|
118
|
-
|
119
|
-
def self.before(filter)
|
120
|
-
(self.before_filters ||= []) << filter
|
121
183
|
end
|
122
184
|
|
185
|
+
if Merb::Server.config[:basic_auth]
|
186
|
+
require File.dirname(__FILE__)+"/mixins/basic_authentication_mixin"
|
187
|
+
include ::Merb::Authentication
|
188
|
+
puts "Basic Authentication mixed in"
|
189
|
+
end
|
190
|
+
|
123
191
|
end
|
124
192
|
|
125
193
|
end
|
@@ -129,7 +197,7 @@ class Noroutefound < Merb::Controller
|
|
129
197
|
# match any defined routes.
|
130
198
|
def method_missing
|
131
199
|
@status = 404
|
132
|
-
"<html><body><h1>No Matching Route
|
200
|
+
"<html><body><h1>No Matching Route!</h1></body></html>"
|
133
201
|
end
|
134
202
|
|
135
203
|
end
|