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
@@ -0,0 +1,3 @@
1
+ /db/*.sqlite
2
+ /public/assets*
3
+ /tmp
@@ -1,57 +1 @@
1
- require 'hanami/model'
2
- require 'hanami/mailer'
3
- Dir["#{ __dir__ }/<%= config[:project_name] %>/**/*.rb"].each { |file| require_relative file }
4
-
5
- Hanami::Model.configure do
6
- ##
7
- # Database adapter
8
- #
9
- # Available options:
10
- #
11
- # * File System adapter
12
- # adapter type: :file_system, uri: 'file:///db/bookshelf_development'
13
- #
14
- # * Memory adapter
15
- # adapter type: :memory, uri: 'memory://localhost/<%= config[:project_name] %>_development'
16
- #
17
- # * SQL adapter
18
- # adapter type: :sql, uri: 'sqlite://db/<%= config[:project_name] %>_development.sqlite3'
19
- # adapter type: :sql, uri: 'postgres://localhost/<%= config[:project_name] %>_development'
20
- # adapter type: :sql, uri: 'mysql://localhost/<%= config[:project_name] %>_development'
21
- #
22
- adapter type: :<%= config[:database_config][:type] %>, uri: ENV['DATABASE_URL']
23
-
24
- <%- if config[:database_config][:type] == :sql -%>
25
- ##
26
- # Migrations
27
- #
28
- migrations 'db/migrations'
29
- schema 'db/schema.sql'
30
-
31
- <%- end -%>
32
- ##
33
- # Database mapping
34
- #
35
- # Intended for specifying application wide mappings.
36
- #
37
- mapping do
38
- # collection :users do
39
- # entity User
40
- # repository UserRepository
41
- #
42
- # attribute :id, Integer
43
- # attribute :name, String
44
- # end
45
- end
46
- end.load!
47
-
48
- Hanami::Mailer.configure do
49
- root "#{ __dir__ }/<%= config[:project_name] %>/mailers"
50
-
51
- # See http://hanamirb.org/guides/mailers/delivery
52
- delivery do
53
- development :test
54
- test :test
55
- # production :smtp, address: ENV['SMTP_PORT'], port: 1025
56
- end
57
- end.load!
1
+ Hanami::Utils.require!("#{__dir__}/<%= config[:project_name] %>")
@@ -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,9 +2,8 @@
2
2
  ENV['HANAMI_ENV'] ||= 'test'
3
3
 
4
4
  require_relative '../config/environment'
5
- Hanami::Application.preload!
6
-
7
- Dir[__dir__ + '/support/**/*.rb'].each { |f| require f }
5
+ Hanami.boot
6
+ Hanami::Utils.require!("#{__dir__}/support")
8
7
 
9
8
  # This file was generated by the `rspec --init` command. Conventionally, all
10
9
  # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
@@ -10,12 +10,10 @@ module Hanami
10
10
  'postgresql' => { type: :sql, mri: 'pg', jruby: 'jdbc-postgres' },
11
11
  'postgres' => { type: :sql, mri: 'pg', jruby: 'jdbc-postgres' },
12
12
  'sqlite' => { type: :sql, mri: 'sqlite3', jruby: 'jdbc-sqlite3' },
13
- 'sqlite3' => { type: :sql, mri: 'sqlite3', jruby: 'jdbc-sqlite3' },
14
- 'filesystem' => { type: :file_system, mri: nil, jruby: nil },
15
- 'memory' => { type: :memory, mri: nil, jruby: nil }
13
+ 'sqlite3' => { type: :sql, mri: 'sqlite3', jruby: 'jdbc-sqlite3' }
16
14
  }.freeze
17
15
 
18
- DEFAULT_ENGINE = 'filesystem'.freeze
16
+ DEFAULT_ENGINE = 'sqlite'.freeze
19
17
 
20
18
  attr_reader :engine, :name
21
19
 
@@ -23,7 +21,10 @@ module Hanami
23
21
  @engine = engine
24
22
  @name = name
25
23
 
26
- SUPPORTED_ENGINES.key?(engine.to_s) or fail "\"#{ engine }\" is not a valid database type"
24
+ unless SUPPORTED_ENGINES.key?(engine.to_s) # rubocop:disable Style/GuardClause
25
+ warn %(`#{engine}' is not a valid database engine)
26
+ exit(1)
27
+ end
27
28
  end
28
29
 
29
30
  def to_hash
@@ -42,8 +43,8 @@ module Hanami
42
43
  type == :sql
43
44
  end
44
45
 
45
- def filesystem?
46
- type == :file_system
46
+ def sqlite?
47
+ ['sqlite', 'sqlite3'].include?(engine)
47
48
  end
48
49
 
49
50
  private
@@ -79,10 +80,6 @@ module Hanami
79
80
  "postgres://localhost/#{ name }"
80
81
  when 'sqlite', 'sqlite3'
81
82
  "sqlite://db/#{ Shellwords.escape(name) }"
82
- when 'memory'
83
- "memory://localhost/#{ name }"
84
- when 'filesystem'
85
- "file:///db/#{ Shellwords.escape(name) }"
86
83
  end
87
84
  end
88
85
 
@@ -1,3 +1,2 @@
1
- class <%= config[:model_name] %>
2
- include Hanami::Entity
1
+ class <%= config[:model_name] %> < Hanami::Entity
3
2
  end
@@ -1,3 +1,2 @@
1
- class <%= config[:model_name] %>Repository
2
- include Hanami::Repository
1
+ class <%= config[:model_name] %>Repository < Hanami::Repository
3
2
  end
@@ -4,7 +4,7 @@ module Hanami
4
4
  class UnsupportedTemplateEngine < ::StandardError
5
5
  end
6
6
 
7
- SUPPORTED_ENGINES = %w(erb slim haml).freeze
7
+ SUPPORTED_ENGINES = %w(erb haml slim).freeze
8
8
  DEFAULT_ENGINE = 'erb'.freeze
9
9
 
10
10
  attr_reader :name
@@ -17,11 +17,16 @@ module Hanami
17
17
  private
18
18
 
19
19
  def assert_engine!
20
- unless supported_engine?
21
- raise UnsupportedTemplateEngine, "\"#{ @name }\" is not a valid template engine"
20
+ if !supported_engine?
21
+ warn "`#{name}' is not a valid template engine. Please use one of: #{valid_template_engines.join(', ')}"
22
+ exit(1)
22
23
  end
23
24
  end
24
25
 
26
+ def valid_template_engines
27
+ SUPPORTED_ENGINES.map { |name| "`#{name}'"}
28
+ end
29
+
25
30
  def supported_engine?
26
31
  SUPPORTED_ENGINES.include?(@name.to_s)
27
32
  end
@@ -4,7 +4,7 @@ module Hanami
4
4
  class TestFramework
5
5
  RSPEC = 'rspec'.freeze
6
6
  MINITEST = 'minitest'.freeze
7
- VALID_FRAMEWORKS = [RSPEC, MINITEST].freeze
7
+ VALID_FRAMEWORKS = [MINITEST, RSPEC].freeze
8
8
 
9
9
  attr_reader :framework
10
10
 
@@ -25,12 +25,13 @@ module Hanami
25
25
 
26
26
  def assert_framework!
27
27
  if !supported_framework?
28
- raise ArgumentError.new("Unknown test framework '#{ framework}'. Please use one of #{ valid_test_frameworks.join(', ')}")
28
+ warn "`#{framework}' is not a valid test framework. Please use one of: #{valid_test_frameworks.join(', ')}"
29
+ exit(1)
29
30
  end
30
31
  end
31
32
 
32
33
  def valid_test_frameworks
33
- VALID_FRAMEWORKS.map { |name| "'#{ name }'"}
34
+ VALID_FRAMEWORKS.map { |name| "`#{name}'"}
34
35
  end
35
36
 
36
37
  def supported_framework?
@@ -1,3 +1,6 @@
1
+ require 'rack/builder'
2
+ require 'hanami/utils/class'
3
+
1
4
  module Hanami
2
5
  # Rack middleware stack for an application
3
6
  #
@@ -6,35 +9,32 @@ module Hanami
6
9
  class Middleware
7
10
  # Instantiate a middleware stack
8
11
  #
9
- # @param configuration [Hanami::Configuration] the application's configuration
12
+ # @param configuration [Hanami::ApplicationConfiguration] the application's configuration
10
13
  #
11
14
  # @return [Hanami::Middleware] the new stack
12
15
  #
13
16
  # @since 0.1.0
14
17
  # @api private
15
18
  #
16
- # @see Hanami::Configuration
19
+ # @see Hanami::ApplicationConfiguration
17
20
  def initialize(configuration)
18
- @stack = []
21
+ @stack = []
19
22
  @configuration = configuration
23
+ @builder = Rack::Builder.new
20
24
  end
21
25
 
22
26
  # Load the middleware stack
23
27
  #
24
- # @param application [Hanami::Application] the application loading the middleware
25
- #
26
28
  # @return [Hanami::Middleware] the loaded middleware stack
27
29
  #
28
30
  # @since 0.2.0
29
31
  # @api private
30
32
  #
31
33
  # @see http://rdoc.info/gems/rack/Rack/Builder
32
- def load!(application, namespace)
33
- @namespace = namespace
34
- @builder = ::Rack::Builder.new
35
- load_default_stack(application)
36
- @stack.each { |m, args, block| @builder.use load_middleware(m), *args, &block }
37
- @builder.run application.routes
34
+ def load!
35
+ load_default_stack
36
+ stack.each { |m, args, block| builder.use(load_middleware(m), *args, &block) }
37
+ builder.run routes
38
38
 
39
39
  self
40
40
  end
@@ -49,7 +49,7 @@ module Hanami
49
49
  # @since 0.1.0
50
50
  # @api private
51
51
  def call(env)
52
- @builder.call(env)
52
+ builder.call(env)
53
53
  end
54
54
 
55
55
  # Append a middleware to the stack.
@@ -64,7 +64,8 @@ module Hanami
64
64
  #
65
65
  # @see Hanami::Middleware#prepend
66
66
  def use(middleware, *args, &blk)
67
- @stack.push [middleware, args, blk]
67
+ stack.push [middleware, args, blk]
68
+ stack.uniq!
68
69
  end
69
70
 
70
71
  # Prepend a middleware to the stack.
@@ -79,27 +80,46 @@ module Hanami
79
80
  #
80
81
  # @see Hanami::Middleware#use
81
82
  def prepend(middleware, *args, &blk)
82
- @stack.unshift [middleware, args, blk]
83
+ stack.unshift [middleware, args, blk]
84
+ stack.uniq!
83
85
  end
84
86
 
87
+ private
88
+
89
+ # @api private
90
+ # @since 0.9.0
91
+ attr_reader :stack
92
+
93
+ # @api private
94
+ # @since 0.9.0
95
+ attr_reader :builder
96
+
97
+ # @api private
98
+ # @since 0.9.0
99
+ attr_reader :configuration
100
+
85
101
  # @api private
86
102
  # @since 0.2.0
87
103
  def load_middleware(middleware)
88
104
  case middleware
89
105
  when String
90
- @namespace.const_get(middleware)
106
+ Utils::Class.load!(middleware)
91
107
  else
92
108
  middleware
93
109
  end
94
110
  end
95
111
 
112
+ def routes
113
+ Components["#{configuration.app_name}.routes"]
114
+ end
115
+
96
116
  # @api private
97
117
  # @since 0.2.0
98
- def load_default_stack(application)
118
+ def load_default_stack
99
119
  @default_stack_loaded ||= begin
100
120
  _load_assets_middleware
101
121
  _load_session_middleware
102
- _load_default_welcome_page_for(application)
122
+ _load_default_welcome_page
103
123
  _load_method_override_middleware
104
124
 
105
125
  true
@@ -110,8 +130,8 @@ module Hanami
110
130
  #
111
131
  # @api private
112
132
  # @since 0.2.0
113
- def _load_default_welcome_page_for(application)
114
- unless Hanami.env?(:test) || application.routes.defined?
133
+ def _load_default_welcome_page
134
+ unless Hanami.env?(:test) || routes.defined?
115
135
  require 'hanami/welcome'
116
136
  use Hanami::Welcome
117
137
  end
@@ -122,8 +142,8 @@ module Hanami
122
142
  # @api private
123
143
  # @since 0.2.0
124
144
  def _load_session_middleware
125
- if @configuration.sessions.enabled?
126
- prepend(*@configuration.sessions.middleware)
145
+ if configuration.sessions.enabled?
146
+ prepend(*configuration.sessions.middleware)
127
147
  end
128
148
  end
129
149
 
@@ -16,17 +16,13 @@ module Hanami
16
16
 
17
17
  # @since 0.6.0
18
18
  # @api private
19
+ #
20
+ # rubocop:disable Metrics/AbcSize
21
+ # rubocop:disable Metrics/MethodLength
19
22
  def install
20
- desc "Preload project configuration"
21
- task :preload do
22
- require 'hanami/environment'
23
- Hanami::Environment.new
24
- end
25
-
26
23
  desc "Load the full project"
27
24
  task environment: :preload do
28
- require Hanami::Environment.new.env_config
29
- Hanami::Application.preload_applications!
25
+ Components.resolve('apps')
30
26
  end
31
27
 
32
28
  # Ruby ecosystem compatibility
@@ -64,5 +60,7 @@ module Hanami
64
60
  end
65
61
  end
66
62
  end
63
+ # rubocop:enable Metrics/MethodLength
64
+ # rubocop:enable Metrics/AbcSize
67
65
  end
68
66
  end
data/lib/hanami/server.rb CHANGED
@@ -13,32 +13,15 @@ module Hanami
13
13
  # @since 0.8.0
14
14
  # @api private
15
15
  class Server < ::Rack::Server
16
-
17
16
  attr_reader :options
18
17
 
19
- # @param options [Hash] Environment's options
20
- #
21
- # @since 0.8.0
22
- # @see Hanami::Environment#initialize
23
- def initialize(options)
24
- @_env = Hanami::Environment.new(options)
25
- @options = _extract_options
26
- end
27
-
28
-
29
18
  # @since 0.8.0
30
19
  # @api private
31
- def rackup_config
32
- @_env.rackup.to_s
33
- end
34
-
35
-
36
- # Adds Shotgun Loader
37
20
  #
38
- # @since 0.8.0
39
- # @api private
40
- def app=(shotgun_loader)
41
- @app = shotgun_loader
21
+ # @see Hanami::Environment#initialize
22
+ def initialize
23
+ @options = _extract_options
24
+ setup
42
25
  end
43
26
 
44
27
  # Primarily this removes the ::Rack::Chunked middleware
@@ -54,30 +37,57 @@ module Hanami
54
37
  mw
55
38
  end
56
39
 
40
+ def start
41
+ preload
42
+ super
43
+ end
44
+
57
45
  private
58
46
 
59
- # @since 0.8.0
60
- # @api private
61
- def shotgun_available?
62
- require 'shotgun'
63
- true
64
- rescue LoadError
65
- false
47
+ def setup
48
+ if code_reloading?
49
+ @app = Shotgun::Loader.new(rackup, &reloadable)
50
+ else
51
+ reloadable.call
52
+ end
53
+ end
54
+
55
+ def reloadable
56
+ ->(*) { Hanami::Components.resolve('model', 'finalizers') }
57
+ end
58
+
59
+ def environment
60
+ Components['environment']
66
61
  end
67
62
 
68
63
  # @since 0.8.0
69
64
  # @api private
70
65
  def code_reloading?
71
- @_env.code_reloading?
66
+ Components['code_reloading']
67
+ end
68
+
69
+ def rackup
70
+ environment.rackup.to_s
72
71
  end
73
72
 
73
+ def preload
74
+ if code_reloading?
75
+ Shotgun.enable_copy_on_write
76
+ Shotgun.preload
77
+ else
78
+ Hanami.boot
79
+ end
80
+ end
81
+
82
+ # Options for Rack::Server superclass
83
+ #
74
84
  # @since 0.8.0
75
85
  # @api private
76
86
  def _extract_options
77
- @_env.to_options.merge(
78
- config: @_env.rackup.to_s,
79
- Host: @_env.host,
80
- Port: @_env.port,
87
+ environment.to_options.merge(
88
+ config: rackup,
89
+ Host: environment.host,
90
+ Port: environment.port,
81
91
  AccessLog: []
82
92
  )
83
93
  end