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
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module Merb
|
|
2
|
+
module JavascriptMixin
|
|
3
|
+
|
|
4
|
+
# escape text for javascript.
|
|
5
|
+
def escape_js(javascript)
|
|
6
|
+
(javascript || '').gsub('\\','\0\0').gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" }
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def link_to_function(name, function)
|
|
10
|
+
%{<a href="#" onclick="#{function}; return false;">#{name}</a>}
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def js(data)
|
|
14
|
+
if data.respond_to? :to_json
|
|
15
|
+
data.to_json
|
|
16
|
+
else
|
|
17
|
+
data.inspect.to_json
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def require_js(*scripts)
|
|
22
|
+
return nil if scripts.empty?
|
|
23
|
+
scripts.inject('') do |memo,script|
|
|
24
|
+
script = script.to_s
|
|
25
|
+
memo << %Q|<script src="/javascripts/#{script=~/\.js$/ ? script : script+'.js' }" type="text/javascript">//</script>\n|
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def require_css(*scripts)
|
|
30
|
+
return nil if scripts.empty?
|
|
31
|
+
scripts.inject('') do |memo,script|
|
|
32
|
+
script = script.to_s
|
|
33
|
+
memo << %Q|<link href="/stylesheets/#{script=~/\.css$/ ? script : script+'.css' }" media="all" rel="Stylesheet" type="text/css"/>\n|
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def js_hash(options)
|
|
38
|
+
'{' + options.map {|k, v| "#{k}:#{v}"}.join(', ') + '}'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def insert_html(id, html, options = {})
|
|
42
|
+
position = options.fetch(:where, :before)
|
|
43
|
+
"new Insertion.#{position.to_s.camel_case}('#{id}', '#{escape_js html}');"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def replace_html(id, html, options = {})
|
|
47
|
+
"Element.update('#{id}', '#{escape_js html}');"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def hide(id)
|
|
51
|
+
"$('#{id}').style.display = 'none';"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def show(id)
|
|
55
|
+
"$('#{id}').style.display = 'block';"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def toggle(id)
|
|
59
|
+
"Element.toggle('#{id}');"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -1,75 +1,91 @@
|
|
|
1
|
-
module
|
|
1
|
+
module Merb
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
def template_dir(loc)
|
|
5
|
-
File.expand_path(Merb::Server.config[:merb_root] + "/dist/app/views/#{loc}")
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
# returns the current method name. Used for
|
|
9
|
-
# auto discovery of which template to render
|
|
10
|
-
# based on the action name.
|
|
11
|
-
def current_method_name(depth=0)
|
|
12
|
-
caller[depth] =~ /`(.*)'$/; $1
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
# does a render with no layout. Also sets the
|
|
16
|
-
# content type header to text/javascript and
|
|
17
|
-
# escapes the template for javascript eval on
|
|
18
|
-
# the client
|
|
19
|
-
def render_js(template=current_method_name(1), b=binding)
|
|
20
|
-
headers['Content-Type'] = "text/javascript"
|
|
21
|
-
template = Erubis::Eruby.new(IO.read( template_dir(self.class.name.snake_case) + "/#{template}.merbjs" ))
|
|
22
|
-
template.result(b)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# set the @layout. Use this right before a render to
|
|
26
|
-
# set the name of the layout to use minus the .rhtml
|
|
27
|
-
def layout(l)
|
|
28
|
-
@layout = l
|
|
29
|
-
end
|
|
3
|
+
module RenderMixin
|
|
30
4
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
name
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
5
|
+
# shortcut to a template path based on name.
|
|
6
|
+
def template_dir(loc)
|
|
7
|
+
File.expand_path(Merb::Server.config[:merb_root] + "/dist/app/views/#{loc}")
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# returns the current method name. Used for
|
|
11
|
+
# auto discovery of which template to render
|
|
12
|
+
# based on the action name.
|
|
13
|
+
def current_method_name(depth=0)
|
|
14
|
+
caller[depth] =~ /`(.*)'$/; $1
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def template_extension_for(ext)
|
|
18
|
+
Merb::Server.config[:template_ext][ext]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# does a render with no layout. Also sets the
|
|
22
|
+
# content type header to text/javascript
|
|
23
|
+
def render_js(template=current_method_name(1), b=binding)
|
|
24
|
+
headers['Content-Type'] = "text/javascript"
|
|
25
|
+
template = Erubis::Eruby.new(IO.read( template_dir(self.class.name.snake_case) + "/#{template}.#{template_extension_for(:js)}" ))
|
|
26
|
+
template.result(b)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# set the @layout. Use this right before a render to
|
|
30
|
+
# set the name of the layout to use minus the .rhtml
|
|
31
|
+
def layout(l)
|
|
32
|
+
@layout = l
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# renders nothing but sets the status
|
|
36
|
+
def render_nothing(status=200)
|
|
37
|
+
@status = status
|
|
38
|
+
return "\n"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# renders the action without wrapping it in a layout.
|
|
42
|
+
def render_no_layout(template=current_method_name(1), b=binding)
|
|
43
|
+
template = Erubis::Eruby.new( IO.read( template_dir(self.class.name.snake_case) + "/#{template}.#{template_extension_for(:html)}" ) )
|
|
44
|
+
template.result(b)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def partial(template)
|
|
48
|
+
template = Erubis::Eruby.new( IO.read( template_dir(self.class.name.snake_case) + "/_#{template}.#{template_extension_for(:html)}" ) )
|
|
49
|
+
template.result(binding)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def render_xml(template=current_method_name(1))
|
|
53
|
+
xml = Builder::XmlMarkup.new :indent => 2
|
|
54
|
+
xml.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
|
|
55
|
+
eval IO.read( template_dir(self.class.name.snake_case) + "/#{template}.#{template_extension_for(:xml)}" )
|
|
56
|
+
@headers['Content-Type'] = 'application/xml'
|
|
57
|
+
@headers['Encoding'] = 'UTF-8'
|
|
58
|
+
xml.target!
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# renders a template based on the current action name
|
|
62
|
+
# you can pass the name of a template if you want to
|
|
63
|
+
# render a template with a different name then then
|
|
64
|
+
# current action name. Wraps the rendered template in
|
|
65
|
+
# the layout. Uses layout/application.rhtml unless
|
|
66
|
+
# there is a layout named after the current controller
|
|
67
|
+
# or @layout has been set to another value.
|
|
68
|
+
def render(template=current_method_name(1), b=binding)
|
|
69
|
+
tmpl_ext = template_extension_for(:html)
|
|
70
|
+
MERB_LOGGER.info("Rendering template: #{template_dir(template)}..#{tmpl_ext}")
|
|
71
|
+
name = self.class.name.snake_case
|
|
72
|
+
template = Erubis::Eruby.new( IO.read( template_dir(name) + "/#{template}.#{tmpl_ext}" ) )
|
|
73
|
+
layout_content = template.result(b)
|
|
74
|
+
return layout_content if (@layout.to_s == 'none')
|
|
75
|
+
if ['application', name].include?(@layout.to_s)
|
|
76
|
+
if File.exist?(template_dir("layout/#{name}.#{tmpl_ext}"))
|
|
77
|
+
layout = name
|
|
78
|
+
else
|
|
79
|
+
layout = 'application'
|
|
80
|
+
end
|
|
63
81
|
else
|
|
64
|
-
layout =
|
|
82
|
+
layout = @layout.to_s
|
|
65
83
|
end
|
|
66
|
-
|
|
67
|
-
|
|
84
|
+
MERB_LOGGER.info("With Layout: #{template_dir('layout')}/#{layout}.#{tmpl_ext}")
|
|
85
|
+
@layout_content = layout_content
|
|
86
|
+
layout_tmpl = Erubis::Eruby.new( IO.read( "#{template_dir('layout')}/#{layout}.#{tmpl_ext}" ) )
|
|
87
|
+
layout_tmpl.result(b)
|
|
68
88
|
end
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
layout_tmpl = Erubis::Eruby.new( IO.read( template_dir('layout') + "/#{layout}.rhtml" ) )
|
|
72
|
-
layout_tmpl.result(b)
|
|
73
|
-
end
|
|
74
|
-
|
|
89
|
+
|
|
90
|
+
end
|
|
75
91
|
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Merb
|
|
2
|
+
# Thanks to Chris Wanstrath
|
|
3
|
+
# use this in your controllers to switch output based on
|
|
4
|
+
# the HTTP_ACCEPT header. like so:
|
|
5
|
+
# respond_to do |type|
|
|
6
|
+
# type.js { render_js }
|
|
7
|
+
# type.html { render }
|
|
8
|
+
# type.xml { @foo.to_xml }
|
|
9
|
+
# type.yaml { @foo.to_yaml }
|
|
10
|
+
# end
|
|
11
|
+
|
|
12
|
+
module ResponderMixin
|
|
13
|
+
def respond_to
|
|
14
|
+
yield response = Response.new(@env['HTTP_ACCEPT'])
|
|
15
|
+
@headers['Content-Type'] = response.content_type
|
|
16
|
+
response.body
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class Response
|
|
20
|
+
attr_reader :body, :content_type
|
|
21
|
+
def initialize(accept) @accept = accept end
|
|
22
|
+
|
|
23
|
+
TYPES = {
|
|
24
|
+
:yaml => %w[application/yaml text/yaml],
|
|
25
|
+
:text => %w[text/plain],
|
|
26
|
+
:html => %w[text/html */* application/html],
|
|
27
|
+
:xml => %w[application/xml]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
def method_missing(method, *args)
|
|
31
|
+
if TYPES[method] && @accept =~ Regexp.union(*TYPES[method])
|
|
32
|
+
@content_type = TYPES[method].first
|
|
33
|
+
@body = yield if block_given?
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
require 'drb'
|
|
2
|
+
require 'thread'
|
|
3
|
+
|
|
4
|
+
module Merb
|
|
5
|
+
|
|
6
|
+
class DRbSession
|
|
7
|
+
|
|
8
|
+
include DRbUndumped
|
|
9
|
+
|
|
10
|
+
class << self
|
|
11
|
+
|
|
12
|
+
def setup(opts={})
|
|
13
|
+
@opts = opts
|
|
14
|
+
@sessions = Hash.new
|
|
15
|
+
@timestamps = Hash.new
|
|
16
|
+
@mutex = Mutex.new
|
|
17
|
+
@session_ttl = opts.fetch(:session_ttl, 15*60) # default 15 minutes
|
|
18
|
+
self
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def create(opts={})
|
|
22
|
+
self[opts[:sess_id]] = opts[:data]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def [](key)
|
|
26
|
+
@mutex.synchronize {
|
|
27
|
+
@timestamps[key] = Time.now
|
|
28
|
+
@sessions[key]
|
|
29
|
+
}
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def []=(key, val)
|
|
33
|
+
@mutex.synchronize {
|
|
34
|
+
@timestamps[key] = Time.now
|
|
35
|
+
@sessions[key] = val
|
|
36
|
+
}
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def delete(key)
|
|
40
|
+
@mutex.synchronize {
|
|
41
|
+
@sessions.delete(key)
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def reap_old_sessions
|
|
46
|
+
@timestamps.each do |key,stamp|
|
|
47
|
+
if stamp + @session_ttl < Time.now
|
|
48
|
+
delete(key)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
GC.start
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def sessions
|
|
55
|
+
@sessions
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end # end singleton class
|
|
59
|
+
|
|
60
|
+
end # end DRbSession
|
|
61
|
+
|
|
62
|
+
# Keeps track of the status of all currently processing uploads
|
|
63
|
+
class UploadProgress
|
|
64
|
+
attr_accessor :debug
|
|
65
|
+
def initialize
|
|
66
|
+
@guard = Mutex.new
|
|
67
|
+
@counters = {}
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def check(upid)
|
|
71
|
+
@counters[upid].last rescue nil
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def last_checked(upid)
|
|
75
|
+
@counters[upid].first rescue nil
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def update_checked_time(upid)
|
|
79
|
+
@guard.synchronize { @counters[upid][0] = Time.now }
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def add(upid, size)
|
|
83
|
+
@guard.synchronize do
|
|
84
|
+
@counters[upid] = [Time.now, {:size => size, :received => 0}]
|
|
85
|
+
puts "#{upid}: Added" if @debug
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def mark(upid, len)
|
|
90
|
+
return unless status = check(upid)
|
|
91
|
+
puts "#{upid}: Marking" if @debug
|
|
92
|
+
@guard.synchronize { status[:received] = status[:size] - len }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def finish(upid)
|
|
96
|
+
@guard.synchronize do
|
|
97
|
+
puts "#{upid}: Finished" if @debug
|
|
98
|
+
@counters.delete(upid)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def list
|
|
103
|
+
@counters.keys.sort
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
module Merb
|
|
2
|
+
|
|
3
|
+
module SessionMixin
|
|
4
|
+
|
|
5
|
+
def setup_session
|
|
6
|
+
MERB_LOGGER.info("Setting up session")
|
|
7
|
+
@session = Merb::Session.persist(cookies)
|
|
8
|
+
@fingerprint_before = Marshal.dump(@session).hash
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def finalize_session
|
|
12
|
+
MERB_LOGGER.info("Finalize session")
|
|
13
|
+
unless Marshal.dump(@session).hash == @fingerprint_before
|
|
14
|
+
@session.save
|
|
15
|
+
end
|
|
16
|
+
@headers['Set-Cookie'] = @cookies.map { |k,v| "#{k}=#{escape(v)}; path=/" if v != @k[k] } - [nil]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# accessor for @session. Please use session and
|
|
20
|
+
# never @session directly.
|
|
21
|
+
def session
|
|
22
|
+
@session
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class Session
|
|
28
|
+
|
|
29
|
+
attr_reader :sess_id
|
|
30
|
+
|
|
31
|
+
def []=(k, v) # :nodoc:
|
|
32
|
+
(@data||={})[k] = v rescue nil
|
|
33
|
+
end
|
|
34
|
+
def [](k) # :nodoc:
|
|
35
|
+
@data[k] rescue nil
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def initialize(sess_id,data={})
|
|
39
|
+
@data = data || {}
|
|
40
|
+
@sess_id = sess_id
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def save
|
|
44
|
+
Merb::DRbSession[@sess_id] = @data
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
RAND_CHARS = [*'A'..'Z'] + [*'0'..'9'] + [*'a'..'z']
|
|
48
|
+
|
|
49
|
+
# Generates a new session ID and creates a row for the new session in the database.
|
|
50
|
+
def self.generate(cookies)
|
|
51
|
+
rand_max = RAND_CHARS.size
|
|
52
|
+
sid = (0...32).inject("") { |ret,_| ret << RAND_CHARS[rand(rand_max)] }
|
|
53
|
+
sess = Merb::DRbSession.create(:sess_id => sid, :data => {})
|
|
54
|
+
cookies[:sess_id] = sid
|
|
55
|
+
new(sid, sess)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Gets the existing session based on the <tt>camping_sid</tt> available in cookies.
|
|
59
|
+
# If none is found, generates a new session.
|
|
60
|
+
def self.persist cookies
|
|
61
|
+
if cookies[:sess_id]
|
|
62
|
+
session = new(cookies[:sess_id], Merb::DRbSession[cookies[:sess_id]])
|
|
63
|
+
end
|
|
64
|
+
unless session
|
|
65
|
+
session = Merb::Session.generate(cookies)
|
|
66
|
+
end
|
|
67
|
+
session
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|