hanami-controller 1.2.0 → 1.3.0.beta1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0fa2474de61eb665874dbb5aac1bc97558bbdfd255de8aaa7f21e659f18adb61
4
- data.tar.gz: e5fe8ce5a5bfae4768bb1c1966ddff3d6d2ace31e0996422520977ce4fdf0c8b
3
+ metadata.gz: 70d59d43ccadadc8779881bb8c2bbc9a324e5e68e84e9a68ac7ef994b6124ea6
4
+ data.tar.gz: fab5066f435669ac7dbf7d8d0b7b5d7ec4c52ea2aef4975985ab24542d073994
5
5
  SHA512:
6
- metadata.gz: 0cb4a8984ac4a16991662ac5ab90063a31349590cd14358b2c745da2fe5c523c4a2cf2db5aa8196d87508e57ac25ef5e6c8ebaeb9378051c7ec53e9ddcfc3177
7
- data.tar.gz: 8c7c414fbacbb6564df2ce58a1d512491e25ffda2a6e64c3779063c8e5791e3241b88bc451f8a048a913d1e292939acfdacb702f16dd2820b8b78c0ab4b981b1
6
+ metadata.gz: 40ebcfe48e2b61e4e45447cfa7d6c30a471dc949668895b0758a7519d0a6a1de810f4da6b73a42e2e7a69abc0fd759ce9da16d5a8633fafd473694d639347759
7
+ data.tar.gz: 6f1983a3efc8900850f5496b755d9cf769065bc60e3c2423ec97828cba619db5971b8af4a70d648588e858cda144aa761c5c7d63149d26f379e4ae70f2369c1e
data/CHANGELOG.md CHANGED
@@ -1,6 +1,18 @@
1
1
  # Hanami::Controller
2
2
  Complete, fast and testable actions for Rack
3
3
 
4
+ ## v1.3.0.beta1 - 2018-08-08
5
+ ### Added
6
+ - [Luca Guidi] Official support for JRuby 9.2.0.0
7
+
8
+ ### Fixed
9
+ - [Yuji Ueki] Ensure that if `If-None-Match` or `If-Modified-Since` response HTTP headers are missing, `Etag` or `Last-Modified` headers will be in response HTTP headers.
10
+ - [Gustavo Caso] Don't show flash message for the request after a HTTP redirect.
11
+ - [Gustavo Caso] Ensure `Hanami::Action::Flash#each`, `#map`, and `#empty?` to not reference stale flash data.
12
+
13
+ ### Deprecated
14
+ - [Gustavo Caso] Deprecate `Hanami::Action#parsed_request_body`
15
+
4
16
  ## v1.2.0 - 2018-04-11
5
17
 
6
18
  ## v1.2.0.rc2 - 2018-04-06
data/README.md CHANGED
@@ -4,12 +4,12 @@ Complete, fast and testable actions for Rack and [Hanami](http://hanamirb.org)
4
4
 
5
5
  ## Status
6
6
 
7
- [![Gem Version](https://badge.fury.io/rb/hanami-controller.png)](http://badge.fury.io/rb/hanami-controller)
8
- [![Build Status](https://secure.travis-ci.org/hanami/controller.png?branch=master)](http://travis-ci.org/hanami/controller?branch=master)
9
- [![Coverage](https://coveralls.io/repos/hanami/controller/badge.png?branch=master)](https://coveralls.io/r/hanami/controller)
10
- [![Code Climate](https://codeclimate.com/github/hanami/controller.png)](https://codeclimate.com/github/hanami/controller)
11
- [![Dependencies](https://gemnasium.com/hanami/controller.png)](https://gemnasium.com/hanami/controller)
12
- [![Inline docs](http://inch-ci.org/github/hanami/controller.png)](http://inch-ci.org/github/hanami/controller)
7
+ [![Gem Version](https://badge.fury.io/rb/hanami-controller.svg)](https://badge.fury.io/rb/hanami-controller)
8
+ [![TravisCI](https://travis-ci.org/hanami/controller.svg?branch=master)](https://travis-ci.org/hanami/controller)
9
+ [![CircleCI](https://circleci.com/gh/hanami/controller/tree/master.svg?style=svg)](https://circleci.com/gh/hanami/controller/tree/master)
10
+ [![Test Coverage](https://codecov.io/gh/hanami/controller/branch/master/graph/badge.svg)](https://codecov.io/gh/hanami/controller)
11
+ [![Depfu](https://badges.depfu.com/badges/7cd17419fba78b726be1353118fb01de/overview.svg)](https://depfu.com/github/hanami/controller?project=Bundler)
12
+ [![Inline Docs](http://inch-ci.org/github/hanami/controller.svg)](http://inch-ci.org/github/hanami/controller)
13
13
 
14
14
  ## Contact
15
15
 
@@ -20,10 +20,10 @@ Gem::Specification.new do |spec|
20
20
  spec.required_ruby_version = '>= 2.3.0'
21
21
 
22
22
  spec.add_dependency 'rack', '~> 2.0'
23
- spec.add_dependency 'hanami-utils', '~> 1.2'
23
+ spec.add_dependency 'hanami-utils', '~> 1.3.beta'
24
24
 
25
25
  spec.add_development_dependency 'bundler', '~> 1.6'
26
- spec.add_development_dependency 'rack-test', '~> 0.6'
26
+ spec.add_development_dependency 'rack-test', '~> 1.0'
27
27
  spec.add_development_dependency 'rake', '~> 12'
28
28
  spec.add_development_dependency 'rspec', '~> 3.7'
29
29
  end
@@ -41,7 +41,7 @@ module Hanami
41
41
  # @since 0.3.0
42
42
  # @api private
43
43
  def header
44
- { ETAG => @value } if none_match
44
+ { ETAG => @value } if @value
45
45
  end
46
46
 
47
47
  private
@@ -67,13 +67,13 @@ module Hanami
67
67
  # @since 0.3.0
68
68
  # @api private
69
69
  def fresh?
70
- !Hanami::Utils::Blank.blank?(modified_since) && Time.httpdate(modified_since).to_i >= @value.to_i
70
+ !Hanami::Utils::Blank.blank?(modified_since) && Time.httpdate(modified_since).to_i >= @value.to_time.to_i
71
71
  end
72
72
 
73
73
  # @since 0.3.0
74
74
  # @api private
75
75
  def header
76
- { LAST_MODIFIED => @value.httpdate } if modified_since
76
+ { LAST_MODIFIED => @value.httpdate } if @value && @value.respond_to?(:httpdate)
77
77
  end
78
78
 
79
79
  private
@@ -12,29 +12,26 @@ module Hanami
12
12
  # @api private
13
13
  SESSION_KEY = :__flash
14
14
 
15
- # Session key where the last request_id is stored
15
+ # Session key where keep data is store for redirect
16
16
  #
17
- # @since 0.4.0
17
+ # @since 1.3.0
18
18
  # @api private
19
- LAST_REQUEST_KEY = :__last_request_id
19
+ KEPT_KEY = :__kept_key
20
20
 
21
21
  # Initialize a new Flash instance
22
22
  #
23
23
  # @param session [Rack::Session::Abstract::SessionHash] the session
24
- # @param request_id [String] the HTTP Request ID
25
24
  #
26
25
  # @return [Hanami::Action::Flash] the flash
27
26
  #
28
27
  # @see http://www.rubydoc.info/gems/rack/Rack/Session/Abstract/SessionHash
29
28
  # @see Hanami::Action::Rack#session_id
30
- def initialize(session, request_id)
29
+ def initialize(session)
31
30
  @session = session
32
- @request_id = request_id
33
- @last_request_id = session[LAST_REQUEST_KEY]
34
- @merged = {}
31
+ @keep = false
35
32
 
36
- session[SESSION_KEY] ||= {}
37
- session[SESSION_KEY][request_id] ||= {}
33
+ session[KEPT_KEY] ||= []
34
+ session[SESSION_KEY] = {}
38
35
  end
39
36
 
40
37
  # Set the given value for the given key
@@ -45,7 +42,7 @@ module Hanami
45
42
  # @since 0.3.0
46
43
  # @api private
47
44
  def []=(key, value)
48
- data[key] = value
45
+ _data[key] = value
49
46
  end
50
47
 
51
48
  # Get the value associated to the given key, if any
@@ -55,28 +52,26 @@ module Hanami
55
52
  # @since 0.3.0
56
53
  # @api private
57
54
  def [](key)
58
- @merged.fetch(key) do
59
- _values.find {|data| !data[key].nil? }
60
- end
55
+ _data.fetch(key) { search_in_kept_data(key) }
61
56
  end
62
57
 
63
- # Iterates through data
58
+ # Iterates through current request data and kept data
64
59
  #
65
60
  # @param blk [Proc]
66
61
  #
67
62
  # @since 1.2.0
68
63
  def each(&blk)
69
- @merged.each(&blk)
64
+ _values.each(&blk)
70
65
  end
71
66
 
72
- # Iterates through data
67
+ # Iterates through current request data and kept data
73
68
  #
74
69
  # @param blk [Proc]
75
70
  # @return [Array]
76
71
  #
77
72
  # @since 1.2.0
78
73
  def map(&blk)
79
- @merged.map(&blk)
74
+ _values.map(&blk)
80
75
  end
81
76
 
82
77
  # Removes entirely the flash from the session if it has stale contents
@@ -91,11 +86,11 @@ module Hanami
91
86
  # this bug that I've found via a browser.
92
87
  #
93
88
  # It may happen that `#flash` is nil, and those two methods will fail
94
- unless flash.nil?
95
- expire_stale!
96
- remove!
97
- merge!
98
- set_last_request_id!
89
+ unless _data.nil?
90
+ update_kept_request_count
91
+ keep_data if @keep
92
+ expire_kept
93
+ remove
99
94
  end
100
95
  end
101
96
 
@@ -107,112 +102,167 @@ module Hanami
107
102
  # @since 0.3.0
108
103
  # @api private
109
104
  def empty?
110
- _values.all?(&:empty?)
105
+ _values.empty?
111
106
  end
112
107
 
113
108
  # @return [String]
114
109
  #
115
110
  # @since 1.0.0
116
111
  def inspect
117
- "#<#{self.class}:#{'0x%x' % (__id__ << 1)} #{@merged.inspect}>"
112
+ "#<#{self.class}:#{'0x%x' % (__id__ << 1)} {:data=>#{_data.inspect}, :kept=>#{kept_data.inspect}} >"
113
+ end
114
+
115
+ # Set @keep to true, is use when triggering a redirect, and the content of _data is not empty.
116
+ # @return [TrueClass, NilClass]
117
+ #
118
+ # @since 1.3.0
119
+ # @api private
120
+ #
121
+ # @see Hanami::Action::Flash#empty?
122
+ def keep!
123
+ return if empty?
124
+ @keep = true
118
125
  end
119
126
 
120
127
  private
121
128
 
122
- # The flash registry that holds the data for **all** the recent requests
129
+ # The flash registry that holds the data for the current requests
123
130
  #
124
131
  # @return [Hash] the flash
125
132
  #
126
133
  # @since 0.3.0
127
134
  # @api private
128
- def flash
135
+ def _data
129
136
  @session[SESSION_KEY] || {}
130
137
  end
131
138
 
132
- # The flash registry that holds the data **only for** the current request
139
+ # Remove the flash entirely from the session if empty.
133
140
  #
134
- # @return [Hash] the flash for the current request
141
+ # @return [void]
135
142
  #
136
143
  # @since 0.3.0
137
144
  # @api private
138
- def data
139
- flash[@request_id] || {}
145
+ #
146
+ # @see Hanami::Action::Flash#empty?
147
+ def remove
148
+ if empty?
149
+ @session.delete(SESSION_KEY)
150
+ @session.delete(KEPT_KEY)
151
+ end
140
152
  end
141
153
 
142
- # Expire the stale data from the previous request.
154
+ # Returns the values from current session and kept.
143
155
  #
144
- # @return [void]
156
+ # @return [Hash]
145
157
  #
146
158
  # @since 0.3.0
147
159
  # @api private
148
- def expire_stale!
149
- flash.each do |request_id, _|
150
- flash.delete(request_id) if delete?(request_id)
151
- end
160
+ def _values
161
+ _data.merge(kept_data)
152
162
  end
153
163
 
154
- # Remove the flash entirely from the session if empty.
164
+ # Get the kept request data
155
165
  #
156
- # @return [void]
166
+ # @return [Array]
157
167
  #
158
- # @since 0.3.0
168
+ # @since 1.3.0
159
169
  # @api private
160
- #
161
- # @see Hanami::Action::Flash#empty?
162
- def remove!
163
- @session.delete(SESSION_KEY) if empty?
170
+ def kept
171
+ @session[KEPT_KEY] || []
164
172
  end
165
173
 
166
- # @since 1.0.0
167
- # @api private
174
+ # Merge current data into KEPT_KEY hash
175
+ #
176
+ # @return [Hash] the current value of KEPT_KEY
168
177
  #
169
- # @see Hanami::Action::Flash#[]
170
- def merge!
171
- @merged = last_request_flash.merge(data)
178
+ # @since 1.3.0
179
+ # @api private
180
+ def keep_data
181
+ new_kept_data = kept << JSON.generate({ count: 0, data: _data })
182
+
183
+ update_kept(new_kept_data)
172
184
  end
173
185
 
174
- # Values from all the stored requests
186
+ # Removes from kept data those who have lived for more than two requests
175
187
  #
176
- # @return [Array]
188
+ # @return [Hash] the current value of KEPT_KEY
177
189
  #
178
- # @since 0.3.0
190
+ # @since 1.3.0
179
191
  # @api private
180
- def _values
181
- flash.select { |session_id, _| !delete?(session_id) }.values
192
+ def expire_kept
193
+ new_kept_data = kept.reject do |kept_data|
194
+ parsed = JSON.parse(kept_data)
195
+ parsed['count'] >= 2 if is_hash?(parsed) && parsed['count'].is_a?(Integer)
196
+ end
197
+
198
+ update_kept(new_kept_data)
182
199
  end
183
200
 
184
- # Determine if delete data from flash for the given Request ID
201
+ # Update the count of request for each kept data
185
202
  #
186
- # @return [TrueClass,FalseClass] the result of the check
203
+ # @return [Hash] the current value of KEPT_KEY
187
204
  #
188
- # @since 0.4.0
205
+ # @since 1.3.0
189
206
  # @api private
207
+ def update_kept_request_count
208
+ new_kept_data = kept.map do |kept_data|
209
+ parsed = JSON.parse(kept_data)
210
+ parsed['count'] += 1 if is_hash?(parsed) && parsed['count'].is_a?(Integer)
211
+ JSON.generate(parsed)
212
+ end
213
+
214
+ update_kept(new_kept_data)
215
+ end
216
+
217
+ # Search in the kept data for a match on the key
190
218
  #
191
- # @see Hanami::Action::Flash#expire_stale!
192
- def delete?(request_id)
193
- ![@request_id, @session[LAST_REQUEST_KEY]].include?(request_id)
219
+ # @param key [#to_s] the key
220
+ # @return [Object, NilClass]
221
+ #
222
+ # @since 1.3.0
223
+ # @api private
224
+ def search_in_kept_data(key)
225
+ string_key = key.to_s
226
+
227
+ data = kept.find do |kept_data|
228
+ parsed = JSON.parse(kept_data)
229
+ parsed['data'].fetch(string_key, nil) if is_hash?(parsed['data'])
230
+ end
231
+
232
+ JSON.parse(data)['data'][string_key] if data
194
233
  end
195
234
 
196
- # Get the last request session flash
235
+ # Set the given new_kept_data to KEPT_KEY
197
236
  #
198
- # @return [Hash] the flash of last request
237
+ # @param new_kept_data
238
+ # @return [Hash] the current value of KEPT_KEY
199
239
  #
200
- # @since 0.4.0
240
+ # @since 1.3.0
201
241
  # @api private
202
- def last_request_flash
203
- flash[@last_request_id] || {}
242
+ def update_kept(new_kept_data)
243
+ @session[KEPT_KEY] = new_kept_data
204
244
  end
205
245
 
206
- # Store the last request_id to create the next flash with its values
207
- # is current flash is not empty.
246
+ # Values from kept
208
247
  #
209
- # @return [void]
210
- # @since 0.4.0
248
+ # @return [Hash]
249
+ #
250
+ # @since 1.3.0
211
251
  # @api private
212
- def set_last_request_id!
213
- @session[LAST_REQUEST_KEY] = @request_id if !empty?
252
+ def kept_data
253
+ kept.each_with_object({}) { |kept_data, result| result.merge!(JSON.parse(kept_data)['data']) }
214
254
  end
215
255
 
256
+ # Check if data is a hash
257
+ #
258
+ # @param data
259
+ # @return [TrueClass, FalseClass]
260
+ #
261
+ # @since 1.3.0
262
+ # @api private
263
+ def is_hash?(data)
264
+ data && data.is_a?(Hash)
265
+ end
216
266
  end
217
267
  end
218
268
  end
@@ -3,6 +3,7 @@ require 'hanami/action/request'
3
3
  require 'hanami/action/base_params'
4
4
  require 'hanami/action/rack/callable'
5
5
  require 'hanami/action/rack/file'
6
+ require 'hanami/utils/deprecation'
6
7
 
7
8
  module Hanami
8
9
  module Action
@@ -245,7 +246,10 @@ module Hanami
245
246
  end
246
247
 
247
248
  # Return parsed request body
249
+ #
250
+ # @deprecated
248
251
  def parsed_request_body
252
+ Hanami::Utils::Deprecation.new('#parsed_request_body is deprecated and it will be removed in future versions')
249
253
  @_env.fetch(ROUTER_PARSED_BODY, nil)
250
254
  end
251
255
 
@@ -83,7 +83,7 @@ module Hanami
83
83
  #
84
84
  # @see Hanami::Action::Flash
85
85
  def flash
86
- @flash ||= Flash.new(session, request_id)
86
+ @flash ||= Flash.new(session)
87
87
  end
88
88
 
89
89
  # In case of validations errors, preserve those informations after a
@@ -134,7 +134,7 @@ module Hanami
134
134
  if params.respond_to?(:valid?)
135
135
  flash[ERRORS_KEY] = errors.to_a unless params.valid?
136
136
  end
137
-
137
+ flash.keep!
138
138
  super
139
139
  end
140
140
 
@@ -96,8 +96,8 @@ module Hanami
96
96
  # Hanami::Controller::Configuration.for(MyApp::Controllers::Dashboard)
97
97
  # # => will duplicate from MyApp::Controller
98
98
  def self.for(base)
99
- namespace = Utils::String.namespace(base)
100
- framework = Utils::Class.load_from_pattern!("(#{namespace}|Hanami)::Controller")
99
+ namespace = Utils::String.namespace(base.name)
100
+ framework = Utils::Class.load("#{namespace}::Controller") || Utils::Class.load!('Hanami::Controller')
101
101
  framework.configuration.duplicate
102
102
  end
103
103
 
@@ -3,6 +3,6 @@ module Hanami
3
3
  # Defines the version
4
4
  #
5
5
  # @since 0.1.0
6
- VERSION = '1.2.0'.freeze
6
+ VERSION = '1.3.0.beta1'.freeze
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hanami-controller
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-11 00:00:00.000000000 Z
11
+ date: 2018-08-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.2'
33
+ version: 1.3.beta
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.2'
40
+ version: 1.3.beta
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0.6'
61
+ version: '1.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0.6'
68
+ version: '1.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -153,12 +153,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
153
153
  version: 2.3.0
154
154
  required_rubygems_version: !ruby/object:Gem::Requirement
155
155
  requirements:
156
- - - ">="
156
+ - - ">"
157
157
  - !ruby/object:Gem::Version
158
- version: '0'
158
+ version: 1.3.1
159
159
  requirements: []
160
160
  rubyforge_project:
161
- rubygems_version: 2.7.6
161
+ rubygems_version: 2.7.7
162
162
  signing_key:
163
163
  specification_version: 4
164
164
  summary: Complete, fast and testable actions for Rack and Hanami