hanami 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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