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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e5372a7522c384925f3944349192e57986d50d80
4
- data.tar.gz: 04e0cce2379b2c6a715a4651bcb20fc95283f193
3
+ metadata.gz: 231fd3e7e51ec7e9c6ccd1e9d8f91ba32b76e075
4
+ data.tar.gz: c7b8808423c4e968156bee4592a1595f511767d7
5
5
  SHA512:
6
- metadata.gz: 873a49c091e733de1f09092484baacc97c618c3ffc6666d68890b4bed9df50d3245db8f4c9af505b14883355b3c30c19e33fdb3271bb505d1d7a0bccca4b9899
7
- data.tar.gz: 760ba2f3f321c42cecaf25ffd2c9b25c60ccbbf79d1a9a65063eeb19f2df40902eac3f99cd5d028fffc91959976e874c740e1027e421cab2a9cb1b2d1f24787f
6
+ metadata.gz: 05b89fb3ac8d80064d0fa272ccea7a6344692d316f165d5cec0b58d8761442e7ec83b2231620a8b863d4a868dc47eea69861b8eaccc2ecb8af5f0ffb3c068aeb
7
+ data.tar.gz: 0d25225c8892dfcbb1c16e3031099ee33bf1dba14710b74ca2709cc0888586d6cf3b319d30468c824ae84fdbd6cd07e808fb2c0732565c43f18ba87a1a773901
data/CHANGELOG.md CHANGED
@@ -1,6 +1,29 @@
1
1
  # Hanami
2
2
  The web, with simplicity.
3
3
 
4
+ ## v0.9.0 - 2016-11-15
5
+ ### Added
6
+ - [Christophe Philemotte] Introduced `hanami secret` to generate and print a new sessions secret
7
+
8
+ ### Fixed
9
+ - [Bruz Marzolf] Skip project code preloading when code reloading is enabled
10
+ - [Bruz Marzolf] Ensure to generate project in current directory when running `hanami new .`
11
+ - [Pascal Betz] Fix constant lookup within the project namespace
12
+ - [Sean Collins] Ensure consistent order of code loading across operating systems
13
+ - [Luca Guidi] Ensure to load the project configurations only once
14
+ - [Luca Guidi] Fix duplicated Rack middleware in single Hanami application stacks
15
+
16
+ ### Changed
17
+ - [Luca Guidi] Official support for Ruby MRI 2.3+
18
+ - [Luca Guidi] Removed support for "application" architecture
19
+ - [Luca Guidi] Removed `Hanami::Container.new` in favor of `Hanami.app`
20
+ - [Luca Guidi] Removed `Hanami::Container.configure` in favor of `Hanami.configure`
21
+ - [Luca Guidi] Configure model and mailer within `Hanami.configure` block in `config/environment.rb`
22
+ - [Luca Guidi] Removed `mapping` from model configuration
23
+ - [Luca Guidi] Removed `Hanami::Application.preload!` in favor of `Hanami.boot`
24
+ - [Luca Guidi] Removed experimental code support for `entr(1)`
25
+ - [Luca Guidi & Sean Collins] Renamed assets configuration `digest` into `fingerprint`
26
+
4
27
  ## v0.8.0 - 2016-07-22
5
28
  ### Added
6
29
  - [Luca Guidi] Generate new projects with Subresurce Integrity enabled in production (security).
data/FEATURES.md CHANGED
@@ -3,6 +3,19 @@
3
3
 
4
4
  ## Features
5
5
 
6
+ ## v0.9.0 - (unreleased)
7
+
8
+ - Experimental repositories associations (only "has many")
9
+ - Database automapping for SQL databases
10
+ - Entities schema
11
+ - Immutable entities
12
+ - Removed dirty tracking for entities
13
+ - Repositories CRUD operations can accept both entities and/or data
14
+ - Removed Memory and File System adapters
15
+ - SQLite is the default adapter for new projects
16
+ - Native support for PostgreSQL types
17
+ - CLI: `hanami secret` to generate and print a new session secret for a single Hanami app
18
+
6
19
  ## v0.8.0 - 2016-07-22
7
20
 
8
21
  - New validation syntax based on predicates
data/README.md CHANGED
@@ -50,7 +50,7 @@ You can give back to Open Source, by supporting Hanami development via a [donati
50
50
 
51
51
  ## Rubies
52
52
 
53
- __Hanami__ supports Ruby (MRI) 2+
53
+ __Hanami__ supports Ruby (MRI) 2.3+
54
54
 
55
55
  ## Installation
56
56
 
@@ -112,6 +112,33 @@ vim Gemfile # edit with: gem 'hanami', path: '..'
112
112
  bundle
113
113
  ```
114
114
 
115
+ ### Development Requirements
116
+
117
+ * Ruby 2.3+ / JRuby 9.1.5.0+
118
+ * Bundler
119
+ * Qt (MacOS)
120
+ * Node.js (MacOS)
121
+
122
+ ### Testing
123
+
124
+ In order to simulate installed gems on developers' computers, the build installs
125
+ all the gems locally in `vendor/cache`, including `hanami` code from `lib/`.
126
+
127
+ **Before to run a test please make sure to have a fresh version of the code:**
128
+
129
+ ```shell
130
+ % ./script/setup
131
+ % bundle exec rspec spec/path/to/file_spec.rb
132
+ ```
133
+
134
+ ### Build / CI
135
+
136
+ To run all the tests, please use:
137
+
138
+ ```shell
139
+ % ./script/ci
140
+ ```
141
+
115
142
  ## Versioning
116
143
 
117
144
  __Hanami__ uses [Semantic Versioning 2.0.0](http://semver.org)
data/hanami.gemspec CHANGED
@@ -8,30 +8,33 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Hanami::VERSION
9
9
  spec.authors = ['Luca Guidi', 'Trung Lê', 'Alfonso Uceda Pompa']
10
10
  spec.email = ['me@lucaguidi.com', 'trung.le@ruby-journal.com', 'uceda73@gmail.com']
11
- spec.summary = %q{The web, with simplicity.}
12
- spec.description = %q{Hanami is a web framework for Ruby}
11
+ spec.summary = 'The web, with simplicity'
12
+ spec.description = 'Hanami is a web framework for Ruby'
13
13
  spec.homepage = 'http://hanamirb.org'
14
14
  spec.license = 'MIT'
15
15
 
16
- spec.files = `git ls-files -z -- lib/* bin/* LICENSE.md README.md CHANGELOG.md FEATURES.md hanami.gemspec`.split("\x0")
16
+ spec.files = `git ls-files -c -o --exclude-standard -z -- lib/* bin/* LICENSE.md README.md CHANGELOG.md FEATURES.md hanami.gemspec`.split("\x0")
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test)/})
19
19
  spec.require_paths = ['lib']
20
- spec.required_ruby_version = '>= 2.2.0'
20
+ spec.required_ruby_version = '>= 2.3.0'
21
21
 
22
- spec.add_dependency 'hanami-utils', '~> 0.8'
23
- spec.add_dependency 'hanami-validations', '~> 0.6'
24
- spec.add_dependency 'hanami-router', '~> 0.7'
25
- spec.add_dependency 'hanami-controller', '~> 0.7'
26
- spec.add_dependency 'hanami-view', '~> 0.7'
27
- spec.add_dependency 'hanami-helpers', '~> 0.4'
28
- spec.add_dependency 'hanami-mailer', '~> 0.3'
29
- spec.add_dependency 'hanami-assets', '~> 0.3'
22
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
23
+
24
+ spec.add_dependency 'hanami-utils', '~> 0.9'
25
+ spec.add_dependency 'hanami-validations', '~> 0.7'
26
+ spec.add_dependency 'hanami-router', '~> 0.8'
27
+ spec.add_dependency 'hanami-controller', '~> 0.8'
28
+ spec.add_dependency 'hanami-view', '~> 0.8'
29
+ spec.add_dependency 'hanami-helpers', '~> 0.5'
30
+ spec.add_dependency 'hanami-mailer', '~> 0.4'
31
+ spec.add_dependency 'hanami-assets', '~> 0.4'
32
+ spec.add_dependency 'concurrent-ruby', '~> 1.0'
30
33
  spec.add_dependency 'thor', '~> 0.19'
31
- spec.add_dependency 'bundler', '~> 1.6'
34
+ spec.add_dependency 'bundler', '~> 1.13'
32
35
 
33
- spec.add_development_dependency 'minispec-metadata', '~> 3.2.1'
34
- spec.add_development_dependency 'minitest', '~> 5'
35
- spec.add_development_dependency 'rack-test', '~> 0.6'
36
- spec.add_development_dependency 'rake', '~> 10'
36
+ spec.add_development_dependency 'rspec', '~> 3.5'
37
+ spec.add_development_dependency 'rack-test', '~> 0.6'
38
+ spec.add_development_dependency 'aruba', '~> 0.14'
39
+ spec.add_development_dependency 'rake', '~> 11.3'
37
40
  end
data/lib/hanami.rb CHANGED
@@ -1,8 +1,4 @@
1
- require 'hanami/version'
2
- require 'hanami/application'
3
- require 'hanami/container'
4
- require 'hanami/environment'
5
- require 'hanami/server'
1
+ require 'thread'
6
2
 
7
3
  # A complete web framework for Ruby
8
4
  #
@@ -10,8 +6,100 @@ require 'hanami/server'
10
6
  #
11
7
  # @see http://hanamirb.org
12
8
  module Hanami
9
+ require 'hanami/version'
10
+ require 'hanami/frameworks'
11
+ require 'hanami/environment'
12
+ require 'hanami/app'
13
+ require 'hanami/application'
14
+ require 'hanami/components'
15
+ require 'hanami/configuration'
16
+
17
+ # @api private
18
+ # @since 0.6.0
13
19
  DEFAULT_PUBLIC_DIRECTORY = 'public'.freeze
14
20
 
21
+ # @api private
22
+ # @since 0.9.0
23
+ @_mutex = Mutex.new
24
+
25
+ # Configure Hanami project
26
+ #
27
+ # Please note that the code for this method is generated by `hanami new`.
28
+ #
29
+ # @param blk [Proc] the configuration block
30
+ #
31
+ # @since 0.9.0
32
+ #
33
+ # @example
34
+ # # config/environment.rb
35
+ #
36
+ # # ...
37
+ #
38
+ # Hanami.configure do
39
+ # mount Admin::Application, at: "/admin"
40
+ # mount Web::Application, at: "/"
41
+ #
42
+ # model do
43
+ # adapter :sql, ENV['DATABASE_URL']
44
+ #
45
+ # migrations "db/migrations"
46
+ # schema "db/schema.sql"
47
+ # end
48
+ #
49
+ # mailer do
50
+ # root "lib/bookshelf/mailers"
51
+ #
52
+ # delivery do
53
+ # development :test
54
+ # test :test
55
+ # # production :smtp, address: ENV['SMTP_HOST'], port: 1025
56
+ # end
57
+ # end
58
+ # end
59
+ def self.configure(&blk)
60
+ @_mutex.synchronize do
61
+ @_configuration = Hanami::Configuration.new(&blk)
62
+ end
63
+ end
64
+
65
+ # Hanami configuration
66
+ #
67
+ # @return [Hanami::Configuration] the configuration
68
+ #
69
+ # @see Hanami.configure
70
+ #
71
+ # @since 0.9.0
72
+ # @api private
73
+ def self.configuration
74
+ @_mutex.synchronize do
75
+ raise "Hanami not configured" unless defined?(@_configuration)
76
+ @_configuration
77
+ end
78
+ end
79
+
80
+ # Boot Hanami project
81
+ #
82
+ # @since 0.9.0
83
+ # @api private
84
+ def self.boot
85
+ Components.resolve('all')
86
+ end
87
+
88
+ # Main application that mounts many Rack and/or Hanami applications.
89
+ #
90
+ # This is used as integration point for:
91
+ #
92
+ # * `config.ru` (`run Hanami.app`)
93
+ # * Feature tests (`Capybara.app = Hanami.app`)
94
+ #
95
+ # @return [Hanami::App] the app
96
+ #
97
+ # @since 0.9.0
98
+ # @api private
99
+ def self.app
100
+ App.new(configuration, environment)
101
+ end
102
+
15
103
  # Return root of the project (top level directory).
16
104
  #
17
105
  # @return [Pathname] root path
@@ -24,6 +112,15 @@ module Hanami
24
112
  environment.root
25
113
  end
26
114
 
115
+ # Project public directory
116
+ #
117
+ # @return [Pathname] public directory
118
+ #
119
+ # @since 0.6.0
120
+ # @api private
121
+ #
122
+ # @example
123
+ # Hanami.public_directory # => #<Pathname:/Users/luca/Code/bookshelf/public>
27
124
  def self.public_directory
28
125
  root.join(DEFAULT_PUBLIC_DIRECTORY)
29
126
  end
@@ -70,13 +167,15 @@ module Hanami
70
167
  environment.environment?(*names)
71
168
  end
72
169
 
73
- # Return environment
170
+ # Current environment
74
171
  #
75
172
  # @return [Hanami::Environment] environment
76
173
  #
77
174
  # @api private
78
175
  # @since 0.3.2
79
176
  def self.environment
80
- Environment.new
177
+ Components.resolved('environment') do
178
+ Environment.new
179
+ end
81
180
  end
82
181
  end
@@ -25,13 +25,13 @@ module Hanami
25
25
  # end
26
26
  module RoutingHelpers
27
27
  def self.included(base)
28
- factory = "#{ Utils::String.new(base).namespace }::Routes"
28
+ factory = "#{Utils::String.new(base).namespace}.routes"
29
29
 
30
30
  base.class_eval <<-END_EVAL, __FILE__, __LINE__
31
31
  private
32
32
 
33
33
  def routes
34
- #{ factory }
34
+ #{factory}
35
35
  end
36
36
  END_EVAL
37
37
  end
data/lib/hanami/app.rb ADDED
@@ -0,0 +1,72 @@
1
+ require 'rack'
2
+ require 'rack/builder'
3
+ require 'hanami/router'
4
+ require 'hanami/components'
5
+
6
+ module Hanami
7
+ # Main application that mounts many Rack and/or Hanami applications.
8
+ #
9
+ # @see Hanami.app
10
+ #
11
+ # @since 0.9.0
12
+ # @api private
13
+ class App
14
+ # Initialize a new instance
15
+ #
16
+ # @param configuration [Hanami::Configuration] general configuration
17
+ # @param environment [Hanami::Environment] current environment
18
+ #
19
+ # @since 0.9.0
20
+ # @api private
21
+ def initialize(configuration, environment)
22
+ Components.resolve('apps')
23
+
24
+ @builder = Rack::Builder.new
25
+ @routes = Hanami::Router.new
26
+
27
+ mount(configuration)
28
+ middleware(environment)
29
+ builder.run(routes)
30
+ end
31
+
32
+ # Implements Rack SPEC
33
+ #
34
+ # @param env [Hash] a Rack env
35
+ #
36
+ # @return [Array] a serialized Rack response
37
+ #
38
+ # @since 0.9.0
39
+ # @api private
40
+ def call(env)
41
+ builder.call(env)
42
+ end
43
+
44
+ private
45
+
46
+ # @since 0.9.0
47
+ # @api private
48
+ attr_reader :builder
49
+
50
+ # @since 0.9.0
51
+ # @api private
52
+ attr_reader :routes
53
+
54
+ # @since 0.9.0
55
+ # @api private
56
+ def mount(configuration)
57
+ configuration.mounted.each do |klass, app|
58
+ routes.mount(klass, at: app.path_prefix)
59
+ end
60
+ end
61
+
62
+ # @since 0.9.0
63
+ # @api private
64
+ def middleware(environment)
65
+ if middleware = environment.static_assets_middleware # rubocop:disable Lint/AssignmentInCondition
66
+ builder.use middleware
67
+ end
68
+
69
+ builder.use Rack::MethodOverride
70
+ end
71
+ end
72
+ end
@@ -1,10 +1,10 @@
1
- require 'hanami/utils/class_attribute'
2
- require 'hanami/frameworks'
3
- require 'hanami/configuration'
4
- require 'hanami/loader'
5
- require 'hanami/logger'
1
+ require 'thread'
2
+ require 'concurrent'
3
+ require 'hanami/application_name'
4
+ require 'hanami/application_namespace'
5
+ require 'hanami/application_configuration'
6
+ require 'hanami/environment_application_configurations'
6
7
  require 'hanami/rendering_policy'
7
- require 'hanami/middleware'
8
8
 
9
9
  module Hanami
10
10
  # A full stack Hanami application
@@ -28,116 +28,105 @@ module Hanami
28
28
  def self.inherited(base)
29
29
  super
30
30
 
31
- base.class_eval do
32
- include Hanami::Utils::ClassAttribute
33
-
34
- class_attribute :configuration
35
- self.configuration = Configuration.new
36
- end
37
-
38
- synchronize do
39
- applications.add(base)
31
+ base.extend(ClassMethods)
32
+ base.namespace.module_eval do
33
+ class << self
34
+ # Logger for this application
35
+ #
36
+ # @return [Hanami::Logger] the logger for this Hanami application
37
+ #
38
+ # @since 0.9.0
39
+ # @api public
40
+ #
41
+ # @example
42
+ #
43
+ # Web.logger
44
+ # Admin.logger
45
+ attr_accessor :logger
46
+
47
+ # Routes for this application
48
+ #
49
+ # @return [Hanami::Routes] the routes for this Hanami application
50
+ #
51
+ # @since 0.9.0
52
+ # @api public
53
+ #
54
+ # @example
55
+ #
56
+ # Web.routes
57
+ # Admin.routes
58
+ attr_accessor :routes
59
+ end
40
60
  end
41
61
  end
42
62
 
43
- # @since 0.8.0
44
- # @api private
45
- LOCK = Mutex.new
46
-
47
- # Return the routes for this application
63
+ # Class interface for Hanami applications
48
64
  #
49
- # @return [Hanami::Router] a route set
50
- #
51
- # @since 0.1.0
52
- #
53
- # @see Hanami::Configuration#routes
54
- attr_reader :routes
65
+ # @since 0.9.0
66
+ module ClassMethods
67
+ # Override Ruby's Class#extended
68
+ #
69
+ # @since 0.9.0
70
+ # @api private
71
+ #
72
+ # @see http://www.ruby-doc.org/core/Class.html#method-i-extended
73
+ def self.extended(base) # rubocop:disable Metrics/MethodLength
74
+ super
55
75
 
56
- # Set the routes for this application
57
- #
58
- @param [Hanami::Router]
59
- #
60
- # @since 0.1.0
61
- # @api private
62
- attr_writer :routes
76
+ base.class_eval do
77
+ @namespace = ApplicationNamespace.resolve(name)
78
+ @configurations = EnvironmentApplicationConfigurations.new
79
+ @_lock = Mutex.new
63
80
 
64
- # Rendering policy
65
- #
66
- # @param [Hanami::RenderingPolicy]
67
- #
68
- # @since 0.2.0
69
- # @api private
70
- attr_accessor :renderer
81
+ class << self
82
+ # @since 0.9.0
83
+ # @api private
84
+ attr_reader :namespace
71
85
 
72
- # Initialize and load a new instance of the application
73
- #
74
- # @return [Hanami::Application] a new instance of the application
75
- #
76
- # @since 0.1.0
77
- def initialize(options = {})
78
- self.class.configuration.path_prefix options[:path_prefix]
79
- self.class.load!(self)
80
- end
81
-
82
- # Return the configuration for this application
83
- #
84
- # @since 0.1.0
85
- # @api private
86
- #
87
- # @see Hanami::Application.configuration
88
- def configuration
89
- self.class.configuration
90
- end
86
+ # @since 0.9.0
87
+ # @api private
88
+ attr_reader :configurations
91
89
 
92
- # Return the application name
93
- #
94
- # @since 0.2.0
95
- # @api private
96
- def name
97
- self.class.name
98
- end
99
-
100
- # Process a request.
101
- # This method makes Hanami applications compatible with the Rack protocol.
102
- #
103
- # @param env [Hash] a Rack env
104
- #
105
- # @return [Array] a serialized Rack response
106
- #
107
- # @since 0.1.0
108
- #
109
- # @see http://rack.github.io
110
- # @see Hanami::RenderingPolicy#render
111
- # @see Hanami::Application#middleware
112
- def call(env)
113
- renderer.render(env, middleware.call(env))
114
- end
115
-
116
- # Rack middleware stack
117
- #
118
- # @return [Hanami::Middleware] the middleware stack
119
- #
120
- # @since 0.1.0
121
- # @api private
122
- #
123
- # @see Hanami::Middleware
124
- def middleware
125
- @middleware ||= configuration.middleware
126
- end
90
+ # @since 0.9.0
91
+ # @api private
92
+ attr_reader :configuration
93
+ end
94
+ end
95
+ end
127
96
 
128
- class << self
129
- # @since 0.2.0
97
+ # Hanami application name
98
+ #
99
+ # @return [String] the Hanami application name
100
+ #
101
+ # @since 0.9.0
130
102
  # @api private
131
- @@applications = Set.new
103
+ #
104
+ # @example
105
+ # require 'hanami'
106
+ #
107
+ # module Web
108
+ # class Application < Hanami::Application
109
+ # end
110
+ # end
111
+ #
112
+ # Web::Application.app_name # => "web"
113
+ def app_name
114
+ ApplicationName.new(name).to_s
115
+ end
132
116
 
133
- # Registry of Hanami applications in the current Ruby process
117
+ # Set configuration
118
+ #
119
+ # @param configuration [Hanami::ApplicationConfiguration] the application configuration
134
120
  #
135
- # @return [Set] a set of all the registered applications
121
+ # @raise [RuntimeError] if the configuration is assigned more than once
136
122
  #
137
- # @since 0.2.0
123
+ # @since 0.1.0
138
124
  # @api private
139
- def applications
140
- @@applications
125
+ def configuration=(configuration)
126
+ @_lock.synchronize do
127
+ raise "Can't assign configuration more than once (#{app_name})" unless @configuration.nil?
128
+ @configuration = configuration
129
+ end
141
130
  end
142
131
 
143
132
  # Configure the application.
@@ -148,7 +137,7 @@ module Hanami
148
137
  #
149
138
  # @since 0.1.0
150
139
  #
151
- # @see Hanami::Configuration
140
+ # @see Hanami::ApplicationConfiguration
152
141
  #
153
142
  # @example
154
143
  # require 'hanami'
@@ -161,92 +150,64 @@ module Hanami
161
150
  # end
162
151
  # end
163
152
  def configure(environment = nil, &blk)
164
- configuration.configure(environment, &blk)
165
- end
166
-
167
- # Eager load the application configuration, by activating the framework
168
- # duplication mechanisms.
169
- #
170
- # @param application [Hanami::Application, Class<Hanami::Application>]
171
- # @return void
172
- #
173
- # @since 0.1.1
174
- #
175
- # @example
176
- # require 'hanami'
177
- #
178
- # module OneFile
179
- # class Application < Hanami::Application
180
- # configure do
181
- # routes do
182
- # get '/', to: 'dashboard#index'
183
- # end
184
- # end
185
- #
186
- # load!
187
- # end
188
- #
189
- # module Controllers::Dashboard
190
- # class Index
191
- # include OneFile::Action
192
- #
193
- # def call(params)
194
- # self.body = 'Hello!'
195
- # end
196
- # end
197
- # end
198
- # end
199
- def load!(application = self)
200
- Hanami::Loader.new(application).load!
153
+ configurations.add(environment, &blk)
201
154
  end
155
+ end
202
156
 
203
- # Preload all the registered applications, by yielding their configurations
204
- # and preparing the frameworks.
205
- #
206
- # This is useful for testing suites, where we want to make Hanami frameworks
207
- # ready, but not preload applications code.
208
- #
209
- # This allows to test components such as views or actions in isolation and
210
- # to have faster boot times.
211
- #
212
- # @return [void]
213
- #
214
- # @since 0.2.0
215
- def preload!
216
- synchronize do
217
- applications.each(&:load!)
218
- end
157
+ # Initialize and load a new instance of the application
158
+ #
159
+ # @return [Hanami::Application] a new instance of the application
160
+ #
161
+ # @since 0.1.0
162
+ def initialize
163
+ @renderer = RenderingPolicy.new(configuration)
164
+ @middleware = configuration.middleware
165
+ end
219
166
 
220
- nil
221
- end
167
+ # Process a request.
168
+ # This method makes Hanami applications compatible with the Rack protocol.
169
+ #
170
+ # @param env [Hash] a Rack env
171
+ #
172
+ # @return [Array] a serialized Rack response
173
+ #
174
+ # @since 0.1.0
175
+ #
176
+ # @see http://rack.github.io
177
+ # @see Hanami::RenderingPolicy#render
178
+ # @see Hanami::Application#middleware
179
+ def call(env)
180
+ renderer.render(env, middleware.call(env))
181
+ end
222
182
 
223
- # Full preload for all the registered applications.
224
- #
225
- # This is useful in console where we want all the application code available.
226
- #
227
- # @return [void]
228
- #
229
- # @since 0.2.1
230
- # @api private
231
- def preload_applications!
232
- synchronize do
233
- applications.each { |app| app.new }
234
- end
183
+ private
235
184
 
236
- nil
237
- end
185
+ # Return the configuration for this application
186
+ #
187
+ # @since 0.1.0
188
+ # @api private
189
+ #
190
+ # @see Hanami::Application.configuration
191
+ def configuration
192
+ self.class.configuration
193
+ end
238
194
 
239
- private
195
+ # Rendering policy
196
+ #
197
+ # @since 0.2.0
198
+ # @api private
199
+ #
200
+ # @see Hanami::RenderingPolicy
201
+ attr_reader :renderer
240
202
 
241
- # Yields the given block in a critical section
242
- #
243
- # @since 0.2.0
244
- # @api private
245
- def synchronize
246
- LOCK.synchronize do
247
- yield
248
- end
249
- end
250
- end
203
+ # Rack middleware stack
204
+ #
205
+ # @return [Hanami::Middleware] the middleware stack
206
+ #
207
+ # @since 0.1.0
208
+ # @api private
209
+ #
210
+ # @see Hanami::Middleware
211
+ attr_reader :middleware
251
212
  end
252
213
  end