hanami-controller 0.8.1 → 1.0.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
  SHA1:
3
- metadata.gz: 94316cf20a120464d9314f31c0ea0774d8256847
4
- data.tar.gz: 0d468b04cc1ae458ee3d2cb1188adfae48e63402
3
+ metadata.gz: 0f0fb43da2ad920ba9c799b41f4ccfc87eb5b438
4
+ data.tar.gz: 294e4ed9ebf6e18c13c52d560efb181f69ded99b
5
5
  SHA512:
6
- metadata.gz: 68a1d9c7ae87c693fa7a9ac85ae15b0736bdd1de6dc02f21a9ef320a08f6f1f9b0fc3e99b88a92186c7e1ebc5ebf48cb52b914a400f655c1699b12bdb8bbe61b
7
- data.tar.gz: b49bfaff6ee7d1150f1f1e99ea335948300d519c8522b200dc0b914ddc7a0d3f7ee9c9778fdc79abfa267998987aa65216f9f2488e09db2b9c1321bb5fc2b69b
6
+ metadata.gz: 6b7ce52381b3e383caf8a169f9c40af67e8a8a546503c89d0b3b7642fe8e36321ab3bf5bee8d844d9e26ace64d5c1c49f894f642b469dcac63c712d5025246b0
7
+ data.tar.gz: f6e6cfe2e117ce0d3946b308b2684dfd53ae31783510ec143f10cd9959e671338abe613bc70ef2070a2c5ecdd1383fbcffad76070cfd76e457ebf218be22759e
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.0.0beta1 - 2017-02-14
5
+ ### Added
6
+ - [Luca Guidi] Official support for Ruby: MRI 2.4
7
+
8
+ ### Fixed
9
+ - [Marcello Rocha & Luca Guidi] Avoid MIME type conflicts for `Action#format` detection
10
+ - [Matias H. Leidemer & Luca Guidi] Ensure `Flash` to return only fresh data
11
+ - [Luca Guidi] Ensure `session` keys to be accessed as symbols in action unit tests
12
+
13
+ ### Changed
14
+ - [Anton Davydov & Luca Guidi] Make it work only with Rack 2.0
15
+
4
16
  ## v0.8.1 - 2016-12-19
5
17
  ### Fixed
6
18
  - [Thorbjørn Hermansen] Don't pollute Rack env's `rack.exception` key if an exception is handled
data/README.md CHANGED
@@ -282,7 +282,7 @@ class Show
282
282
  expose :article
283
283
 
284
284
  def call(params)
285
- @article = ArticleRepository.find params[:id]
285
+ @article = ArticleRepository.new.find(params[:id])
286
286
  end
287
287
  end
288
288
 
@@ -19,8 +19,8 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ['lib']
20
20
  spec.required_ruby_version = '>= 2.3.0'
21
21
 
22
- spec.add_dependency 'rack', '~> 1.6', '>= 1.6.2'
23
- spec.add_dependency 'hanami-utils', '~> 0.9'
22
+ spec.add_dependency 'rack', '~> 2.0'
23
+ spec.add_dependency 'hanami-utils', '~> 1.0.0.beta1'
24
24
 
25
25
  spec.add_development_dependency 'bundler', '~> 1.6'
26
26
  spec.add_development_dependency 'rack-test', '~> 0.6'
@@ -15,6 +15,18 @@ module Hanami
15
15
  # @since 0.7.0
16
16
  ROUTER_PARAMS = 'router.params'.freeze
17
17
 
18
+ # The key that returns Rack session params from the Rack env
19
+ # Please note that this is used only when an action is unit tested.
20
+ #
21
+ # @since 1.0.0.beta1
22
+ # @api private
23
+ #
24
+ # @example
25
+ # # action unit test
26
+ # action.call('rack.session' => { 'foo' => 'bar' })
27
+ # action.session[:foo] # => "bar"
28
+ RACK_SESSION = 'rack.session'.freeze
29
+
18
30
  # @attr_reader env [Hash] the Rack env
19
31
  #
20
32
  # @since 0.7.0
@@ -37,7 +49,7 @@ module Hanami
37
49
  def initialize(env)
38
50
  @env = env
39
51
  @raw = _extract_params
40
- @params = Utils::Hash.new(@raw).deep_dup.symbolize!.to_h
52
+ @params = Utils::Hash.new(@raw).deep_dup.deep_symbolize!.to_h
41
53
  freeze
42
54
  end
43
55
 
@@ -143,7 +155,13 @@ module Hanami
143
155
  # @since 0.7.0
144
156
  # @api private
145
157
  def _router_params(fallback = {})
146
- env.fetch(ROUTER_PARAMS, fallback)
158
+ env.fetch(ROUTER_PARAMS) do
159
+ if session = fallback.delete(RACK_SESSION) # rubocop:disable Lint/AssignmentInCondition
160
+ fallback[RACK_SESSION] = Utils::Hash.new(session).symbolize!.to_hash
161
+ end
162
+
163
+ fallback
164
+ end
147
165
  end
148
166
  end
149
167
  end
@@ -55,7 +55,7 @@ module Hanami
55
55
  # @since 0.1.0
56
56
  def initialize(env, headers, default_options)
57
57
  @_headers = headers
58
- @cookies = Utils::Hash.new(extract(env)).symbolize!
58
+ @cookies = Utils::Hash.new(extract(env)).deep_symbolize!
59
59
  @default_options = default_options
60
60
  end
61
61
 
@@ -142,7 +142,7 @@ module Hanami
142
142
  # @since 0.3.0
143
143
  # @api private
144
144
  def _values
145
- flash.values
145
+ flash.select { |session_id, _| !delete?(session_id) }.values
146
146
  end
147
147
 
148
148
  # Determine if delete data from flash for the given Request ID
@@ -59,7 +59,7 @@ module Hanami
59
59
  #
60
60
  # @since 0.4.3
61
61
  def sending_file?
62
- @_body.is_a?(::Rack::File)
62
+ @_body.is_a?(::Rack::File::Iterator)
63
63
  end
64
64
  end
65
65
  end
@@ -1,7 +1,6 @@
1
1
  require 'rack/utils'
2
2
  require 'hanami/utils'
3
3
  require 'hanami/utils/kernel'
4
- require 'hanami/utils/deprecation'
5
4
 
6
5
  module Hanami
7
6
  module Action
@@ -41,6 +40,64 @@ module Hanami
41
40
  # @api private
42
41
  DEFAULT_CHARSET = 'utf-8'.freeze
43
42
 
43
+ # Most commom mime types used for responses
44
+ #
45
+ # @since 1.0.0.beta1
46
+ # @api private
47
+ MIME_TYPES = {
48
+ txt: 'text/plain',
49
+ html: 'text/html',
50
+ json: 'application/json',
51
+ manifest: 'text/cache-manifest',
52
+ atom: 'application/atom+xml',
53
+ avi: 'video/x-msvideo',
54
+ bmp: 'image/bmp',
55
+ bz: 'application/x-bzip',
56
+ bz2: 'application/x-bzip2',
57
+ chm: 'application/vnd.ms-htmlhelp',
58
+ css: 'text/css',
59
+ csv: 'text/csv',
60
+ flv: 'video/x-flv',
61
+ gif: 'image/gif',
62
+ gz: 'application/x-gzip',
63
+ h264: 'video/h264',
64
+ ico: 'image/vnd.microsoft.icon',
65
+ ics: 'text/calendar',
66
+ jpg: 'image/jpeg',
67
+ js: 'application/javascript',
68
+ mp4: 'video/mp4',
69
+ mov: 'video/quicktime',
70
+ mp3: 'audio/mpeg',
71
+ mp4a: 'audio/mp4',
72
+ mpg: 'video/mpeg',
73
+ oga: 'audio/ogg',
74
+ ogg: 'application/ogg',
75
+ ogv: 'video/ogg',
76
+ pdf: 'application/pdf',
77
+ pgp: 'application/pgp-encrypted',
78
+ png: 'image/png',
79
+ psd: 'image/vnd.adobe.photoshop',
80
+ rtf: 'application/rtf',
81
+ sh: 'application/x-sh',
82
+ svg: 'image/svg+xml',
83
+ swf: 'application/x-shockwave-flash',
84
+ tar: 'application/x-tar',
85
+ torrent: 'application/x-bittorrent',
86
+ tsv: 'text/tab-separated-values',
87
+ uri: 'text/uri-list',
88
+ vcs: 'text/x-vcalendar',
89
+ wav: 'audio/x-wav',
90
+ webm: 'video/webm',
91
+ wmv: 'video/x-ms-wmv',
92
+ woff: 'application/font-woff',
93
+ woff2: 'application/font-woff2',
94
+ wsdl: 'application/wsdl+xml',
95
+ xhtml: 'application/xhtml+xml',
96
+ xml: 'application/xml',
97
+ xslt: 'application/xslt+xml',
98
+ yml: 'text/yaml',
99
+ zip: 'application/zip' }.freeze
100
+
44
101
  # Override Ruby's hook for modules.
45
102
  # It includes Mime types logic
46
103
  #
@@ -62,7 +119,7 @@ module Hanami
62
119
  # @api private
63
120
  def format_to_mime_type(format)
64
121
  configuration.mime_type_for(format) ||
65
- ::Rack::Mime.mime_type(".#{ format }", nil) or
122
+ MIME_TYPES[format] or
66
123
  raise Hanami::Controller::UnknownFormatError.new(format)
67
124
  end
68
125
 
@@ -100,6 +157,8 @@ module Hanami
100
157
  format_to_mime_type(format)
101
158
  end
102
159
 
160
+ configuration.restrict_mime_types!(mime_types)
161
+
103
162
  before do
104
163
  unless mime_types.find {|mt| accept?(mt) }
105
164
  halt 406
@@ -298,12 +357,12 @@ module Hanami
298
357
  # When the format is set, the framework searches for a corresponding mime
299
358
  # type to be set as the `Content-Type` header of the response.
300
359
  # This lookup is performed first in the configuration, and then in
301
- # `Rack::Mime::MIME_TYPES`. If the lookup fails, it raises an error.
360
+ # `Hanami::Action::Mime::MIME_TYPES`. If the lookup fails, it raises an error.
302
361
  #
303
362
  # PERFORMANCE: Because `Hanami::Controller::Configuration#formats` is
304
- # smaller and looked up first than `Rack::Mime::MIME_TYPES`, we suggest to
305
- # configure the most common mime types used by your application, **even
306
- # if they are already present in that Rack constant**.
363
+ # smaller and looked up first than `Hanami::Action::Mime::MIME_TYPES`,
364
+ # we suggest to configure the most common mime types used by your
365
+ # application, **even if they are already present in that Rack constant**.
307
366
  #
308
367
  # @param format [#to_sym] the format
309
368
  #
@@ -482,8 +541,7 @@ module Hanami
482
541
  # @since 0.2.0
483
542
  # @api private
484
543
  def detect_format
485
- configuration.format_for(content_type) ||
486
- ::Rack::Mime::MIME_TYPES.key(content_type).gsub(/\A\./, '').to_sym
544
+ configuration.format_for(content_type) || MIME_TYPES.key(content_type)
487
545
  end
488
546
 
489
547
  # @since 0.3.0
@@ -282,7 +282,7 @@ module Hanami
282
282
  # end
283
283
  # end
284
284
  def send_file(path)
285
- result = File.new(path).call(@_env)
285
+ result = File.new(path, self.class.configuration.public_directory).call(@_env)
286
286
  headers.merge!(result[1])
287
287
  halt result[0], result[2]
288
288
  end
@@ -10,20 +10,27 @@ module Hanami
10
10
  #
11
11
  # @see Hanami::Action::Rack#send_file
12
12
  class File
13
+
14
+ # The key that returns path info from the Rack env
15
+ #
16
+ # @since 1.0.0.beta1
17
+ # @api private
18
+ PATH_INFO = "PATH_INFO".freeze
19
+
13
20
  # @param path [String,Pathname] file path
14
21
  #
15
22
  # @since 0.4.3
16
23
  # @api private
17
- def initialize(path)
18
- @file = ::Rack::File.new(nil)
24
+ def initialize(path, root)
25
+ @file = ::Rack::File.new(root)
19
26
  @path = path
20
27
  end
21
28
 
22
29
  # @since 0.4.3
23
30
  # @api private
24
31
  def call(env)
25
- @file.path = @path.to_s
26
- @file.serving(env)
32
+ env[PATH_INFO] = @path
33
+ @file.get(env)
27
34
  rescue Errno::ENOENT
28
35
  [404, {}, nil]
29
36
  end
@@ -26,6 +26,14 @@ module Hanami
26
26
  # @api private
27
27
  DEFAULT_ERROR_CODE = 500
28
28
 
29
+ # Default public directory
30
+ #
31
+ # It serves as base root for file downloads
32
+ #
33
+ # @since 1.0.0.beta1
34
+ # @api private
35
+ DEFAULT_PUBLIC_DIRECTORY = 'public'.freeze
36
+
29
37
  # Default Mime type to format mapping
30
38
  #
31
39
  # @since 0.2.0
@@ -212,7 +220,7 @@ module Hanami
212
220
  #
213
221
  # @param exception [Exception] an exception
214
222
  #
215
- # @since x.x.x
223
+ # @since 1.0.0.beta1
216
224
  # @api private
217
225
  #
218
226
  # @see Hanami::Controller::Configuration#handle_exception
@@ -423,10 +431,22 @@ module Hanami
423
431
  def mime_types
424
432
  @mime_types ||= begin
425
433
  ((@formats.keys - DEFAULT_FORMATS.keys) +
426
- ::Rack::Mime::MIME_TYPES.values).freeze
434
+ Hanami::Action::Mime::MIME_TYPES.values).freeze
427
435
  end
428
436
  end
429
437
 
438
+ # Restrict the MIME types set only to the given set
439
+ #
440
+ # @param mime_types [Array] the set of MIME types
441
+ #
442
+ # @since 1.0.0.beta1
443
+ # @api private
444
+ #
445
+ # @see Hanami::Action::Mime::ClassMethods#accept
446
+ def restrict_mime_types!(mime_types)
447
+ @mime_types = self.mime_types & mime_types
448
+ end
449
+
430
450
  # Set a format as default fallback for all the requests without a strict
431
451
  # requirement for the mime type.
432
452
  #
@@ -631,6 +651,14 @@ module Hanami
631
651
  @formats.key(format)
632
652
  end
633
653
 
654
+ def public_directory(value = nil)
655
+ if value.nil?
656
+ @public_directory
657
+ else
658
+ @public_directory = Pathname.new(Dir.pwd).join(value).to_s
659
+ end
660
+ end
661
+
634
662
  # Duplicate by copying the settings in a new instance.
635
663
  #
636
664
  # @return [Hanami::Controller::Configuration] a copy of the configuration
@@ -648,6 +676,7 @@ module Hanami
648
676
  c.default_response_format = default_response_format
649
677
  c.default_charset = default_charset
650
678
  c.default_headers = default_headers.dup
679
+ c.public_directory = public_directory
651
680
  c.cookies = cookies.dup
652
681
  end
653
682
  end
@@ -677,6 +706,7 @@ module Hanami
677
706
  @default_charset = nil
678
707
  @default_headers = {}
679
708
  @cookies = {}
709
+ @public_directory = ::File.join(Dir.pwd, "public")
680
710
  @action_module = ::Hanami::Action
681
711
  end
682
712
 
@@ -722,6 +752,7 @@ module Hanami
722
752
  attr_writer :default_charset
723
753
  attr_writer :default_headers
724
754
  attr_writer :cookies
755
+ attr_writer :public_directory
725
756
  end
726
757
  end
727
758
  end
@@ -3,6 +3,6 @@ module Hanami
3
3
  # Defines the version
4
4
  #
5
5
  # @since 0.1.0
6
- VERSION = '0.8.1'.freeze
6
+ VERSION = '1.0.0.beta1'.freeze
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hanami-controller
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 1.0.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-12-19 00:00:00.000000000 Z
13
+ date: 2017-02-14 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rack
@@ -18,34 +18,28 @@ dependencies:
18
18
  requirements:
19
19
  - - "~>"
20
20
  - !ruby/object:Gem::Version
21
- version: '1.6'
22
- - - ">="
23
- - !ruby/object:Gem::Version
24
- version: 1.6.2
21
+ version: '2.0'
25
22
  type: :runtime
26
23
  prerelease: false
27
24
  version_requirements: !ruby/object:Gem::Requirement
28
25
  requirements:
29
26
  - - "~>"
30
27
  - !ruby/object:Gem::Version
31
- version: '1.6'
32
- - - ">="
33
- - !ruby/object:Gem::Version
34
- version: 1.6.2
28
+ version: '2.0'
35
29
  - !ruby/object:Gem::Dependency
36
30
  name: hanami-utils
37
31
  requirement: !ruby/object:Gem::Requirement
38
32
  requirements:
39
33
  - - "~>"
40
34
  - !ruby/object:Gem::Version
41
- version: '0.9'
35
+ version: 1.0.0.beta1
42
36
  type: :runtime
43
37
  prerelease: false
44
38
  version_requirements: !ruby/object:Gem::Requirement
45
39
  requirements:
46
40
  - - "~>"
47
41
  - !ruby/object:Gem::Version
48
- version: '0.9'
42
+ version: 1.0.0.beta1
49
43
  - !ruby/object:Gem::Dependency
50
44
  name: bundler
51
45
  requirement: !ruby/object:Gem::Requirement
@@ -149,9 +143,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
149
143
  version: 2.3.0
150
144
  required_rubygems_version: !ruby/object:Gem::Requirement
151
145
  requirements:
152
- - - ">="
146
+ - - ">"
153
147
  - !ruby/object:Gem::Version
154
- version: '0'
148
+ version: 1.3.1
155
149
  requirements: []
156
150
  rubyforge_project:
157
151
  rubygems_version: 2.6.8