hanami-controller 0.0.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +155 -0
- data/LICENSE.md +22 -0
- data/README.md +1180 -9
- data/hanami-controller.gemspec +19 -12
- data/lib/hanami-controller.rb +1 -0
- data/lib/hanami/action.rb +85 -0
- data/lib/hanami/action/cache.rb +174 -0
- data/lib/hanami/action/cache/cache_control.rb +70 -0
- data/lib/hanami/action/cache/conditional_get.rb +93 -0
- data/lib/hanami/action/cache/directives.rb +99 -0
- data/lib/hanami/action/cache/expires.rb +73 -0
- data/lib/hanami/action/callable.rb +94 -0
- data/lib/hanami/action/callbacks.rb +210 -0
- data/lib/hanami/action/configurable.rb +49 -0
- data/lib/hanami/action/cookie_jar.rb +181 -0
- data/lib/hanami/action/cookies.rb +85 -0
- data/lib/hanami/action/exposable.rb +115 -0
- data/lib/hanami/action/flash.rb +182 -0
- data/lib/hanami/action/glue.rb +66 -0
- data/lib/hanami/action/head.rb +122 -0
- data/lib/hanami/action/mime.rb +493 -0
- data/lib/hanami/action/params.rb +285 -0
- data/lib/hanami/action/rack.rb +270 -0
- data/lib/hanami/action/rack/callable.rb +47 -0
- data/lib/hanami/action/rack/file.rb +33 -0
- data/lib/hanami/action/redirect.rb +59 -0
- data/lib/hanami/action/request.rb +86 -0
- data/lib/hanami/action/session.rb +154 -0
- data/lib/hanami/action/throwable.rb +194 -0
- data/lib/hanami/action/validatable.rb +128 -0
- data/lib/hanami/controller.rb +250 -2
- data/lib/hanami/controller/configuration.rb +705 -0
- data/lib/hanami/controller/error.rb +7 -0
- data/lib/hanami/controller/version.rb +4 -1
- data/lib/hanami/http/status.rb +62 -0
- metadata +124 -16
- data/.gitignore +0 -9
- data/Gemfile +0 -4
- data/Rakefile +0 -2
- data/bin/console +0 -14
- data/bin/setup +0 -8
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'hanami/utils/class_attribute'
|
2
|
+
|
3
|
+
module Hanami
|
4
|
+
module Action
|
5
|
+
# Configuration API
|
6
|
+
#
|
7
|
+
# @since 0.2.0
|
8
|
+
#
|
9
|
+
# @see Hanami::Controller::Configuration
|
10
|
+
module Configurable
|
11
|
+
# Override Ruby's hook for modules.
|
12
|
+
# It includes configuration logic
|
13
|
+
#
|
14
|
+
# @param base [Class] the target action
|
15
|
+
#
|
16
|
+
# @since 0.2.0
|
17
|
+
# @api private
|
18
|
+
#
|
19
|
+
# @see http://www.ruby-doc.org/core-2.1.2/Module.html#method-i-included
|
20
|
+
#
|
21
|
+
# @example
|
22
|
+
# require 'hanami/controller'
|
23
|
+
#
|
24
|
+
# class Show
|
25
|
+
# include Hanami::Action
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# Show.configuration
|
29
|
+
def self.included(base)
|
30
|
+
config = Hanami::Controller::Configuration.for(base)
|
31
|
+
|
32
|
+
base.class_eval do
|
33
|
+
include Utils::ClassAttribute
|
34
|
+
|
35
|
+
class_attribute :configuration
|
36
|
+
self.configuration = config
|
37
|
+
end
|
38
|
+
|
39
|
+
config.copy!(base)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def configuration
|
45
|
+
self.class.configuration
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
require 'hanami/utils/hash'
|
2
|
+
|
3
|
+
module Hanami
|
4
|
+
module Action
|
5
|
+
# A set of HTTP Cookies
|
6
|
+
#
|
7
|
+
# It acts as an Hash
|
8
|
+
#
|
9
|
+
# @since 0.1.0
|
10
|
+
#
|
11
|
+
# @see Hanami::Action::Cookies#cookies
|
12
|
+
class CookieJar
|
13
|
+
# The key that returns raw cookies from the Rack env
|
14
|
+
#
|
15
|
+
# @since 0.1.0
|
16
|
+
# @api private
|
17
|
+
HTTP_HEADER = 'HTTP_COOKIE'.freeze
|
18
|
+
|
19
|
+
# The key used by Rack to set the session cookie
|
20
|
+
#
|
21
|
+
# We let CookieJar to NOT take care of this cookie, but it leaves the
|
22
|
+
# responsibility to the Rack middleware that handle sessions.
|
23
|
+
#
|
24
|
+
# This prevents <tt>Set-Cookie</tt> to be sent twice.
|
25
|
+
#
|
26
|
+
# @since 0.5.1
|
27
|
+
# @api private
|
28
|
+
#
|
29
|
+
# @see https://github.com/hanami/controller/issues/138
|
30
|
+
RACK_SESSION_KEY = :'rack.session'
|
31
|
+
|
32
|
+
# The key used by Rack to set the cookies as an Hash in the env
|
33
|
+
#
|
34
|
+
# @since 0.1.0
|
35
|
+
# @api private
|
36
|
+
COOKIE_HASH_KEY = 'rack.request.cookie_hash'.freeze
|
37
|
+
|
38
|
+
# The key used by Rack to set the cookies as a String in the env
|
39
|
+
#
|
40
|
+
# @since 0.1.0
|
41
|
+
# @api private
|
42
|
+
COOKIE_STRING_KEY = 'rack.request.cookie_string'.freeze
|
43
|
+
|
44
|
+
# @since 0.4.5
|
45
|
+
# @api private
|
46
|
+
COOKIE_SEPARATOR = ';,'.freeze
|
47
|
+
|
48
|
+
# Initialize the CookieJar
|
49
|
+
#
|
50
|
+
# @param env [Hash] a raw Rack env
|
51
|
+
# @param headers [Hash] the response headers
|
52
|
+
#
|
53
|
+
# @return [CookieJar]
|
54
|
+
#
|
55
|
+
# @since 0.1.0
|
56
|
+
def initialize(env, headers, default_options)
|
57
|
+
@_headers = headers
|
58
|
+
@cookies = Utils::Hash.new(extract(env)).symbolize!
|
59
|
+
@default_options = default_options
|
60
|
+
end
|
61
|
+
|
62
|
+
# Finalize itself, by setting the proper headers to add and remove
|
63
|
+
# cookies, before the response is returned to the webserver.
|
64
|
+
#
|
65
|
+
# @return [void]
|
66
|
+
#
|
67
|
+
# @since 0.1.0
|
68
|
+
#
|
69
|
+
# @see Hanami::Action::Cookies#finish
|
70
|
+
def finish
|
71
|
+
@cookies.delete(RACK_SESSION_KEY)
|
72
|
+
@cookies.each { |k,v| v.nil? ? delete_cookie(k) : set_cookie(k, _merge_default_values(v)) }
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns the object associated with the given key
|
76
|
+
#
|
77
|
+
# @param key [Symbol] the key
|
78
|
+
#
|
79
|
+
# @return [Object,nil] return the associated object, if found
|
80
|
+
#
|
81
|
+
# @since 0.2.0
|
82
|
+
def [](key)
|
83
|
+
@cookies[key]
|
84
|
+
end
|
85
|
+
|
86
|
+
# Associate the given value with the given key and store them
|
87
|
+
#
|
88
|
+
# @param key [Symbol] the key
|
89
|
+
# @param value [#to_s,Hash] value that can be serialized as a string or
|
90
|
+
# expressed as a Hash
|
91
|
+
# @option value [String] :domain - The domain
|
92
|
+
# @option value [String] :path - The path
|
93
|
+
# @option value [Integer] :max_age - Duration expressed in seconds
|
94
|
+
# @option value [Time] :expires - Expiration time
|
95
|
+
# @option value [TrueClass,FalseClass] :secure - Restrict cookie to secure
|
96
|
+
# connections
|
97
|
+
# @option value [TrueClass,FalseClass] :httponly - Restrict JavaScript
|
98
|
+
# access
|
99
|
+
#
|
100
|
+
# @return [void]
|
101
|
+
#
|
102
|
+
# @since 0.2.0
|
103
|
+
#
|
104
|
+
# @see http://en.wikipedia.org/wiki/HTTP_cookie
|
105
|
+
def []=(key, value)
|
106
|
+
@cookies[key] = value
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
# Merge default cookies options with values provided by user
|
112
|
+
#
|
113
|
+
# Cookies values provided by user are respected
|
114
|
+
#
|
115
|
+
# @since 0.4.0
|
116
|
+
# @api private
|
117
|
+
def _merge_default_values(value)
|
118
|
+
cookies_options = if value.is_a? Hash
|
119
|
+
value.merge! _add_expires_option(value)
|
120
|
+
else
|
121
|
+
{ value: value }
|
122
|
+
end
|
123
|
+
@default_options.merge cookies_options
|
124
|
+
end
|
125
|
+
|
126
|
+
# Add expires option to cookies if :max_age presents
|
127
|
+
#
|
128
|
+
# @since 0.4.3
|
129
|
+
# @api private
|
130
|
+
def _add_expires_option(value)
|
131
|
+
if value.has_key?(:max_age) && !value.has_key?(:expires)
|
132
|
+
{ expires: (Time.now + value[:max_age]) }
|
133
|
+
else
|
134
|
+
{}
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# Extract the cookies from the raw Rack env.
|
139
|
+
#
|
140
|
+
# This implementation is borrowed from Rack::Request#cookies.
|
141
|
+
#
|
142
|
+
# @since 0.1.0
|
143
|
+
# @api private
|
144
|
+
def extract(env)
|
145
|
+
hash = env[COOKIE_HASH_KEY] ||= {}
|
146
|
+
string = env[HTTP_HEADER]
|
147
|
+
|
148
|
+
return hash if string == env[COOKIE_STRING_KEY]
|
149
|
+
# TODO Next Rack 1.7.x ?? version will have ::Rack::Utils.parse_cookies
|
150
|
+
# We can then replace the following lines.
|
151
|
+
hash.clear
|
152
|
+
|
153
|
+
# According to RFC 2109:
|
154
|
+
# If multiple cookies satisfy the criteria above, they are ordered in
|
155
|
+
# the Cookie header such that those with more specific Path attributes
|
156
|
+
# precede those with less specific. Ordering with respect to other
|
157
|
+
# attributes (e.g., Domain) is unspecified.
|
158
|
+
cookies = ::Rack::Utils.parse_query(string, COOKIE_SEPARATOR) { |s| ::Rack::Utils.unescape(s) rescue s }
|
159
|
+
cookies.each { |k,v| hash[k] = Array === v ? v.first : v }
|
160
|
+
env[COOKIE_STRING_KEY] = string
|
161
|
+
hash
|
162
|
+
end
|
163
|
+
|
164
|
+
# Set a cookie in the headers
|
165
|
+
#
|
166
|
+
# @since 0.1.0
|
167
|
+
# @api private
|
168
|
+
def set_cookie(key, value)
|
169
|
+
::Rack::Utils.set_cookie_header!(@_headers, key, value)
|
170
|
+
end
|
171
|
+
|
172
|
+
# Remove a cookie from the headers
|
173
|
+
#
|
174
|
+
# @since 0.1.0
|
175
|
+
# @api private
|
176
|
+
def delete_cookie(key)
|
177
|
+
::Rack::Utils.delete_cookie_header!(@_headers, key, {})
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'hanami/action/cookie_jar'
|
2
|
+
|
3
|
+
module Hanami
|
4
|
+
module Action
|
5
|
+
# Cookies API
|
6
|
+
#
|
7
|
+
# This module isn't included by default.
|
8
|
+
#
|
9
|
+
# @since 0.1.0
|
10
|
+
#
|
11
|
+
# @see Hanami::Action::Cookies#cookies
|
12
|
+
module Cookies
|
13
|
+
protected
|
14
|
+
|
15
|
+
# Gets the cookies from the request and expose them as an Hash
|
16
|
+
#
|
17
|
+
# It automatically sets options from global configuration, but it allows to
|
18
|
+
# override values case by case.
|
19
|
+
#
|
20
|
+
# For a list of options please have a look at <tt>Hanami::Controller::Configuration</tt>,
|
21
|
+
# and <tt>Hanami::Action::CookieJar</tt>.
|
22
|
+
#
|
23
|
+
# @return [Hanami::Action::CookieJar] cookies
|
24
|
+
#
|
25
|
+
# @since 0.1.0
|
26
|
+
# @api public
|
27
|
+
#
|
28
|
+
# @see Hanami::Controller::Configuration#cookies
|
29
|
+
# @see Hanami::Action::CookieJar#[]=
|
30
|
+
#
|
31
|
+
# @example Basic Usage
|
32
|
+
# require 'hanami/controller'
|
33
|
+
# require 'hanami/action/cookies'
|
34
|
+
#
|
35
|
+
# class Show
|
36
|
+
# include Hanami::Action
|
37
|
+
# include Hanami::Action::Cookies
|
38
|
+
#
|
39
|
+
# def call(params)
|
40
|
+
# # ...
|
41
|
+
#
|
42
|
+
# # get a value
|
43
|
+
# cookies[:user_id] # => '23'
|
44
|
+
#
|
45
|
+
# # set a value
|
46
|
+
# cookies[:foo] = 'bar'
|
47
|
+
#
|
48
|
+
# # remove a value
|
49
|
+
# cookies[:bax] = nil
|
50
|
+
# end
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# @example Cookies Options
|
54
|
+
# require 'hanami/controller'
|
55
|
+
# require 'hanami/action/cookies'
|
56
|
+
#
|
57
|
+
# class Show
|
58
|
+
# include Hanami::Action
|
59
|
+
# include Hanami::Action::Cookies
|
60
|
+
#
|
61
|
+
# def call(params)
|
62
|
+
# # ...
|
63
|
+
# # set a value
|
64
|
+
# cookies[:foo] = { value: 'bar', max_age: 300, path: '/dashboard' }
|
65
|
+
# end
|
66
|
+
# end
|
67
|
+
def cookies
|
68
|
+
@cookies ||= CookieJar.new(@_env.dup, headers, configuration.cookies)
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
# Finalize the response by flushing cookies into the response
|
74
|
+
#
|
75
|
+
# @since 0.1.0
|
76
|
+
# @api private
|
77
|
+
#
|
78
|
+
# @see Hanami::Action#finish
|
79
|
+
def finish
|
80
|
+
super
|
81
|
+
cookies.finish
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module Hanami
|
2
|
+
module Action
|
3
|
+
# Exposures API
|
4
|
+
#
|
5
|
+
# @since 0.1.0
|
6
|
+
#
|
7
|
+
# @see Hanami::Action::Exposable::ClassMethods#expose
|
8
|
+
module Exposable
|
9
|
+
# Override Ruby's hook for modules.
|
10
|
+
# It includes exposures logic
|
11
|
+
#
|
12
|
+
# @param base [Class] the target action
|
13
|
+
#
|
14
|
+
# @since 0.1.0
|
15
|
+
# @api private
|
16
|
+
#
|
17
|
+
# @see http://www.ruby-doc.org/core-2.1.2/Module.html#method-i-included
|
18
|
+
def self.included(base)
|
19
|
+
base.extend ClassMethods
|
20
|
+
end
|
21
|
+
|
22
|
+
# Exposures API class methods
|
23
|
+
#
|
24
|
+
# @since 0.1.0
|
25
|
+
# @api private
|
26
|
+
module ClassMethods
|
27
|
+
# Expose the given attributes on the outside of the object with
|
28
|
+
# a getter and a special method called #exposures.
|
29
|
+
#
|
30
|
+
# @param names [Array<Symbol>] the name(s) of the attribute(s) to be
|
31
|
+
# exposed
|
32
|
+
#
|
33
|
+
# @return [void]
|
34
|
+
#
|
35
|
+
# @since 0.1.0
|
36
|
+
#
|
37
|
+
# @example
|
38
|
+
# require 'hanami/controller'
|
39
|
+
#
|
40
|
+
# class Show
|
41
|
+
# include Hanami::Action
|
42
|
+
#
|
43
|
+
# expose :article, :tags
|
44
|
+
#
|
45
|
+
# def call(params)
|
46
|
+
# @article = Article.find params[:id]
|
47
|
+
# @tags = Tag.for(article)
|
48
|
+
# end
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# action = Show.new
|
52
|
+
# action.call({id: 23})
|
53
|
+
#
|
54
|
+
# action.article # => #<Article ...>
|
55
|
+
# action.tags # => [#<Tag ...>, #<Tag ...>]
|
56
|
+
#
|
57
|
+
# action.exposures # => { :article => #<Article ...>, :tags => [ ... ] }
|
58
|
+
def expose(*names)
|
59
|
+
class_eval do
|
60
|
+
names.each do |name|
|
61
|
+
attr_reader(name) unless attr_reader?(name)
|
62
|
+
end
|
63
|
+
|
64
|
+
exposures.push(*names)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Set of exposures attribute names
|
69
|
+
#
|
70
|
+
# @return [Array] the exposures attribute names
|
71
|
+
#
|
72
|
+
# @since 0.1.0
|
73
|
+
# @api private
|
74
|
+
def exposures
|
75
|
+
@exposures ||= []
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
# Check if the attr_reader is already defined
|
80
|
+
#
|
81
|
+
# @since 0.3.0
|
82
|
+
# @api private
|
83
|
+
def attr_reader?(name)
|
84
|
+
(instance_methods | private_instance_methods).include?(name)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Set of exposures
|
89
|
+
#
|
90
|
+
# @return [Hash] the exposures
|
91
|
+
#
|
92
|
+
# @since 0.1.0
|
93
|
+
#
|
94
|
+
# @see Hanami::Action::Exposable::ClassMethods.expose
|
95
|
+
def exposures
|
96
|
+
@exposures ||= {}.tap do |result|
|
97
|
+
self.class.exposures.each do |name|
|
98
|
+
result[name] = send(name)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Finalize the response
|
104
|
+
#
|
105
|
+
# @since 0.3.0
|
106
|
+
# @api private
|
107
|
+
#
|
108
|
+
# @see Hanami::Action#finish
|
109
|
+
def finish
|
110
|
+
super
|
111
|
+
exposures
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
module Hanami
|
2
|
+
module Action
|
3
|
+
# Container useful to transport data with the HTTP session
|
4
|
+
# It has a life span of one HTTP request or redirect.
|
5
|
+
#
|
6
|
+
# @since 0.3.0
|
7
|
+
# @api private
|
8
|
+
class Flash
|
9
|
+
# Session key where the data is stored
|
10
|
+
#
|
11
|
+
# @since 0.3.0
|
12
|
+
# @api private
|
13
|
+
SESSION_KEY = :__flash
|
14
|
+
|
15
|
+
# Session key where the last request_id is stored
|
16
|
+
#
|
17
|
+
# @since 0.4.0
|
18
|
+
# @api private
|
19
|
+
LAST_REQUEST_KEY = :__last_request_id
|
20
|
+
|
21
|
+
# Initialize a new Flash instance
|
22
|
+
#
|
23
|
+
# @param session [Rack::Session::Abstract::SessionHash] the session
|
24
|
+
# @param request_id [String] the HTTP Request ID
|
25
|
+
#
|
26
|
+
# @return [Hanami::Action::Flash] the flash
|
27
|
+
#
|
28
|
+
# @see http://www.rubydoc.info/gems/rack/Rack/Session/Abstract/SessionHash
|
29
|
+
# @see Hanami::Action::Rack#session_id
|
30
|
+
def initialize(session, request_id)
|
31
|
+
@session = session
|
32
|
+
@request_id = request_id
|
33
|
+
@last_request_id = session[LAST_REQUEST_KEY]
|
34
|
+
|
35
|
+
session[SESSION_KEY] ||= {}
|
36
|
+
session[SESSION_KEY][request_id] ||= {}
|
37
|
+
end
|
38
|
+
|
39
|
+
# Set the given value for the given key
|
40
|
+
#
|
41
|
+
# @param key [#to_s] the key
|
42
|
+
# @param value [Object] the value
|
43
|
+
#
|
44
|
+
# @since 0.3.0
|
45
|
+
# @api private
|
46
|
+
def []=(key, value)
|
47
|
+
data[key] = value
|
48
|
+
end
|
49
|
+
|
50
|
+
# Get the value associated to the given key, if any
|
51
|
+
#
|
52
|
+
# @return [Object,NilClass] the value
|
53
|
+
#
|
54
|
+
# @since 0.3.0
|
55
|
+
# @api private
|
56
|
+
def [](key)
|
57
|
+
last_request_flash.merge(data).fetch(key) do
|
58
|
+
_values.find {|data| !data[key].nil? }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Removes entirely the flash from the session if it has stale contents
|
63
|
+
# or if empty.
|
64
|
+
#
|
65
|
+
# @return [void]
|
66
|
+
#
|
67
|
+
# @since 0.3.0
|
68
|
+
# @api private
|
69
|
+
def clear
|
70
|
+
# FIXME we're just before a release and I can't find a proper way to reproduce
|
71
|
+
# this bug that I've found via a browser.
|
72
|
+
#
|
73
|
+
# It may happen that `#flash` is nil, and those two methods will fail
|
74
|
+
unless flash.nil?
|
75
|
+
expire_stale!
|
76
|
+
set_last_request_id!
|
77
|
+
remove!
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Check if there are contents stored in the flash from the current or the
|
82
|
+
# previous request.
|
83
|
+
#
|
84
|
+
# @return [TrueClass,FalseClass] the result of the check
|
85
|
+
#
|
86
|
+
# @since 0.3.0
|
87
|
+
# @api private
|
88
|
+
def empty?
|
89
|
+
_values.all?(&:empty?)
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
# The flash registry that holds the data for **all** the recent requests
|
95
|
+
#
|
96
|
+
# @return [Hash] the flash
|
97
|
+
#
|
98
|
+
# @since 0.3.0
|
99
|
+
# @api private
|
100
|
+
def flash
|
101
|
+
@session[SESSION_KEY] || {}
|
102
|
+
end
|
103
|
+
|
104
|
+
# The flash registry that holds the data **only for** the current request
|
105
|
+
#
|
106
|
+
# @return [Hash] the flash for the current request
|
107
|
+
#
|
108
|
+
# @since 0.3.0
|
109
|
+
# @api private
|
110
|
+
def data
|
111
|
+
flash[@request_id] || {}
|
112
|
+
end
|
113
|
+
|
114
|
+
# Expire the stale data from the previous request.
|
115
|
+
#
|
116
|
+
# @return [void]
|
117
|
+
#
|
118
|
+
# @since 0.3.0
|
119
|
+
# @api private
|
120
|
+
def expire_stale!
|
121
|
+
flash.each do |request_id, _|
|
122
|
+
flash.delete(request_id) if delete?(request_id)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Remove the flash entirely from the session if empty.
|
127
|
+
#
|
128
|
+
# @return [void]
|
129
|
+
#
|
130
|
+
# @since 0.3.0
|
131
|
+
# @api private
|
132
|
+
#
|
133
|
+
# @see Hanami::Action::Flash#empty?
|
134
|
+
def remove!
|
135
|
+
@session.delete(SESSION_KEY) if empty?
|
136
|
+
end
|
137
|
+
|
138
|
+
# Values from all the stored requests
|
139
|
+
#
|
140
|
+
# @return [Array]
|
141
|
+
#
|
142
|
+
# @since 0.3.0
|
143
|
+
# @api private
|
144
|
+
def _values
|
145
|
+
flash.values
|
146
|
+
end
|
147
|
+
|
148
|
+
# Determine if delete data from flash for the given Request ID
|
149
|
+
#
|
150
|
+
# @return [TrueClass,FalseClass] the result of the check
|
151
|
+
#
|
152
|
+
# @since 0.4.0
|
153
|
+
# @api private
|
154
|
+
#
|
155
|
+
# @see Hanami::Action::Flash#expire_stale!
|
156
|
+
def delete?(request_id)
|
157
|
+
![@request_id, @session[LAST_REQUEST_KEY]].include?(request_id)
|
158
|
+
end
|
159
|
+
|
160
|
+
# Get the last request session flash
|
161
|
+
#
|
162
|
+
# @return [Hash] the flash of last request
|
163
|
+
#
|
164
|
+
# @since 0.4.0
|
165
|
+
# @api private
|
166
|
+
def last_request_flash
|
167
|
+
flash[@last_request_id] || {}
|
168
|
+
end
|
169
|
+
|
170
|
+
# Store the last request_id to create the next flash with its values
|
171
|
+
# is current flash is not empty.
|
172
|
+
#
|
173
|
+
# @return [void]
|
174
|
+
# @since 0.4.0
|
175
|
+
# @api private
|
176
|
+
def set_last_request_id!
|
177
|
+
@session[LAST_REQUEST_KEY] = @request_id if !empty?
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|