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
@@ -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