merb 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +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
|