hanami 0.8.0 → 0.9.0

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.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -0
  3. data/FEATURES.md +13 -0
  4. data/README.md +28 -1
  5. data/hanami.gemspec +20 -17
  6. data/lib/hanami.rb +106 -7
  7. data/lib/hanami/action/routing_helpers.rb +2 -2
  8. data/lib/hanami/app.rb +72 -0
  9. data/lib/hanami/application.rb +144 -183
  10. data/lib/hanami/application_configuration.rb +1541 -0
  11. data/lib/hanami/application_name.rb +2 -2
  12. data/lib/hanami/application_namespace.rb +12 -0
  13. data/lib/hanami/assets/asset.rb +3 -1
  14. data/lib/hanami/assets/static.rb +3 -9
  15. data/lib/hanami/cli.rb +10 -7
  16. data/lib/hanami/cli_sub_commands/assets.rb +1 -9
  17. data/lib/hanami/cli_sub_commands/generate.rb +16 -0
  18. data/lib/hanami/commands/apps.rb +4 -0
  19. data/lib/hanami/commands/assets/precompile.rb +6 -19
  20. data/lib/hanami/commands/command.rb +64 -0
  21. data/lib/hanami/commands/console.rb +37 -26
  22. data/lib/hanami/commands/db/apply.rb +4 -2
  23. data/lib/hanami/commands/db/console.rb +11 -27
  24. data/lib/hanami/commands/db/create.rb +4 -2
  25. data/lib/hanami/commands/db/drop.rb +4 -2
  26. data/lib/hanami/commands/db/migrate.rb +11 -5
  27. data/lib/hanami/commands/db/prepare.rb +4 -2
  28. data/lib/hanami/commands/db/version.rb +4 -2
  29. data/lib/hanami/commands/generate/abstract.rb +5 -7
  30. data/lib/hanami/commands/generate/action.rb +18 -6
  31. data/lib/hanami/commands/generate/app.rb +15 -2
  32. data/lib/hanami/commands/generate/migration.rb +3 -2
  33. data/lib/hanami/commands/generate/model.rb +4 -3
  34. data/lib/hanami/commands/generate/secret_token.rb +31 -0
  35. data/lib/hanami/commands/new/abstract.rb +14 -5
  36. data/lib/hanami/commands/new/container.rb +1 -0
  37. data/lib/hanami/commands/routes.rb +5 -22
  38. data/lib/hanami/commands/server.rb +14 -142
  39. data/lib/hanami/components.rb +107 -0
  40. data/lib/hanami/components/app/assets.rb +55 -0
  41. data/lib/hanami/components/app/controller.rb +69 -0
  42. data/lib/hanami/components/app/logger.rb +30 -0
  43. data/lib/hanami/components/app/routes.rb +51 -0
  44. data/lib/hanami/components/app/view.rb +40 -0
  45. data/lib/hanami/components/component.rb +166 -0
  46. data/lib/hanami/components/components.rb +366 -0
  47. data/lib/hanami/components/routes_inspector.rb +70 -0
  48. data/lib/hanami/config/load_paths.rb +7 -6
  49. data/lib/hanami/config/mapper.rb +1 -1
  50. data/lib/hanami/config/security.rb +0 -8
  51. data/lib/hanami/configuration.rb +27 -1697
  52. data/lib/hanami/env.rb +67 -0
  53. data/lib/hanami/environment.rb +31 -21
  54. data/lib/hanami/environment_application_configurations.rb +30 -0
  55. data/lib/hanami/frameworks.rb +1 -0
  56. data/lib/hanami/generators/app/application.rb.tt +2 -2
  57. data/lib/hanami/generators/application/app/Gemfile.tt +3 -1
  58. data/lib/hanami/generators/application/app/config/application.rb.tt +2 -2
  59. data/lib/hanami/generators/application/app/gitignore_with_sqlite.tt +3 -0
  60. data/lib/hanami/generators/application/app/lib/app_name.rb.tt +4 -25
  61. data/lib/hanami/generators/application/app/spec_helper.rb.minitest.tt +1 -1
  62. data/lib/hanami/generators/application/app/spec_helper.rb.rspec.tt +1 -1
  63. data/lib/hanami/generators/application/container/Gemfile.tt +3 -1
  64. data/lib/hanami/generators/application/container/capybara.rb.rspec.tt +1 -1
  65. data/lib/hanami/generators/application/container/config.ru.tt +1 -1
  66. data/lib/hanami/generators/application/container/config/environment.rb.tt +35 -1
  67. data/lib/hanami/generators/application/container/features_helper.rb.minitest.tt +1 -1
  68. data/lib/hanami/generators/application/container/gitignore_with_sqlite.tt +3 -0
  69. data/lib/hanami/generators/application/container/lib/project.rb.tt +1 -57
  70. data/lib/hanami/generators/application/container/spec_helper.rb.minitest.tt +1 -1
  71. data/lib/hanami/generators/application/container/spec_helper.rb.rspec.tt +2 -3
  72. data/lib/hanami/generators/database_config.rb +8 -11
  73. data/lib/hanami/generators/model/entity.rb.tt +1 -2
  74. data/lib/hanami/generators/model/repository.rb.tt +1 -2
  75. data/lib/hanami/generators/template_engine.rb +8 -3
  76. data/lib/hanami/generators/test_framework.rb +4 -3
  77. data/lib/hanami/middleware.rb +41 -21
  78. data/lib/hanami/rake_helper.rb +6 -8
  79. data/lib/hanami/server.rb +43 -33
  80. data/lib/hanami/static.rb +2 -2
  81. data/lib/hanami/version.rb +35 -1
  82. data/lib/hanami/welcome.rb +4 -5
  83. metadata +68 -42
  84. data/lib/hanami/commands/db/abstract.rb +0 -19
  85. data/lib/hanami/config/configure.rb +0 -17
  86. data/lib/hanami/config/mapping.rb +0 -12
  87. data/lib/hanami/container.rb +0 -71
  88. data/lib/hanami/generators/application/container/gitignore_with_db.tt +0 -4
  89. data/lib/hanami/loader.rb +0 -257
  90. data/lib/hanami/repositories/car_repository.rb +0 -3
  91. data/lib/hanami/repositories/name_repository.rb +0 -3
data/lib/hanami/env.rb ADDED
@@ -0,0 +1,67 @@
1
+ begin
2
+ require 'dotenv'
3
+ rescue LoadError # rubocop:disable Lint/HandleExceptions
4
+ end
5
+
6
+ module Hanami
7
+ # Encapsulate access to ENV
8
+ #
9
+ # @since 0.9.0
10
+ # @api private
11
+ class Env
12
+ # Create a new instance
13
+ #
14
+ # @param env [#[],#[]=] a Hash like object. It defaults to ENV
15
+ #
16
+ # @return [Hanami::Env]
17
+ #
18
+ # @since 0.9.0
19
+ # @api private
20
+ def initialize(env: ENV)
21
+ @env = env
22
+ end
23
+
24
+ # Return a value, if found
25
+ #
26
+ # @param key [String] the key
27
+ #
28
+ # @return [String,NilClass] the value, if found
29
+ #
30
+ # @since 0.9.0
31
+ # @api private
32
+ def [](key)
33
+ @env[key]
34
+ end
35
+
36
+ # Sets a value
37
+ #
38
+ # @param key [String] the key
39
+ # @param value [String] the value
40
+ #
41
+ # @since 0.9.0
42
+ # @api private
43
+ def []=(key, value)
44
+ @env[key] = value
45
+ end
46
+
47
+ # Loads a dotenv file and updates self
48
+ #
49
+ # @param path [String, Pathname] the path to the dotenv file
50
+ #
51
+ # @return void
52
+ #
53
+ # @since 0.9.0
54
+ # @api private
55
+ def load!(path)
56
+ return unless defined?(Dotenv)
57
+
58
+ contents = ::File.open(path, "rb:bom|utf-8", &:read)
59
+ parsed = Dotenv::Parser.call(contents)
60
+
61
+ parsed.each do |k, v|
62
+ @env[k] = v
63
+ end
64
+ nil
65
+ end
66
+ end
67
+ end
@@ -2,11 +2,9 @@ require 'thread'
2
2
  require 'pathname'
3
3
  require 'hanami/utils'
4
4
  require 'hanami/utils/hash'
5
+ require 'hanami/env'
5
6
  require 'hanami/hanamirc'
6
- begin
7
- require 'dotenv'
8
- rescue LoadError
9
- end
7
+ require 'hanami/components'
10
8
 
11
9
  module Hanami
12
10
  # Define and expose information about the Hanami environment.
@@ -196,8 +194,10 @@ module Hanami
196
194
  # # the one defined in the parent (eg `FOO` is overwritten). All the
197
195
  # # other settings (eg `XYZ`) will be left untouched.
198
196
  def initialize(options = {})
197
+ opts = options.to_h.dup
198
+ @env = Hanami::Env.new(env: opts.delete(:env) || ENV)
199
199
  @options = Hanami::Hanamirc.new(root).options
200
- @options.merge! Utils::Hash.new(options.clone).symbolize!
200
+ @options.merge! Utils::Hash.new(opts.clone).symbolize!
201
201
  LOCK.synchronize { set_env_vars! }
202
202
  end
203
203
 
@@ -218,7 +218,7 @@ module Hanami
218
218
  #
219
219
  # @see Hanami::Environment::DEFAULT_ENV
220
220
  def environment
221
- @environment ||= ENV[HANAMI_ENV] || rack_env || DEFAULT_ENV
221
+ @environment ||= env[HANAMI_ENV] || rack_env || DEFAULT_ENV
222
222
  end
223
223
 
224
224
  # @since 0.3.1
@@ -304,9 +304,9 @@ module Hanami
304
304
  # @see Hanami::Environment::DEFAULT_HOST
305
305
  # @see Hanami::Environment::LISTEN_ALL_HOST
306
306
  def host
307
- @host ||= @options.fetch(:host) {
308
- ENV[HANAMI_HOST] || default_host
309
- }
307
+ @host ||= @options.fetch(:host) do
308
+ env[HANAMI_HOST] || default_host
309
+ end
310
310
  end
311
311
 
312
312
  # The HTTP port
@@ -324,7 +324,9 @@ module Hanami
324
324
  #
325
325
  # @see Hanami::Environment::DEFAULT_PORT
326
326
  def port
327
- @port ||= @options.fetch(:port) { ENV[HANAMI_PORT] || DEFAULT_PORT }.to_i
327
+ @port ||= @options.fetch(:port) do
328
+ env[HANAMI_PORT] || DEFAULT_PORT
329
+ end.to_i
328
330
  end
329
331
 
330
332
  # Path to the Rack configuration file
@@ -366,6 +368,8 @@ module Hanami
366
368
  root.join(@options.fetch(:environment) { config.join(DEFAULT_ENVIRONMENT_CONFIG) })
367
369
  end
368
370
 
371
+ alias project_environment_configuration env_config
372
+
369
373
  # Require application environment
370
374
  #
371
375
  # Eg <tt>require "config/environment"</tt>.
@@ -373,9 +377,11 @@ module Hanami
373
377
  # @since 0.4.0
374
378
  # @api private
375
379
  def require_application_environment
376
- require env_config.to_s #if env_config.exist?
380
+ require project_environment_configuration.to_s # if project_environment_configuration.exist?
377
381
  end
378
382
 
383
+ alias require_project_environment require_application_environment
384
+
379
385
  # Determine if activate code reloading for the current environment while
380
386
  # running the server.
381
387
  #
@@ -401,10 +407,10 @@ module Hanami
401
407
  # @since 0.4.0
402
408
  # @api private
403
409
  def architecture
404
- @options.fetch(:architecture) {
410
+ @options.fetch(:architecture) do
405
411
  puts "Cannot recognize Hanami architecture, please check `.hanamirc'"
406
412
  exit 1
407
- }
413
+ end
408
414
  end
409
415
 
410
416
  # @since 0.4.0
@@ -416,7 +422,7 @@ module Hanami
416
422
  # @since 0.6.0
417
423
  # @api private
418
424
  def serve_static_assets?
419
- SERVE_STATIC_ASSETS_ENABLED == ENV[SERVE_STATIC_ASSETS]
425
+ SERVE_STATIC_ASSETS_ENABLED == env[SERVE_STATIC_ASSETS]
420
426
  end
421
427
 
422
428
  # @since 0.6.0
@@ -463,6 +469,8 @@ module Hanami
463
469
 
464
470
  private
465
471
 
472
+ attr_reader :env
473
+
466
474
  # @since 0.1.0
467
475
  # @api private
468
476
  def set_env_vars!
@@ -473,16 +481,18 @@ module Hanami
473
481
  # @since 0.2.0
474
482
  # @api private
475
483
  def set_hanami_env_vars!
476
- ENV[HANAMI_ENV] = ENV[RACK_ENV] = environment
477
- ENV[HANAMI_HOST] = host
478
- ENV[HANAMI_PORT] = port.to_s
484
+ env[HANAMI_ENV] = env[RACK_ENV] = environment
485
+ env[HANAMI_HOST] = host
486
+ env[HANAMI_PORT] = port.to_s
479
487
  end
480
488
 
481
489
  # @since 0.2.0
482
490
  # @api private
483
491
  def set_application_env_vars!
484
- return unless defined?(Dotenv) && (dotenv = root.join(DEFAULT_DOTENV_ENV % environment)).exist?
485
- Dotenv.overload dotenv
492
+ dotenv = root.join(DEFAULT_DOTENV_ENV % environment)
493
+ return unless dotenv.exist?
494
+
495
+ env.load!(dotenv)
486
496
  end
487
497
 
488
498
  # @since 0.1.0
@@ -494,11 +504,11 @@ module Hanami
494
504
  # @since 0.6.0
495
505
  # @api private
496
506
  def rack_env
497
- case ENV[RACK_ENV]
507
+ case env[RACK_ENV]
498
508
  when RACK_ENV_DEPLOYMENT
499
509
  PRODUCTION_ENV
500
510
  else
501
- ENV[RACK_ENV]
511
+ env[RACK_ENV]
502
512
  end
503
513
  end
504
514
  end
@@ -0,0 +1,30 @@
1
+ module Hanami
2
+ class EnvironmentApplicationConfigurations
3
+ ALL = :all
4
+
5
+ def initialize
6
+ @configurations = Concurrent::Hash.new { |k, v| k[v] = [] }
7
+ end
8
+
9
+ def add(environment, &blk)
10
+ env = (environment || ALL).to_sym
11
+ configurations[env].push(blk)
12
+ end
13
+
14
+ def each(environment, &blk)
15
+ configurations.each do |env, blks|
16
+ next unless matching_env?(environment, env)
17
+ blks.each(&blk)
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :configurations
24
+
25
+ def matching_env?(environment, env)
26
+ environment.to_sym == env ||
27
+ env == ALL
28
+ end
29
+ end
30
+ end
@@ -1,3 +1,4 @@
1
+ require 'hanami/utils'
1
2
  require 'hanami/validations'
2
3
  require 'hanami/router'
3
4
  require 'hanami/view'
@@ -325,10 +325,10 @@ module <%= config[:classified_app_name] %>
325
325
  # See: http://www.rubydoc.info/gems/hanami-assets#Configuration
326
326
  compile false
327
327
 
328
- # Use digest file name for asset paths
328
+ # Use fingerprint file name for asset paths
329
329
  #
330
330
  # See: http://hanamirb.org/guides/assets/overview
331
- digest true
331
+ fingerprint true
332
332
 
333
333
  # Content Delivery Network (CDN)
334
334
  #
@@ -31,12 +31,14 @@ gem 'slim'
31
31
  gem 'haml'
32
32
  <%- end -%>
33
33
 
34
+ <%- unless Hanami::Utils.jruby? -%>
34
35
  group :development do
35
36
  # Code reloading
36
- # See: http://hanamirb.org/guides/applications/code-reloading
37
+ # See: http://hanamirb.org/guides/projects/code-reloading
37
38
  gem 'shotgun'
38
39
  end
39
40
 
41
+ <%- end -%>
40
42
  group :test, :development do
41
43
  gem 'dotenv', '~> 2.0'
42
44
  end
@@ -324,10 +324,10 @@ module <%= config[:classified_app_name] %>
324
324
  # See: http://www.rubydoc.info/gems/hanami-assets#Configuration
325
325
  compile false
326
326
 
327
- # Use digest file name for asset paths
327
+ # Use fingerprint file name for asset paths
328
328
  #
329
329
  # See: http://hanamirb.org/guides/assets/overview
330
- digest true
330
+ fingerprint true
331
331
 
332
332
  # Content Delivery Network (CDN)
333
333
  #
@@ -0,0 +1,3 @@
1
+ /db/*.sqlite
2
+ /public/assets*
3
+ /tmp
@@ -7,18 +7,12 @@ Hanami::Model.configure do
7
7
  #
8
8
  # Available options:
9
9
  #
10
- # * File System adapter
11
- # adapter type: :file_system, uri: 'file:///db/bookshelf_development'
12
- #
13
- # * Memory adapter
14
- # adapter type: :memory, uri: 'memory://localhost/<%= config[:app_name] %>_development'
15
- #
16
10
  # * SQL adapter
17
- # adapter type: :sql, uri: 'sqlite://db/<%= config[:app_name] %>_development.sqlite3'
18
- # adapter type: :sql, uri: 'postgres://localhost/<%= config[:app_name] %>_development'
19
- # adapter type: :sql, uri: 'mysql://localhost/<%= config[:app_name] %>_development'
11
+ # adapter :sql, 'sqlite://db/<%= config[:app_name] %>_development.sqlite3'
12
+ # adapter :sql, 'postgres://localhost/<%= config[:app_name] %>_development'
13
+ # adapter :sql, 'mysql://localhost/<%= config[:app_name] %>_development'
20
14
  #
21
- adapter type: :<%= config[:database_config][:type] %>, uri: ENV['DATABASE_URL']
15
+ adapter :<%= config[:database_config][:type] %>, ENV['DATABASE_URL']
22
16
 
23
17
  <%- if config[:database_config][:type] == :sql -%>
24
18
  ##
@@ -26,22 +20,7 @@ Hanami::Model.configure do
26
20
  #
27
21
  migrations 'db/migrations'
28
22
  schema 'db/schema.sql'
29
-
30
23
  <%- end -%>
31
- ##
32
- # Database mapping
33
- #
34
- # Intended for specifying application wide mappings.
35
- #
36
- mapping do
37
- # collection :users do
38
- # entity User
39
- # repository UserRepository
40
- #
41
- # attribute :id, Integer
42
- # attribute :name, String
43
- # end
44
- end
45
24
  end.load!
46
25
 
47
26
  Hanami::Mailer.configure do
@@ -4,4 +4,4 @@ ENV['HANAMI_ENV'] ||= 'test'
4
4
  require_relative '../config/environment'
5
5
  require 'minitest/autorun'
6
6
 
7
- Hanami::Application.preload!
7
+ Hanami.boot
@@ -2,7 +2,7 @@
2
2
  ENV['HANAMI_ENV'] ||= 'test'
3
3
 
4
4
  require_relative '../config/environment'
5
- Hanami::Application.preload!
5
+ Hanami.boot
6
6
 
7
7
  Dir[__dir__ + '/support/**/*.rb'].each { |f| require f }
8
8
 
@@ -31,12 +31,14 @@ gem 'slim'
31
31
  gem 'haml'
32
32
  <%- end -%>
33
33
 
34
+ <%- if config[:code_reloading] -%>
34
35
  group :development do
35
36
  # Code reloading
36
- # See: http://hanamirb.org/guides/applications/code-reloading
37
+ # See: http://hanamirb.org/guides/projects/code-reloading
37
38
  gem 'shotgun'
38
39
  end
39
40
 
41
+ <%- end -%>
40
42
  group :test, :development do
41
43
  gem 'dotenv', '~> 2.0'
42
44
  end
@@ -2,7 +2,7 @@ module RSpec
2
2
  module FeatureExampleGroup
3
3
  def self.included(group)
4
4
  group.metadata[:type] = :feature
5
- Capybara.app = Hanami::Container.new
5
+ Capybara.app = Hanami.app
6
6
  end
7
7
  end
8
8
  end
@@ -1,3 +1,3 @@
1
1
  require './config/environment'
2
2
 
3
- run Hanami::Container.new
3
+ run Hanami.app
@@ -1,6 +1,40 @@
1
1
  require 'bundler/setup'
2
2
  require 'hanami/setup'
3
+ require 'hanami/model'
3
4
  require_relative '../lib/<%= config[:project_name] %>'
4
5
 
5
- Hanami::Container.configure do
6
+ Hanami.configure do
7
+
8
+ model do
9
+ ##
10
+ # Database adapter
11
+ #
12
+ # Available options:
13
+ #
14
+ # * SQL adapter
15
+ # adapter :sql, 'sqlite://db/<%= config[:project_name] %>_development.sqlite3'
16
+ # adapter :sql, 'postgres://localhost/<%= config[:project_name] %>_development'
17
+ # adapter :sql, 'mysql://localhost/<%= config[:project_name] %>_development'
18
+ #
19
+ adapter :<%= config[:database_config][:type] %>, ENV['DATABASE_URL']
20
+
21
+ <%- if config[:database_config][:type] == :sql -%>
22
+ ##
23
+ # Migrations
24
+ #
25
+ migrations 'db/migrations'
26
+ schema 'db/schema.sql'
27
+ <%- end -%>
28
+ end
29
+
30
+ mailer do
31
+ root 'lib/<%= config[:project_name] %>/mailers'
32
+
33
+ # See http://hanamirb.org/guides/mailers/delivery
34
+ delivery do
35
+ development :test
36
+ test :test
37
+ # production :smtp, address: ENV['SMTP_PORT'], port: 1025
38
+ end
39
+ end
6
40
  end
@@ -4,7 +4,7 @@ require_relative './spec_helper'
4
4
  require 'capybara'
5
5
  require 'capybara/dsl'
6
6
 
7
- Capybara.app = Hanami::Container.new
7
+ Capybara.app = Hanami.app
8
8
 
9
9
  class MiniTest::Spec
10
10
  include Capybara::DSL