hanami 1.3.0.beta1 → 1.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -5
  3. data/FEATURES.md +17 -2
  4. data/LICENSE.md +1 -1
  5. data/README.md +5 -5
  6. data/bin/hanami +2 -2
  7. data/hanami.gemspec +14 -14
  8. data/lib/hanami.rb +1 -1
  9. data/lib/hanami/app.rb +1 -1
  10. data/lib/hanami/application.rb +2 -2
  11. data/lib/hanami/application_configuration.rb +3 -3
  12. data/lib/hanami/cli/commands.rb +2 -2
  13. data/lib/hanami/cli/commands/command.rb +4 -6
  14. data/lib/hanami/cli/commands/generate/action/action_spec.minitest.erb +1 -1
  15. data/lib/hanami/cli/commands/generate/action/view_spec.minitest.erb +1 -1
  16. data/lib/hanami/cli/commands/generate/app/application.erb +5 -18
  17. data/lib/hanami/cli/commands/generate/app/layout_spec.minitest.erb +2 -3
  18. data/lib/hanami/cli/commands/generate/app/layout_spec.rspec.erb +1 -2
  19. data/lib/hanami/cli/commands/generate/app/routes.erb +1 -1
  20. data/lib/hanami/cli/commands/new.rb +4 -4
  21. data/lib/hanami/cli/commands/new/Gemfile.erb +1 -2
  22. data/lib/hanami/cli/commands/new/README.md.erb +1 -1
  23. data/lib/hanami/cli/commands/new/config.ru.erb +1 -1
  24. data/lib/hanami/cli/commands/new/config/environment.erb +2 -2
  25. data/lib/hanami/cli/commands/new/gitignore.erb +2 -0
  26. data/lib/hanami/cli/commands/new/gitignore_with_sqlite.erb +2 -0
  27. data/lib/hanami/common_logger.rb +29 -3
  28. data/lib/hanami/components/app/assets.rb +1 -1
  29. data/lib/hanami/components/app/controller.rb +1 -1
  30. data/lib/hanami/components/app/routes.rb +8 -6
  31. data/lib/hanami/components/app/view.rb +1 -1
  32. data/lib/hanami/components/routes_inspector.rb +1 -1
  33. data/lib/hanami/configuration.rb +7 -4
  34. data/lib/hanami/configuration/app.rb +5 -2
  35. data/lib/hanami/early_hints.rb +1 -1
  36. data/lib/hanami/environment.rb +38 -10
  37. data/lib/hanami/{middleware.rb → middleware_stack.rb} +5 -5
  38. data/lib/hanami/rake_helper.rb +1 -1
  39. data/lib/hanami/rake_tasks.rb +1 -0
  40. data/lib/hanami/routes.rb +1 -1
  41. data/lib/hanami/setup.rb +1 -1
  42. data/lib/hanami/templates/welcome.html.erb +2 -2
  43. data/lib/hanami/version.rb +1 -1
  44. data/lib/hanami/welcome.rb +6 -1
  45. metadata +45 -34
@@ -1,5 +1,5 @@
1
1
  # Configure your routes here
2
- # See: http://hanamirb.org/guides/routing/overview/
2
+ # See: https://guides.hanamirb.org/routing/overview
3
3
  #
4
4
  # Example:
5
5
  # get '/hello', to: ->(env) { [200, {}, ['Hello from Hanami!']] }
@@ -301,7 +301,7 @@ module Hanami
301
301
  application_name: options.fetch(:application_name),
302
302
  application_base_url: options.fetch(:application_base_url),
303
303
  hanami_head: options.fetch(:hanami_head),
304
- hanami_model_version: '~> 1.3.beta',
304
+ hanami_model_version: '~> 1.3',
305
305
  code_reloading: code_reloading?,
306
306
  hanami_version: hanami_version,
307
307
  project_module: Utils::String.classify(project),
@@ -502,7 +502,7 @@ module Hanami
502
502
  # @since 1.1.0
503
503
  # @api private
504
504
  def generate_app(context)
505
- Hanami::CLI::Commands::New::App.new(command_name: "generate app", out: @out, files: @files).call(app: context.application_name, application_base_url: context.application_base_url, **context.options)
505
+ Hanami::CLI::Commands::New::App.new(out: @out, files: @files).call(app: context.application_name, application_base_url: context.application_base_url, **context.options)
506
506
  end
507
507
 
508
508
  # @since 1.1.0
@@ -565,8 +565,8 @@ module Hanami
565
565
 
566
566
  # @since 1.1.0
567
567
  # @api private
568
- def initialize(*)
569
- super
568
+ def initialize(*args, **kwargs)
569
+ super(*args, **kwargs)
570
570
  @templates = Templates.new(self.class.superclass)
571
571
  end
572
572
  end
@@ -10,7 +10,6 @@ gem 'hanami-controller', require: false, git: 'https://github.com/hanami/contro
10
10
  gem 'hanami-view', require: false, git: 'https://github.com/hanami/view.git', branch: 'develop'
11
11
  gem 'hanami-helpers', require: false, git: 'https://github.com/hanami/helpers.git', branch: 'develop'
12
12
  gem 'hanami-mailer', require: false, git: 'https://github.com/hanami/mailer.git', branch: 'develop'
13
- gem 'hanami-cli', require: false, git: 'https://github.com/hanami/cli.git', branch: 'develop'
14
13
  gem 'hanami-assets', require: false, git: 'https://github.com/hanami/assets.git', branch: 'develop'
15
14
  gem 'hanami-model', require: false, git: 'https://github.com/hanami/model.git', branch: 'develop'
16
15
  gem 'hanami', git: 'https://github.com/hanami/hanami.git', branch: 'develop'
@@ -34,7 +33,7 @@ gem 'haml'
34
33
  <%- if code_reloading -%>
35
34
  group :development do
36
35
  # Code reloading
37
- # See: http://hanamirb.org/guides/projects/code-reloading
36
+ # See: https://guides.hanamirb.org/projects/code-reloading
38
37
  gem 'shotgun', platforms: :ruby
39
38
  gem 'hanami-webconsole'
40
39
  end
@@ -30,4 +30,4 @@ How to prepare (create and migrate) DB for `development` and `test` environments
30
30
  % HANAMI_ENV=test bundle exec hanami db prepare
31
31
  ```
32
32
 
33
- Explore Hanami [guides](http://hanamirb.org/guides/), [API docs](http://docs.hanamirb.org/<%= Hanami::VERSION %>/), or jump in [chat](http://chat.hanamirb.org) for help. Enjoy! 🌸
33
+ Explore Hanami [guides](https://guides.hanamirb.org/), [API docs](http://docs.hanamirb.org/<%= Hanami::VERSION %>/), or jump in [chat](http://chat.hanamirb.org) for help. Enjoy! 🌸
@@ -1,3 +1,3 @@
1
- require './config/environment'
1
+ require_relative 'config/environment'
2
2
 
3
3
  run Hanami.app
@@ -30,12 +30,12 @@ Hanami.configure do
30
30
  mailer do
31
31
  root 'lib/<%= project %>/mailers'
32
32
 
33
- # See http://hanamirb.org/guides/mailers/delivery
33
+ # See https://guides.hanamirb.org/mailers/delivery
34
34
  delivery :test
35
35
  end
36
36
 
37
37
  environment :development do
38
- # See: http://hanamirb.org/guides/projects/logging
38
+ # See: https://guides.hanamirb.org/projects/logging
39
39
  logger level: :debug
40
40
  end
41
41
 
@@ -1,2 +1,4 @@
1
1
  /public/assets*
2
2
  /tmp
3
+ .env.local
4
+ .env.*.local
@@ -1,3 +1,5 @@
1
1
  /db/*.sqlite
2
2
  /public/assets*
3
3
  /tmp
4
+ .env.local
5
+ .env.*.local
@@ -1,4 +1,5 @@
1
1
  require 'rack/common_logger'
2
+ require 'hanami/utils/hash'
2
3
 
3
4
  module Hanami
4
5
  # Rack logger for Hanami.app
@@ -44,13 +45,17 @@ module Hanami
44
45
  # @api private
45
46
  FORM_HASH = 'rack.request.form_hash'.freeze
46
47
 
48
+ # @since 1.3.0
49
+ # @api private
50
+ ROUTER_PARAMS = 'router.params'.freeze
51
+
47
52
  # @since 1.0.0
48
53
  # @api private
49
54
  #
50
55
  # rubocop:disable Metrics/AbcSize
51
56
  # rubocop:disable Metrics/MethodLength
52
57
  def log(env, status, header, began_at)
53
- now = Time.now
58
+ now = ElapsedTime.call
54
59
  length = extract_content_length(header)
55
60
 
56
61
  msg = Hash[
@@ -58,7 +63,7 @@ module Hanami
58
63
  verb: env[REQUEST_METHOD],
59
64
  status: status.to_s[0..3],
60
65
  ip: env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR],
61
- path: env[SCRIPT_NAME] + env[PATH_INFO],
66
+ path: env[SCRIPT_NAME] + env[PATH_INFO].to_s,
62
67
  length: length,
63
68
  params: extract_params(env),
64
69
  elapsed: now - began_at
@@ -73,11 +78,32 @@ module Hanami
73
78
  logger.info(msg)
74
79
  end
75
80
  end
81
+ # rubocop:enable Metrics/MethodLength
82
+ # rubocop:enable Metrics/AbcSize
76
83
 
77
84
  # @since 1.1.0
78
85
  # @api private
79
86
  def extract_params(env)
80
- (env[QUERY_HASH] || {}).merge(env[FORM_HASH] || {})
87
+ result = env.fetch(QUERY_HASH, {})
88
+ result.merge!(env.fetch(FORM_HASH, {}))
89
+ result.merge!(Utils::Hash.deep_stringify(env.fetch(ROUTER_PARAMS, {})))
90
+ result
91
+ end
92
+
93
+ # Wrapper which uses Rack's monotonic clock_time (used for began_at since Rack 2.1.0)
94
+ #
95
+ # @since 1.3.4
96
+ # @api private
97
+ class ElapsedTime
98
+ @clock = if Gem::Version.new(Rack::RELEASE) >= Gem::Version.new('2.1.0')
99
+ -> { Rack::Utils.clock_time }
100
+ else
101
+ -> { Time.now }
102
+ end.freeze
103
+
104
+ def self.call
105
+ @clock.call
106
+ end
81
107
  end
82
108
  end
83
109
  end
@@ -5,7 +5,7 @@ module Hanami
5
5
  # @since 0.9.0
6
6
  # @api private
7
7
  module App
8
- # hanami-assets configuration for a sigle Hanami application in the project.
8
+ # hanami-assets configuration for a single Hanami application in the project.
9
9
  #
10
10
  # @since 0.9.0
11
11
  # @api private
@@ -8,7 +8,7 @@ module Hanami
8
8
  # @since 0.9.0
9
9
  # @api private
10
10
  module App
11
- # hanami-controller configuration for a sigle Hanami application in the project.
11
+ # hanami-controller configuration for a single Hanami application in the project.
12
12
  #
13
13
  # @since 0.9.0
14
14
  # @api private
@@ -8,7 +8,7 @@ module Hanami
8
8
  # @since 0.9.0
9
9
  # @api private
10
10
  module App
11
- # hanami-router configuration for a sigle Hanami application in the project.
11
+ # hanami-router configuration for a single Hanami application in the project.
12
12
  #
13
13
  # @since 0.9.0
14
14
  # @api private
@@ -39,17 +39,19 @@ module Hanami
39
39
  resolver = Hanami::Routing::EndpointResolver.new(pattern: config.controller_pattern, namespace: namespace)
40
40
  default_app = Hanami::Routing::Default.new
41
41
 
42
- Hanami::Router.new(
42
+ options = {
43
43
  resolver: resolver,
44
44
  default_app: default_app,
45
- parsers: config.body_parsers,
46
45
  scheme: config.scheme,
47
46
  host: config.host,
48
47
  port: config.port,
49
48
  prefix: config.path_prefix,
50
- force_ssl: config.force_ssl,
51
- &config.routes
52
- )
49
+ force_ssl: config.force_ssl
50
+ }
51
+
52
+ options[:parsers] = config.body_parsers if config.body_parsers.any?
53
+
54
+ Hanami::Router.new(options, &config.routes)
53
55
  end
54
56
  end
55
57
  end
@@ -5,7 +5,7 @@ module Hanami
5
5
  # @since 0.9.0
6
6
  # @api private
7
7
  module App
8
- # hanami-view configuration for a sigle Hanami application in the project.
8
+ # hanami-view configuration for a single Hanami application in the project.
9
9
  #
10
10
  # @since 0.9.0
11
11
  # @api private
@@ -51,7 +51,7 @@ module Hanami
51
51
  # @since 0.9.0
52
52
  # @api private
53
53
  def hanami_app?(klass)
54
- klass.ancestors.include?(Hanami::Application)
54
+ klass <= Hanami::Application
55
55
  end
56
56
 
57
57
  # @since 0.9.0
@@ -20,6 +20,7 @@ module Hanami
20
20
  # @param app [#call] an application compatible with Rack SPEC
21
21
  # @param options [Hash] a set of options
22
22
  # @option :at [String] options the mount point
23
+ # @option :host [String] options the mount point
23
24
  #
24
25
  # @since 0.9.0
25
26
  #
@@ -27,12 +28,14 @@ module Hanami
27
28
  # # config/environment.rb
28
29
  # # ...
29
30
  # Hanami.configure do
31
+ # mount Beta::Application, at: '/', host: 'beta.bookshelf.com'
32
+ # mount Admin::Application, at: '/api'
30
33
  # mount Web::Application, at: '/'
31
34
  #
32
35
  # # ...
33
36
  # end
34
37
  def mount(app, options)
35
- mounted[app] = App.new(app, options.fetch(:at))
38
+ mounted[app] = App.new(app, options)
36
39
  end
37
40
 
38
41
  # Configure database
@@ -75,7 +78,7 @@ module Hanami
75
78
  # mailer do
76
79
  # root 'lib/bookshelf/mailers'
77
80
  #
78
- # # See http://hanamirb.org/guides/mailers/delivery
81
+ # # See https://guides.hanamirb.org/mailers/delivery
79
82
  # delivery :test
80
83
  # end
81
84
  #
@@ -138,7 +141,7 @@ module Hanami
138
141
  # @api private
139
142
  def apps
140
143
  mounted.each_pair do |klass, app|
141
- yield(app) if klass.ancestors.include?(Hanami::Application)
144
+ yield(app) if klass <= Hanami::Application
142
145
  end
143
146
  end
144
147
 
@@ -151,7 +154,7 @@ module Hanami
151
154
  # @see Hanami.logger
152
155
  # @see Hanami::Logger
153
156
  #
154
- # @see http://hanamirb.org/guides/projects/logging/
157
+ # @see https://guides.hanamirb.org/projects/logging
155
158
  #
156
159
  # @example Basic Usage
157
160
  # # config/environment.rb
@@ -7,11 +7,14 @@ module Hanami
7
7
  class App < SimpleDelegator
8
8
  # @api private
9
9
  attr_reader :path_prefix
10
+ # @api private
11
+ attr_reader :host
10
12
 
11
13
  # @api private
12
- def initialize(app, path_prefix)
14
+ def initialize(app, options = {})
13
15
  super(app)
14
- @path_prefix = path_prefix
16
+ @path_prefix = options[:at]
17
+ @host = options[:host]
15
18
  end
16
19
  end
17
20
  end
@@ -3,7 +3,7 @@
3
3
  module Hanami
4
4
  # HTTP/2 Early Hints Rack middleware
5
5
  #
6
- # It sends extra responses **before** the main reponse is sent.
6
+ # It sends extra responses **before** the main response is sent.
7
7
  # These extra responses are HTTP/2 Early Hints (103).
8
8
  # They specify the web assets (javascripts, stylesheets, etc..) to be "pushed",
9
9
  # so modern browsers pre-fetch them in parallel with the main HTTP response.
@@ -36,6 +36,12 @@ module Hanami
36
36
  # @api private
37
37
  DEFAULT_ENV = 'development'.freeze
38
38
 
39
+ # Test environment
40
+ #
41
+ # @since 1.3.3
42
+ # @api private
43
+ TEST_ENV = 'test'.freeze
44
+
39
45
  # Production environment
40
46
  #
41
47
  # @since 0.6.0
@@ -48,11 +54,21 @@ module Hanami
48
54
  # @api private
49
55
  RACK_ENV_DEPLOYMENT = 'deployment'.freeze
50
56
 
51
- # Default `.env` per environment file name
57
+ # @since 1.3.3
58
+ # @api private
59
+ DOTENV_LOCAL_FILE = '.env.local'.freeze
60
+
61
+ # Default `.env` files that are loaded. The entries are ordered from highest
62
+ # to lowest priority.
52
63
  #
53
- # @since 0.2.0
64
+ # @since 1.3.3
54
65
  # @api private
55
- DEFAULT_DOTENV_ENV = '.env.%s'.freeze
66
+ DOTENV_FILES = [
67
+ '.env.%{environment}.local'.freeze,
68
+ DOTENV_LOCAL_FILE,
69
+ '.env.%{environment}'.freeze,
70
+ '.env'.freeze
71
+ ].freeze
56
72
 
57
73
  # Default configuration directory under application root
58
74
  #
@@ -132,9 +148,8 @@ module Hanami
132
148
  # located under the config directory. All the settings in those files will
133
149
  # be exported as `ENV` variables.
134
150
  #
135
- # Master .env file is ignored to suggest clear separation of environment
136
- # configurations and discourage putting sensitive information into source
137
- # control.
151
+ # This table: https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
152
+ # has more info on the priority of the .env files.
138
153
  #
139
154
  # The format of those `.env.<environment>` files follows UNIX and UNIX-like
140
155
  # operating system environment variable declaration format and compatible
@@ -391,7 +406,7 @@ module Hanami
391
406
  # @since 0.4.0
392
407
  # @api private
393
408
  def require_application_environment
394
- Bundler.setup(*bundler_groups)
409
+ ::Bundler.setup(*bundler_groups)
395
410
  require project_environment_configuration.to_s # if project_environment_configuration.exist?
396
411
  end
397
412
 
@@ -487,10 +502,13 @@ module Hanami
487
502
  # @since 0.2.0
488
503
  # @api private
489
504
  def set_application_env_vars!
490
- dotenv = root.join(DEFAULT_DOTENV_ENV % environment)
491
- return unless dotenv.exist?
505
+ DOTENV_FILES.each do |filename_format|
506
+ file = filename_format % { environment: environment }
507
+ next unless dotenv_applicable?(file)
492
508
 
493
- env.load!(dotenv)
509
+ path = root.join(file)
510
+ env.load!(path) if path.exist?
511
+ end
494
512
  end
495
513
 
496
514
  # @since 0.1.0
@@ -509,5 +527,15 @@ module Hanami
509
527
  env[RACK_ENV]
510
528
  end
511
529
  end
530
+
531
+ # @api private
532
+ # @since 1.3.3
533
+ #
534
+ # @see https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
535
+ def dotenv_applicable?(file)
536
+ return false if file == DOTENV_LOCAL_FILE && environment == TEST_ENV
537
+
538
+ true
539
+ end
512
540
  end
513
541
  end
@@ -6,12 +6,12 @@ module Hanami
6
6
  #
7
7
  # @since 0.1.0
8
8
  # @api private
9
- class Middleware
9
+ class MiddlewareStack
10
10
  # Instantiate a middleware stack
11
11
  #
12
12
  # @param configuration [Hanami::ApplicationConfiguration] the application's configuration
13
13
  #
14
- # @return [Hanami::Middleware] the new stack
14
+ # @return [Hanami::MiddlewareStack] the new stack
15
15
  #
16
16
  # @since 0.1.0
17
17
  # @api private
@@ -25,7 +25,7 @@ module Hanami
25
25
 
26
26
  # Load the middleware stack
27
27
  #
28
- # @return [Hanami::Middleware] the loaded middleware stack
28
+ # @return [Hanami::MiddlewareStack] the loaded middleware stack
29
29
  #
30
30
  # @since 0.2.0
31
31
  # @api private
@@ -62,7 +62,7 @@ module Hanami
62
62
  #
63
63
  # @since 0.2.0
64
64
  #
65
- # @see Hanami::Middleware#prepend
65
+ # @see Hanami::MiddlewareStack#prepend
66
66
  #
67
67
  # @example
68
68
  # # apps/web/application.rb
@@ -89,7 +89,7 @@ module Hanami
89
89
  #
90
90
  # @since 0.6.0
91
91
  #
92
- # @see Hanami::Middleware#use
92
+ # @see Hanami::MiddlewareStack#use
93
93
  #
94
94
  # @example
95
95
  # # apps/web/application.rb