rack-flash3 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +93 -0
- data/Rakefile +28 -0
- data/VERSION.yml +5 -0
- data/example/base_app.ru +22 -0
- data/example/sinatra_app.rb +36 -0
- data/example/views/index.erb +28 -0
- data/example/views/layout.erb +131 -0
- data/example/views/show.erb +15 -0
- data/lib/rack-flash.rb +1 -0
- data/lib/rack/flash.rb +138 -0
- data/lib/rack/flash/test.rb +14 -0
- data/test/helper.rb +51 -0
- data/test/test_flash.rb +157 -0
- metadata +81 -0
data/README.md
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
# Rack Flash
|
2
|
+
|
3
|
+
flash[:notice] = "You can stop rolling your own now."
|
4
|
+
|
5
|
+
Simple flash hash implementation for Rack apps.
|
6
|
+
|
7
|
+
[View the RDoc](http://gitrdoc.com/nakajima/rack-flash/tree/master).
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
|
11
|
+
Here's how to use it.
|
12
|
+
|
13
|
+
### Vanilla Rack apps
|
14
|
+
|
15
|
+
You can access flash entries via `env['x-rack.flash']`. You can treat it either
|
16
|
+
like a regular flash hash:
|
17
|
+
|
18
|
+
env['x-rack.flash'][:notice] = 'You have logged out.'
|
19
|
+
|
20
|
+
Or you can pass the `:accessorize` option to declare your flash types. Each of
|
21
|
+
these will have accessors defined on the flash object:
|
22
|
+
|
23
|
+
use Rack::Flash, :accessorize => [:notice, :error]
|
24
|
+
|
25
|
+
# Set a flash entry
|
26
|
+
env['x-rack.flash'].notice = 'You have logged out.'
|
27
|
+
|
28
|
+
# Get a flash entry
|
29
|
+
env['x-rack.flash'].notice # => 'You have logged out.'
|
30
|
+
|
31
|
+
# Set a a flash entry for only the current request
|
32
|
+
env['x-rack.flash'].notice! 'You have logged out.'
|
33
|
+
|
34
|
+
Sample rack app:
|
35
|
+
|
36
|
+
get = proc { |env|
|
37
|
+
[200, {},
|
38
|
+
env['x-rack.flash'].notice || 'No flash set. Try going to /set'
|
39
|
+
]
|
40
|
+
}
|
41
|
+
|
42
|
+
set = proc { |env|
|
43
|
+
env['x-rack.flash'].notice = 'Hey, the flash was set!'
|
44
|
+
[302, {'Location' => '/'},
|
45
|
+
'You are being redirected.'
|
46
|
+
]
|
47
|
+
}
|
48
|
+
|
49
|
+
builder = Rack::Builder.new do
|
50
|
+
use Rack::Session::Cookie
|
51
|
+
use Rack::Flash, :accessorize => true
|
52
|
+
|
53
|
+
map('/set') { run set }
|
54
|
+
map('/') { run get }
|
55
|
+
end
|
56
|
+
|
57
|
+
Rack::Handler::Mongrel.run builder, :Port => 9292
|
58
|
+
|
59
|
+
### Sinatra
|
60
|
+
|
61
|
+
If you're using Sinatra, you can use the flash hash just like in Rails:
|
62
|
+
|
63
|
+
require 'sinatra/base'
|
64
|
+
require 'rack-flash'
|
65
|
+
|
66
|
+
class MyApp < Sinatra::Base
|
67
|
+
enable :sessions
|
68
|
+
use Rack::Flash
|
69
|
+
|
70
|
+
post '/set-flash' do
|
71
|
+
# Set a flash entry
|
72
|
+
flash[:notice] = "Thanks for signing up!"
|
73
|
+
|
74
|
+
# Get a flash entry
|
75
|
+
flash[:notice] # => "Thanks for signing up!"
|
76
|
+
|
77
|
+
# Set a flash entry for only the current request
|
78
|
+
flash.now[:notice] = "Thanks for signing up!"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
If you've got any ideas on how to simplify access to the flash hash for vanilla
|
83
|
+
Rack apps, let me know. It still feels a bit off to me.
|
84
|
+
|
85
|
+
## Sweeping stale entries
|
86
|
+
|
87
|
+
By default Rack::Flash has slightly different behavior than Rails in that it
|
88
|
+
doesn't delete entries until they are used. If you want entries to be cleared
|
89
|
+
even if they are not ever accessed, you can use the `:sweep` option:
|
90
|
+
|
91
|
+
use Rack::Flash, :sweep => true
|
92
|
+
|
93
|
+
This will sweep stale flash entries, whether or not you actually use them.
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler2'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "rack-flash3"
|
8
|
+
gem.summary = "Flash hash implementation for Rack apps."
|
9
|
+
gem.description = "Flash hash implementation for Rack apps."
|
10
|
+
gem.email = "treeder@gmail.com"
|
11
|
+
gem.homepage = "http://www.iron.io"
|
12
|
+
gem.authors = ["Pat Nakajima", "Travis Reeder"]
|
13
|
+
gem.add_dependency 'rack'
|
14
|
+
gem.required_ruby_version = '>= 1.9'
|
15
|
+
end
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler2"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'rake/testtask'
|
22
|
+
Rake::TestTask.new(:test) do |test|
|
23
|
+
test.libs << 'lib' << 'test'
|
24
|
+
test.pattern = 'test/**/test_*.rb'
|
25
|
+
test.verbose = true
|
26
|
+
end
|
27
|
+
|
28
|
+
task :default => :test
|
data/VERSION.yml
ADDED
data/example/base_app.ru
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rack/request'
|
2
|
+
require 'rack/response'
|
3
|
+
require 'rack/showexceptions'
|
4
|
+
require 'rack/session/cookie'
|
5
|
+
require File.dirname(__FILE__) + '/../lib/rack-flash'
|
6
|
+
|
7
|
+
class Base
|
8
|
+
attr_accessor :env
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
@env = env
|
12
|
+
flash['err'] = "IT'S ALIVE"
|
13
|
+
res = Rack::Response.new
|
14
|
+
res.write "<title>Flashy</title>"
|
15
|
+
res.write "#{flash['err']}"
|
16
|
+
res.finish
|
17
|
+
end
|
18
|
+
end
|
19
|
+
use Rack::Session::Cookie
|
20
|
+
use Rack::Flash#, :flash_app_class => Base
|
21
|
+
use Rack::ShowExceptions
|
22
|
+
run Base.new
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'sinatra/base'
|
3
|
+
require File.dirname(__FILE__) + '/../lib/rack-flash'
|
4
|
+
|
5
|
+
class MyApp < Sinatra::Base
|
6
|
+
use Rack::Flash
|
7
|
+
|
8
|
+
set :root, File.dirname(__FILE__)
|
9
|
+
set :layout, true
|
10
|
+
set :logging, true
|
11
|
+
set :sessions, true
|
12
|
+
|
13
|
+
get '/' do
|
14
|
+
erb :index
|
15
|
+
end
|
16
|
+
|
17
|
+
# View the value of any given flash
|
18
|
+
get '/:name' do
|
19
|
+
erb :show
|
20
|
+
end
|
21
|
+
|
22
|
+
post '/:name' do
|
23
|
+
if params[:message].strip.empty?
|
24
|
+
flash["err"] = "You must enter a message."
|
25
|
+
flash["err_on_#{params[:name]}"] = 1
|
26
|
+
redirect('/')
|
27
|
+
end
|
28
|
+
|
29
|
+
flash[:ok] = "Set flash entry!"
|
30
|
+
|
31
|
+
flash[params[:name]] = params[:message]
|
32
|
+
redirect '/'
|
33
|
+
end
|
34
|
+
|
35
|
+
run!
|
36
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<% if flash.has?(:err) %>
|
2
|
+
<h3 class="err"><%= flash[:err] %></h3>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<% if flash.has?(:ok) %>
|
6
|
+
<h3 class="ok"><%= flash[:ok] %></h3>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<% [:notice, :error, :success, :whatevz, :bliggety].each do |name| %>
|
10
|
+
<form action="/<%= name %>" method="post" accept-charset="utf-8">
|
11
|
+
<label>
|
12
|
+
<span>
|
13
|
+
<% if flash.has?(name) %>
|
14
|
+
<a href="/<%= name %>">View Current</a>
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
Set <code>flash[:<%= name %>]</code>
|
18
|
+
|
19
|
+
<% if err = flash["err_on_#{name}"] %>
|
20
|
+
<strong class="err_on">Required!</strong>
|
21
|
+
<% end %>
|
22
|
+
</span>
|
23
|
+
<input type="text" name="message" value="" id="message">
|
24
|
+
</label>
|
25
|
+
|
26
|
+
<input type="submit" value="Set Flash">
|
27
|
+
</form>
|
28
|
+
<% end %>
|
@@ -0,0 +1,131 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>Flash Examples</title>
|
4
|
+
<style type="text/css" media="screen">
|
5
|
+
* {
|
6
|
+
margin: 0;
|
7
|
+
padding: 0;
|
8
|
+
}
|
9
|
+
|
10
|
+
body {
|
11
|
+
font-family: Helvetica;
|
12
|
+
font-size: 18px;
|
13
|
+
}
|
14
|
+
|
15
|
+
a {
|
16
|
+
color: #f09;
|
17
|
+
text-decoration: none;
|
18
|
+
padding: 0px 3px;
|
19
|
+
}
|
20
|
+
|
21
|
+
a:hover {
|
22
|
+
background: #f09;
|
23
|
+
color: #fff;
|
24
|
+
}
|
25
|
+
|
26
|
+
a:active {
|
27
|
+
text-decoration: underline;
|
28
|
+
}
|
29
|
+
|
30
|
+
h1 {
|
31
|
+
text-align: center;
|
32
|
+
}
|
33
|
+
|
34
|
+
code {
|
35
|
+
font-family: Bitstream Vera Sans Mono , monospace;
|
36
|
+
background: #D4EBF7;
|
37
|
+
}
|
38
|
+
|
39
|
+
form {
|
40
|
+
margin: 0.4em auto;
|
41
|
+
display: inline-block;
|
42
|
+
}
|
43
|
+
|
44
|
+
label {
|
45
|
+
line-height: 1em;
|
46
|
+
height: 1em;
|
47
|
+
}
|
48
|
+
|
49
|
+
label span {
|
50
|
+
display: block;
|
51
|
+
font-size: 12px;
|
52
|
+
margin-bottom: 1px;
|
53
|
+
}
|
54
|
+
|
55
|
+
label a {
|
56
|
+
font-weight: bold;
|
57
|
+
float: right;
|
58
|
+
margin-right: 79px;
|
59
|
+
line-height: 1.5em;
|
60
|
+
}
|
61
|
+
|
62
|
+
input[type="text"] {
|
63
|
+
padding: 2px;
|
64
|
+
font-size: 18px;
|
65
|
+
width: 610px;
|
66
|
+
margin-right: 10px;
|
67
|
+
}
|
68
|
+
|
69
|
+
input[type="submit"] {
|
70
|
+
cursor: pointer;
|
71
|
+
vertical-align: 20%;
|
72
|
+
}
|
73
|
+
|
74
|
+
.err, .ok {
|
75
|
+
margin: 0.3em 0;
|
76
|
+
padding: 5px 7px;
|
77
|
+
text-align: center;
|
78
|
+
color: #fff;
|
79
|
+
}
|
80
|
+
|
81
|
+
.ok {
|
82
|
+
background: #00A8FF;
|
83
|
+
}
|
84
|
+
|
85
|
+
.err {
|
86
|
+
background: #f10;
|
87
|
+
}
|
88
|
+
|
89
|
+
.err_on {
|
90
|
+
display: inline-block;
|
91
|
+
padding: 0px 3px;
|
92
|
+
color: #f10;
|
93
|
+
font-weight: bold;
|
94
|
+
}
|
95
|
+
|
96
|
+
.highlight {
|
97
|
+
background: #ffc;
|
98
|
+
padding: 10px;
|
99
|
+
margin-bottom: 10px;
|
100
|
+
}
|
101
|
+
|
102
|
+
#content {
|
103
|
+
width: 700px;
|
104
|
+
margin: 1em auto;
|
105
|
+
}
|
106
|
+
|
107
|
+
#result {
|
108
|
+
font-size: 48px;
|
109
|
+
margin: 10% auto 20%;
|
110
|
+
text-align: center;
|
111
|
+
display: block;
|
112
|
+
}
|
113
|
+
|
114
|
+
#result cite {
|
115
|
+
font-size: 14px;
|
116
|
+
display: block;
|
117
|
+
text-align: right;
|
118
|
+
}
|
119
|
+
|
120
|
+
#result cite code {
|
121
|
+
font-style: normal;
|
122
|
+
}
|
123
|
+
</style>
|
124
|
+
</head>
|
125
|
+
<body>
|
126
|
+
<div id="content">
|
127
|
+
<h1><code>Sinatra::Flash</code></h1>
|
128
|
+
<%= yield %>
|
129
|
+
</div>
|
130
|
+
</body>
|
131
|
+
</html>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<div id="result">
|
2
|
+
<% if flash.has?(params[:name]) %>
|
3
|
+
<h1 class="highlight"><%= flash[params[:name]] %></h1>
|
4
|
+
<cite>- from <code>flash[:<%= params[:name] %>]</code></cite>
|
5
|
+
<% else %>
|
6
|
+
<p>No flash message for <code>flash[:<%= params[:name] %>]</code></p>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<br>
|
10
|
+
|
11
|
+
<small>
|
12
|
+
<a href="/">Go Back Home</a>
|
13
|
+
</small>
|
14
|
+
</div>
|
15
|
+
|
data/lib/rack-flash.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[rack flash])
|
data/lib/rack/flash.rb
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
module Rack
|
2
|
+
|
3
|
+
class Flash
|
4
|
+
# Raised when the session passed to FlashHash initialize is nil. This
|
5
|
+
# is usually an indicator that session middleware is not in use.
|
6
|
+
class SessionUnavailable < StandardError; end
|
7
|
+
|
8
|
+
# Implements bracket accessors for storing and retrieving flash entries.
|
9
|
+
class FlashHash
|
10
|
+
attr_reader :flagged
|
11
|
+
|
12
|
+
def initialize(store, opts={})
|
13
|
+
raise Rack::Flash::SessionUnavailable \
|
14
|
+
.new('Rack::Flash depends on session middleware.') unless store
|
15
|
+
|
16
|
+
@opts = opts
|
17
|
+
@store = store
|
18
|
+
|
19
|
+
if accessors = @opts[:accessorize]
|
20
|
+
accessors.each { |opt| def_accessor(opt) }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Remove an entry from the session and return its value. Cache result in
|
25
|
+
# the instance cache.
|
26
|
+
def [](key)
|
27
|
+
key = key.to_sym
|
28
|
+
cache[key] ||= values.delete(key)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Store the entry in the session, updating the instance cache as well.
|
32
|
+
def []=(key,val)
|
33
|
+
key = key.to_sym
|
34
|
+
cache[key] = values[key] = val
|
35
|
+
end
|
36
|
+
|
37
|
+
# Store a flash entry for only the current request, swept regardless of
|
38
|
+
# whether or not it was actually accessed. Useful for AJAX requests, where
|
39
|
+
# you want a flash message, even though you're response isn't redirecting.
|
40
|
+
def now
|
41
|
+
cache
|
42
|
+
end
|
43
|
+
|
44
|
+
# Checks for the presence of a flash entry without retrieving or removing
|
45
|
+
# it from the cache or store.
|
46
|
+
def has?(key)
|
47
|
+
[cache, values].any? { |store| store.keys.include?(key.to_sym) }
|
48
|
+
end
|
49
|
+
alias_method :include?, :has?
|
50
|
+
|
51
|
+
# Mark existing entries to allow for sweeping.
|
52
|
+
def flag!
|
53
|
+
@flagged = values.keys
|
54
|
+
end
|
55
|
+
|
56
|
+
# Remove flagged entries from flash session, clear flagged list.
|
57
|
+
def sweep!
|
58
|
+
Array(flagged).each { |key| values.delete(key) }
|
59
|
+
flagged.clear
|
60
|
+
end
|
61
|
+
|
62
|
+
# Hide the underlying :__FLASH__ session key and only expose values stored
|
63
|
+
# in the flash.
|
64
|
+
def inspect
|
65
|
+
'#<FlashHash @values=%s @cache=%s>' % [values.inspect, cache.inspect]
|
66
|
+
end
|
67
|
+
|
68
|
+
# Human readable for logging.
|
69
|
+
def to_s
|
70
|
+
values.inspect
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
# Maintain an instance-level cache of retrieved flash entries. These
|
76
|
+
# entries will have been removed from the session, but are still available
|
77
|
+
# through the cache.
|
78
|
+
def cache
|
79
|
+
@cache ||= {}
|
80
|
+
end
|
81
|
+
|
82
|
+
# Helper to access flash entries from :__FLASH__ session value. This key
|
83
|
+
# is used to prevent collisions with other user-defined session values.
|
84
|
+
def values
|
85
|
+
@store[:__FLASH__] ||= {}
|
86
|
+
end
|
87
|
+
|
88
|
+
# Generate accessor methods for the given entry key if :accessorize is true.
|
89
|
+
def def_accessor(key)
|
90
|
+
raise ArgumentError.new('Invalid entry type: %s' % key) if respond_to?(key)
|
91
|
+
|
92
|
+
class << self; self end.class_eval do
|
93
|
+
define_method(key) { |*args| val = args.first; val ? (self[key]=val) : self[key] }
|
94
|
+
define_method("#{key}=") { |val| self[key] = val }
|
95
|
+
define_method("#{key}!") { |val| cache[key] = val }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# -------------------------------------------------------------------------
|
101
|
+
# - Rack Middleware implementation
|
102
|
+
|
103
|
+
def initialize(app, opts={})
|
104
|
+
if klass = app_class(app, opts)
|
105
|
+
klass.class_eval do
|
106
|
+
def flash; env['x-rack.flash'] end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
@app, @opts = app, opts
|
111
|
+
end
|
112
|
+
|
113
|
+
def call(env)
|
114
|
+
env['x-rack.flash'] ||= Rack::Flash::FlashHash.new(env['rack.session'], @opts)
|
115
|
+
|
116
|
+
if @opts[:sweep]
|
117
|
+
env['x-rack.flash'].flag!
|
118
|
+
end
|
119
|
+
|
120
|
+
res = @app.call(env)
|
121
|
+
|
122
|
+
if @opts[:sweep]
|
123
|
+
env['x-rack.flash'].sweep!
|
124
|
+
end
|
125
|
+
|
126
|
+
res
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
def app_class(app, opts)
|
132
|
+
return nil if opts.has_key?(:helper) and not opts[:helper]
|
133
|
+
opts[:flash_app_class] ||
|
134
|
+
defined?(Sinatra::Base) && Sinatra::Base ||
|
135
|
+
self.class.rack_builder.leaf_app.class
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Rack
|
2
|
+
class Flash
|
3
|
+
def self.fake_session
|
4
|
+
@fake_session ||= {}
|
5
|
+
end
|
6
|
+
|
7
|
+
alias_method :old_call, :call
|
8
|
+
def new_call(env)
|
9
|
+
env['rack.session'] ||= Rack::Flash.fake_session
|
10
|
+
old_call(env)
|
11
|
+
end
|
12
|
+
alias_method :call, :new_call
|
13
|
+
end
|
14
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'sinatra', '<=1.3.2'
|
3
|
+
require 'sinatra/base'
|
4
|
+
require 'bacon'
|
5
|
+
require 'rack/test'
|
6
|
+
require File.join(File.dirname(__FILE__), *%w[.. lib rack-flash])
|
7
|
+
|
8
|
+
class String
|
9
|
+
[:green, :yellow, :red].each { |c| define_method(c) { self } }
|
10
|
+
end if ENV['TM_RUBY']
|
11
|
+
|
12
|
+
# bacon swallows errors alive
|
13
|
+
def err_explain
|
14
|
+
begin
|
15
|
+
yield
|
16
|
+
rescue => e
|
17
|
+
puts e.inspect
|
18
|
+
puts e.backtrace
|
19
|
+
raise e
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module Rack
|
24
|
+
class FakeFlash < Rack::Flash::FlashHash
|
25
|
+
attr_reader :flagged, :sweeped, :store
|
26
|
+
|
27
|
+
def initialize(*args)
|
28
|
+
@flagged, @sweeped = false, false
|
29
|
+
@store = {}
|
30
|
+
super(@store)
|
31
|
+
end
|
32
|
+
|
33
|
+
def flag!
|
34
|
+
@flagged = true
|
35
|
+
super
|
36
|
+
end
|
37
|
+
|
38
|
+
def sweep!
|
39
|
+
@sweeped = true
|
40
|
+
super
|
41
|
+
end
|
42
|
+
|
43
|
+
def flagged?
|
44
|
+
@flagged
|
45
|
+
end
|
46
|
+
|
47
|
+
def swept?
|
48
|
+
@sweeped
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/test/test_flash.rb
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
describe 'Rack::Flash' do
|
4
|
+
include Rack::Test::Methods
|
5
|
+
|
6
|
+
def app(&block)
|
7
|
+
return Sinatra.new &block
|
8
|
+
end
|
9
|
+
|
10
|
+
before do
|
11
|
+
@fake_session = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def new_flash(entries={})
|
15
|
+
flash = Rack::Flash::FlashHash.new(@fake_session)
|
16
|
+
entries.each { |key,val| flash[key] = val }
|
17
|
+
flash
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'stores entries' do
|
21
|
+
new_flash[:foo] = 'bar'
|
22
|
+
new_flash[:foo].should.equal('bar')
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'accepts strings or hashes' do
|
26
|
+
new_flash[:foo] = 'bar'
|
27
|
+
new_flash['foo'].should.equal('bar')
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'deletes entries from session after retrieval' do
|
31
|
+
new_flash[:foo] = 'bar'
|
32
|
+
new_flash[:foo]
|
33
|
+
new_flash[:foo].should.be.nil
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'caches retrieved entries in instance' do
|
37
|
+
flash = new_flash(:foo => 'bar')
|
38
|
+
flash[:foo].should.equal('bar')
|
39
|
+
flash[:foo].should.equal('bar')
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'does not step on session keys' do
|
43
|
+
@fake_session[:foo] = true
|
44
|
+
new_flash[:foo] = false
|
45
|
+
@fake_session[:foo].should.be.true
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'can flag existing entries' do
|
49
|
+
flash = new_flash(:foo => 'bar', :fizz => 'buzz')
|
50
|
+
flash.flag!
|
51
|
+
flash.flagged.should.include(:foo)
|
52
|
+
flash.flagged.should.include(:fizz)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'can sweep flagged entries' do
|
56
|
+
err_explain do
|
57
|
+
flash = new_flash(:foo => 'bar', :fizz => 'buzz')
|
58
|
+
flash.flag!
|
59
|
+
flash.sweep!
|
60
|
+
flash.flagged.should.be.empty
|
61
|
+
new_flash[:foo].should.be.nil
|
62
|
+
new_flash[:fizz].should.be.nil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'allows setters with Flash.now semantics' do
|
67
|
+
flash = new_flash
|
68
|
+
flash.now[:foo] = 'bar'
|
69
|
+
flash[:foo].should.equal('bar')
|
70
|
+
new_flash[:foo].should.be.nil
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'does not raise an error when session is cleared' do
|
74
|
+
flash = new_flash
|
75
|
+
flash[:foo] = 'bar'
|
76
|
+
@fake_session.clear
|
77
|
+
flash['foo'].should.equal(nil)
|
78
|
+
end
|
79
|
+
|
80
|
+
describe 'accessorize option' do
|
81
|
+
def new_flash(entries={})
|
82
|
+
flash = Rack::Flash::FlashHash.new(@fake_session, :accessorize => [:foo, :fizz])
|
83
|
+
entries.each { |key,val| flash[key] = val }
|
84
|
+
flash
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'allows getters' do
|
88
|
+
flash = new_flash(:foo => 'bar')
|
89
|
+
flash.foo.should.equal('bar')
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'allows setters' do
|
93
|
+
flash = new_flash
|
94
|
+
flash.fizz = 'buzz'
|
95
|
+
flash.fizz.should.equal('buzz')
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'allows declarative setters' do
|
99
|
+
flash = new_flash
|
100
|
+
flash.fizz 'buzz'
|
101
|
+
flash.fizz.should.equal('buzz')
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'allows setters with Flash.now semantics' do
|
105
|
+
flash = new_flash
|
106
|
+
flash.foo! 'bar'
|
107
|
+
flash.foo.should.equal('bar')
|
108
|
+
new_flash[:foo].should.be.nil
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'only defines accessors for passed entry types' do
|
112
|
+
err_explain do
|
113
|
+
flash = new_flash
|
114
|
+
proc {
|
115
|
+
flash.bliggety = 'blam'
|
116
|
+
}.should.raise(NoMethodError)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'does not provide getters by default' do
|
122
|
+
proc {
|
123
|
+
new_flash(:foo => 'bar').foo
|
124
|
+
}.should.raise(NoMethodError)
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'does not provide setters by default' do
|
128
|
+
proc {
|
129
|
+
flash = new_flash
|
130
|
+
flash.fizz = 'buzz'
|
131
|
+
}.should.raise(NoMethodError)
|
132
|
+
end
|
133
|
+
|
134
|
+
describe 'integration' do
|
135
|
+
it 'provides :sweep option to clear unused entries' do
|
136
|
+
app {
|
137
|
+
use Rack::Flash, :sweep => true
|
138
|
+
|
139
|
+
set :sessions, true
|
140
|
+
|
141
|
+
get '/' do
|
142
|
+
'ok'
|
143
|
+
end
|
144
|
+
}
|
145
|
+
|
146
|
+
fake_flash = Rack::FakeFlash.new(:foo => 'bar')
|
147
|
+
|
148
|
+
get '/', :env=>{ 'x-rack.flash' => fake_flash }
|
149
|
+
|
150
|
+
fake_flash.should.be.flagged
|
151
|
+
fake_flash.should.be.swept
|
152
|
+
fake_flash.store[:foo].should.be.nil
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Testing sessions is a royal pain in the ass.
|
157
|
+
end
|
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-flash3
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Pat Nakajima
|
9
|
+
- Travis Reeder
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2012-03-19 00:00:00.000000000Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rack
|
17
|
+
requirement: &11215120 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *11215120
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rack
|
28
|
+
requirement: &11214480 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *11214480
|
37
|
+
description: Flash hash implementation for Rack apps.
|
38
|
+
email: treeder@gmail.com
|
39
|
+
executables: []
|
40
|
+
extensions: []
|
41
|
+
extra_rdoc_files:
|
42
|
+
- README.md
|
43
|
+
files:
|
44
|
+
- README.md
|
45
|
+
- Rakefile
|
46
|
+
- VERSION.yml
|
47
|
+
- example/base_app.ru
|
48
|
+
- example/sinatra_app.rb
|
49
|
+
- example/views/index.erb
|
50
|
+
- example/views/layout.erb
|
51
|
+
- example/views/show.erb
|
52
|
+
- lib/rack-flash.rb
|
53
|
+
- lib/rack/flash.rb
|
54
|
+
- lib/rack/flash/test.rb
|
55
|
+
- test/helper.rb
|
56
|
+
- test/test_flash.rb
|
57
|
+
homepage: http://www.iron.io
|
58
|
+
licenses: []
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.9'
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
none: false
|
71
|
+
requirements:
|
72
|
+
- - ! '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
requirements: []
|
76
|
+
rubyforge_project:
|
77
|
+
rubygems_version: 1.8.15
|
78
|
+
signing_key:
|
79
|
+
specification_version: 3
|
80
|
+
summary: Flash hash implementation for Rack apps.
|
81
|
+
test_files: []
|