hanami 1.0.0.beta2 → 1.0.0.beta3

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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -0
  3. data/FEATURES.md +2 -0
  4. data/LICENSE.md +1 -1
  5. data/README.md +1 -1
  6. data/hanami.gemspec +8 -8
  7. data/lib/hanami.rb +0 -5
  8. data/lib/hanami/action/csrf_protection.rb +35 -0
  9. data/lib/hanami/app.rb +1 -1
  10. data/lib/hanami/application.rb +2 -0
  11. data/lib/hanami/application_configuration.rb +1 -12
  12. data/lib/hanami/application_name.rb +8 -2
  13. data/lib/hanami/application_namespace.rb +2 -0
  14. data/lib/hanami/assets/asset.rb +1 -0
  15. data/lib/hanami/cli.rb +7 -0
  16. data/lib/hanami/cli_base.rb +3 -0
  17. data/lib/hanami/cli_sub_commands/assets.rb +2 -0
  18. data/lib/hanami/cli_sub_commands/db.rb +15 -2
  19. data/lib/hanami/cli_sub_commands/destroy.rb +6 -0
  20. data/lib/hanami/cli_sub_commands/generate.rb +7 -2
  21. data/lib/hanami/commands/assets/precompile.rb +4 -0
  22. data/lib/hanami/commands/command.rb +13 -0
  23. data/lib/hanami/commands/console.rb +6 -0
  24. data/lib/hanami/commands/db/apply.rb +3 -0
  25. data/lib/hanami/commands/db/console.rb +7 -0
  26. data/lib/hanami/commands/db/create.rb +3 -0
  27. data/lib/hanami/commands/db/drop.rb +3 -0
  28. data/lib/hanami/commands/db/migrate.rb +5 -0
  29. data/lib/hanami/commands/db/prepare.rb +3 -0
  30. data/lib/hanami/commands/db/version.rb +3 -0
  31. data/lib/hanami/commands/generate/abstract.rb +13 -1
  32. data/lib/hanami/commands/generate/action.rb +21 -0
  33. data/lib/hanami/commands/generate/app.rb +21 -0
  34. data/lib/hanami/commands/generate/mailer.rb +16 -3
  35. data/lib/hanami/commands/generate/migration.rb +13 -2
  36. data/lib/hanami/commands/generate/model.rb +14 -1
  37. data/lib/hanami/commands/generate/secret_token.rb +6 -0
  38. data/lib/hanami/commands/new/abstract.rb +39 -4
  39. data/lib/hanami/commands/new/app.rb +15 -0
  40. data/lib/hanami/commands/new/container.rb +14 -0
  41. data/lib/hanami/commands/routes.rb +2 -0
  42. data/lib/hanami/commands/server.rb +4 -0
  43. data/lib/hanami/components/app/assets.rb +4 -0
  44. data/lib/hanami/components/app/controller.rb +4 -0
  45. data/lib/hanami/components/app/routes.rb +6 -0
  46. data/lib/hanami/components/app/view.rb +4 -0
  47. data/lib/hanami/components/component.rb +2 -0
  48. data/lib/hanami/components/components.rb +12 -5
  49. data/lib/hanami/components/routes_inspector.rb +2 -0
  50. data/lib/hanami/config/cookies.rb +1 -0
  51. data/lib/hanami/config/framework_configuration.rb +1 -0
  52. data/lib/hanami/config/load_paths.rb +4 -0
  53. data/lib/hanami/config/mapper.rb +11 -0
  54. data/lib/hanami/config/routes.rb +4 -0
  55. data/lib/hanami/config/security.rb +2 -0
  56. data/lib/hanami/config/sessions.rb +6 -0
  57. data/lib/hanami/configuration.rb +102 -0
  58. data/lib/hanami/environment.rb +13 -0
  59. data/lib/hanami/environment_application_configurations.rb +7 -0
  60. data/lib/hanami/generators/app/application.rb.tt +31 -23
  61. data/lib/hanami/generators/app/favicon.ico +0 -0
  62. data/lib/hanami/generators/database_config.rb +19 -1
  63. data/lib/hanami/generators/generatable.rb +13 -0
  64. data/lib/hanami/generators/generator.rb +8 -0
  65. data/lib/hanami/generators/template_engine.rb +9 -0
  66. data/lib/hanami/generators/test_framework.rb +12 -0
  67. data/lib/hanami/hanamirc.rb +2 -0
  68. data/lib/hanami/mailer/glue.rb +1 -0
  69. data/lib/hanami/middleware.rb +24 -0
  70. data/lib/hanami/rendering_policy.rb +15 -0
  71. data/lib/hanami/routes.rb +14 -12
  72. data/lib/hanami/routing/default.rb +7 -0
  73. data/lib/hanami/server.rb +6 -0
  74. data/lib/hanami/version.rb +1 -1
  75. data/lib/hanami/views/default.rb +3 -0
  76. data/lib/hanami/views/default_template_finder.rb +2 -0
  77. data/lib/hanami/views/null_view.rb +2 -0
  78. data/lib/hanami/welcome.rb +7 -0
  79. metadata +18 -19
  80. data/lib/hanami/root.rb +0 -7
@@ -2,6 +2,8 @@ require 'ipaddr'
2
2
  require 'hanami/utils/string'
3
3
 
4
4
  module Hanami
5
+ # @since 0.2.0
6
+ # @api private
5
7
  module Config
6
8
  # Sessions configuration
7
9
  #
@@ -82,6 +84,8 @@ module Hanami
82
84
  end
83
85
  end
84
86
 
87
+ # @since 0.2.0
88
+ # @api private
85
89
  def domain
86
90
  domain = @configuration.host
87
91
  if !BLACKLISTED_DOMAINS.include?(domain) && !ip_address?(domain)
@@ -89,6 +93,8 @@ module Hanami
89
93
  end
90
94
  end
91
95
 
96
+ # @since 0.2.0
97
+ # @api private
92
98
  def ip_address?(string)
93
99
  !!IPAddr.new(string) rescue false
94
100
  end
@@ -5,25 +5,65 @@ require 'hanami/utils/class'
5
5
  require 'hanami/utils/string'
6
6
 
7
7
  module Hanami
8
+ # @api private
8
9
  class Configuration
10
+ # @api private
9
11
  class App < SimpleDelegator
12
+ # @api private
10
13
  attr_reader :path_prefix
11
14
 
15
+ # @api private
12
16
  def initialize(app, path_prefix)
13
17
  super(app)
14
18
  @path_prefix = path_prefix
15
19
  end
16
20
  end
17
21
 
22
+ # @api private
18
23
  def initialize(&blk)
19
24
  @settings = Concurrent::Map.new
20
25
  instance_eval(&blk)
21
26
  end
22
27
 
28
+ # Mount a Hanami::Application or a Rack app
29
+ #
30
+ # @param app [#call] an application compatible with Rack SPEC
31
+ # @param options [Hash] a set of options
32
+ # @option :at [String] options the mount point
33
+ #
34
+ # @since 0.9.0
35
+ #
36
+ # @example
37
+ # # config/environment.rb
38
+ # # ...
39
+ # Hanami.configure do
40
+ # mount Web::Application, at: '/'
41
+ #
42
+ # # ...
43
+ # end
23
44
  def mount(app, options)
24
45
  mounted[app] = App.new(app, options.fetch(:at))
25
46
  end
26
47
 
48
+ # Configure database
49
+ #
50
+ # @param blk [Proc] the database configuration
51
+ #
52
+ # @see Hanami::Model.configure
53
+ #
54
+ # @example
55
+ # # config/environment.rb
56
+ # # ...
57
+ # Hanami.configure do
58
+ # model do
59
+ # adapter :sql, ENV['DATABASE_URL']
60
+ #
61
+ # migrations 'db/migrations'
62
+ # schema 'db/schema.sql'
63
+ # end
64
+ #
65
+ # # ...
66
+ # end
27
67
  def model(&blk)
28
68
  if block_given?
29
69
  settings.put_if_absent(:model, blk)
@@ -32,20 +72,61 @@ module Hanami
32
72
  end
33
73
  end
34
74
 
75
+ # Configure mailer
76
+ #
77
+ # @param blk [Proc] the mailer configuration
78
+ #
79
+ # @see Hanami::Mailer.configure
80
+ #
81
+ # @example
82
+ # # config/environment.rb
83
+ # # ...
84
+ # Hanami.configure do
85
+ # mailer do
86
+ # root 'lib/bookshelf/mailers'
87
+ #
88
+ # # See http://hanamirb.org/guides/mailers/delivery
89
+ # delivery :test
90
+ # end
91
+ #
92
+ # # ...
93
+ # end
35
94
  def mailer(&blk)
36
95
  settings.put_if_absent(:mailer, blk)
37
96
  end
38
97
 
98
+ # @since 0.9.0
99
+ # @api private
39
100
  def mounted
40
101
  settings.fetch_or_store(:mounted, {})
41
102
  end
42
103
 
104
+ # @since 0.9.0
105
+ # @api private
43
106
  def apps
44
107
  mounted.each_pair do |klass, app|
45
108
  yield(app) if klass.ancestors.include?(Hanami::Application)
46
109
  end
47
110
  end
48
111
 
112
+ # Configure logger
113
+ #
114
+ # @since 1.0.0.beta1
115
+ #
116
+ # @param options [Hash] a set of options
117
+ #
118
+ # @see Hanami.logger
119
+ # @see Hanami::Logger
120
+ #
121
+ # @example
122
+ # # config/environment.rb
123
+ # # ...
124
+ # Hanami.configure do
125
+ # # ...
126
+ # environment :development do
127
+ # logger level: :debug
128
+ # end
129
+ # end
49
130
  def logger(options = nil)
50
131
  if options.nil?
51
132
  settings.fetch(:logger, nil)
@@ -54,12 +135,33 @@ module Hanami
54
135
  end
55
136
  end
56
137
 
138
+ # Configure settings for the current environment
139
+ # @since 1.0.0.beta1
140
+ #
141
+ # @param name [Symbol] the name of the Hanami environment
142
+ #
143
+ # @see Hanami.env
144
+ #
145
+ # @example Configure Logging for Different Environments
146
+ # # config/environment.rb
147
+ # # ...
148
+ # Hanami.configure do
149
+ # # ...
150
+ # environment :development do
151
+ # logger level: :debug
152
+ # end
153
+ #
154
+ # environment :production do
155
+ # logger level: :info, formatter: :json
156
+ # end
157
+ # end
57
158
  def environment(name)
58
159
  yield if ENV['HANAMI_ENV'] == name.to_s
59
160
  end
60
161
 
61
162
  private
62
163
 
164
+ # @api private
63
165
  attr_reader :settings
64
166
  end
65
167
  end
@@ -157,6 +157,8 @@ module Hanami
157
157
  # @see Hanami::Commands::Server
158
158
  # @see Hanami::Environment#config
159
159
  #
160
+ # @api private
161
+ #
160
162
  # @example Define ENV variables from .env
161
163
  #
162
164
  # # % tree .
@@ -219,6 +221,7 @@ module Hanami
219
221
  # @return [String] the current environment
220
222
  #
221
223
  # @since 0.1.0
224
+ # @api private
222
225
  #
223
226
  # @see Hanami::Environment::DEFAULT_ENV
224
227
  def environment
@@ -226,6 +229,7 @@ module Hanami
226
229
  end
227
230
 
228
231
  # @since 0.3.1
232
+ # @api private
229
233
  #
230
234
  # @see Hanami.env?(name)
231
235
  def environment?(*names)
@@ -262,6 +266,7 @@ module Hanami
262
266
  # @return [Pathname] application's root
263
267
  #
264
268
  # @since 0.2.0
269
+ # @api private
265
270
  def root
266
271
  @root ||= Pathname.new(Dir.pwd)
267
272
  end
@@ -282,6 +287,7 @@ module Hanami
282
287
  # @return [Pathname] the config directory
283
288
  #
284
289
  # @since 0.2.0
290
+ # @api private
285
291
  #
286
292
  # @see Hanami::Environment::DEFAULT_CONFIG
287
293
  # @see Hanami::Environment#root
@@ -304,6 +310,7 @@ module Hanami
304
310
  # @return [String] the HTTP host name
305
311
  #
306
312
  # @since 0.1.0
313
+ # @api private
307
314
  #
308
315
  # @see Hanami::Environment::DEFAULT_HOST
309
316
  # @see Hanami::Environment::LISTEN_ALL_HOST
@@ -325,6 +332,7 @@ module Hanami
325
332
  # @return [Integer] the default port
326
333
  #
327
334
  # @since 0.1.0
335
+ # @api private
328
336
  #
329
337
  # @see Hanami::Environment::DEFAULT_PORT
330
338
  def port
@@ -357,6 +365,7 @@ module Hanami
357
365
  # @return [Pathname] path to the Rack configuration file
358
366
  #
359
367
  # @since 0.2.0
368
+ # @api private
360
369
  def rackup
361
370
  root.join(@options.fetch(:rackup) { DEFAULT_RACKUP })
362
371
  end
@@ -376,6 +385,7 @@ module Hanami
376
385
  # @return [Pathname] path to applications
377
386
  #
378
387
  # @since 0.1.0
388
+ # @api private
379
389
  #
380
390
  # @see Hanami::Environment::DEFAULT_ENVIRONMENT_CONFIG
381
391
  def env_config
@@ -394,6 +404,7 @@ module Hanami
394
404
  require project_environment_configuration.to_s # if project_environment_configuration.exist?
395
405
  end
396
406
 
407
+ # @api private
397
408
  alias require_project_environment require_application_environment
398
409
 
399
410
  # Determine if activate code reloading for the current environment while
@@ -411,6 +422,7 @@ module Hanami
411
422
  # @return [TrueClass,FalseClass] the result of the check
412
423
  #
413
424
  # @since 0.2.0
425
+ # @api private
414
426
  #
415
427
  # @see Hanami::Commands::Server
416
428
  # @see Hanami::Environment::CODE_RELOADING
@@ -483,6 +495,7 @@ module Hanami
483
495
 
484
496
  private
485
497
 
498
+ # @api private
486
499
  attr_reader :env
487
500
 
488
501
  # @since 0.1.0
@@ -1,16 +1,21 @@
1
1
  module Hanami
2
+ # @api private
2
3
  class EnvironmentApplicationConfigurations
4
+ # @api private
3
5
  ALL = :all
4
6
 
7
+ # @api private
5
8
  def initialize
6
9
  @configurations = Concurrent::Hash.new { |k, v| k[v] = [] }
7
10
  end
8
11
 
12
+ # @api private
9
13
  def add(environment, &blk)
10
14
  env = (environment || ALL).to_sym
11
15
  configurations[env].push(blk)
12
16
  end
13
17
 
18
+ # @api private
14
19
  def each(environment, &blk)
15
20
  configurations.each do |env, blks|
16
21
  next unless matching_env?(environment, env)
@@ -20,8 +25,10 @@ module Hanami
20
25
 
21
26
  private
22
27
 
28
+ # @api private
23
29
  attr_reader :configurations
24
30
 
31
+ # @api private
25
32
  def matching_env?(environment, env)
26
33
  environment.to_sym == env ||
27
34
  env == ALL
@@ -13,7 +13,9 @@ module <%= config[:classified_app_name] %>
13
13
  #
14
14
  root __dir__
15
15
 
16
- # Relative load paths where this application will recursively load the code.
16
+ # Relative load paths where this application will recursively load the
17
+ # code.
18
+ #
17
19
  # When you add new directories, remember to add them here.
18
20
  #
19
21
  load_paths << [
@@ -47,8 +49,10 @@ module <%= config[:classified_app_name] %>
47
49
  # host 'example.org'
48
50
 
49
51
  # URI port used by the routing system to generate absolute URLs
50
- # Argument: An object coercible to integer, default to 80 if the scheme is http and 443 if it's https
51
- # This SHOULD be configured only in case the application listens to that non standard ports
52
+ # Argument: An object coercible to integer, defaults to 80 if the scheme
53
+ # is http and 443 if it's https
54
+ #
55
+ # This should only be configured if app listens to non-standard ports
52
56
  #
53
57
  # port 443
54
58
 
@@ -56,13 +60,16 @@ module <%= config[:classified_app_name] %>
56
60
  # Argument: boolean to toggle the feature
57
61
  # A Hash with options
58
62
  #
59
- # Options: :domain - The domain (String - nil by default, not required)
60
- # :path - Restrict cookies to a relative URI (String - nil by default)
61
- # :max_age - Cookies expiration expressed in seconds (Integer - nil by default)
62
- # :secure - Restrict cookies to secure connections
63
- # (Boolean - Automatically set on true if currently using a secure connection)
64
- # See #scheme and #ssl?
65
- # :httponly - Prevent JavaScript access (Boolean - true by default)
63
+ # Options:
64
+ # :domain - The domain (String - nil by default, not required)
65
+ # :path - Restrict cookies to a relative URI
66
+ # (String - nil by default)
67
+ # :max_age - Cookies expiration expressed in seconds
68
+ # (Integer - nil by default)
69
+ # :secure - Restrict cookies to secure connections
70
+ # (Boolean - Automatically true when using HTTPS)
71
+ # See #scheme and #ssl?
72
+ # :httponly - Prevent JavaScript access (Boolean - true by default)
66
73
  #
67
74
  # cookies true
68
75
  # or
@@ -81,24 +88,25 @@ module <%= config[:classified_app_name] %>
81
88
  # middleware.use Rack::Protection
82
89
 
83
90
  # Default format for the requests that don't specify an HTTP_ACCEPT header
84
- # Argument: A symbol representation of a mime type, default to :html
91
+ # Argument: A symbol representation of a mime type, defaults to :html
85
92
  #
86
93
  # default_request_format :html
87
94
 
88
- # Default format for responses that doesn't take into account the request format
89
- # Argument: A symbol representation of a mime type, default to :html
95
+ # Default format for responses that don't consider the request format
96
+ # Argument: A symbol representation of a mime type, defaults to :html
90
97
  #
91
98
  # default_response_format :html
92
99
 
93
100
  # HTTP Body parsers
94
101
  # Parse non GET responses body for a specific mime type
95
- # Argument: Symbol, which represent the format of the mime type (only `:json` is supported)
102
+ # Argument: Symbol, which represent the format of the mime type
103
+ # (only `:json` is supported)
96
104
  # Object, the parser
97
105
  #
98
106
  # body_parsers :json
99
107
 
100
108
  # When it's true and the router receives a non-encrypted request (http),
101
- # it redirects to the secure equivalent resource (https). Default disabled.
109
+ # it redirects to the secure equivalent (https). Disabled by default.
102
110
  #
103
111
  # force_ssl true
104
112
 
@@ -180,8 +188,8 @@ module <%= config[:classified_app_name] %>
180
188
  #
181
189
  security.x_content_type_options 'nosniff'
182
190
 
183
- # X-XSS-Protection is a HTTP header to determine the behavior of the browser
184
- # in case an XSS attack is detected.
191
+ # X-XSS-Protection is a HTTP header to determine the behavior of the
192
+ # browser in case an XSS attack is detected.
185
193
  #
186
194
  # Read more at:
187
195
  #
@@ -190,16 +198,16 @@ module <%= config[:classified_app_name] %>
190
198
  #
191
199
  security.x_xss_protection '1; mode=block'
192
200
 
193
- # Content-Security-Policy (CSP) is a HTTP header supported by modern browsers.
194
- # It determines trusted sources of execution for dynamic contents
195
- # (JavaScript) or other web related assets: stylesheets, images, fonts,
196
- # plugins, etc.
201
+ # Content-Security-Policy (CSP) is a HTTP header supported by modern
202
+ # browsers. It determines trusted sources of execution for dynamic
203
+ # contents (JavaScript) or other web related assets: stylesheets, images,
204
+ # fonts, plugins, etc.
197
205
  #
198
206
  # Web applications can send this header to mitigate Cross Site Scripting
199
207
  # (XSS) attacks.
200
208
  #
201
- # The default value allows images, scripts, AJAX, fonts and CSS from the same
202
- # origin, and does not allow any other resources to load (eg object,
209
+ # The default value allows images, scripts, AJAX, fonts and CSS from the
210
+ # same origin, and does not allow any other resources to load (eg object,
203
211
  # frame, media, etc).
204
212
  #
205
213
  # Inline JavaScript is NOT allowed. To enable it, please use:
Binary file
@@ -1,9 +1,12 @@
1
1
  require 'shellwords'
2
2
 
3
3
  module Hanami
4
+ # @api private
4
5
  module Generators
6
+ # @api private
5
7
  class DatabaseConfig
6
8
 
9
+ # @api private
7
10
  SUPPORTED_ENGINES = {
8
11
  'mysql' => { type: :sql, mri: 'mysql2', jruby: 'jdbc-mysql' },
9
12
  'mysql2' => { type: :sql, mri: 'mysql2', jruby: 'jdbc-mysql' },
@@ -13,10 +16,15 @@ module Hanami
13
16
  'sqlite3' => { type: :sql, mri: 'sqlite3', jruby: 'jdbc-sqlite3' }
14
17
  }.freeze
15
18
 
19
+ # @api private
16
20
  DEFAULT_ENGINE = 'sqlite'.freeze
17
21
 
18
- attr_reader :engine, :name
22
+ # @api private
23
+ attr_reader :engine
24
+ # @api private
25
+ attr_reader :name
19
26
 
27
+ # @api private
20
28
  def initialize(engine, name)
21
29
  @engine = engine
22
30
  @name = name
@@ -27,6 +35,7 @@ module Hanami
27
35
  end
28
36
  end
29
37
 
38
+ # @api private
30
39
  def to_hash
31
40
  {
32
41
  gem: gem,
@@ -35,28 +44,34 @@ module Hanami
35
44
  }
36
45
  end
37
46
 
47
+ # @api private
38
48
  def type
39
49
  SUPPORTED_ENGINES[engine][:type]
40
50
  end
41
51
 
52
+ # @api private
42
53
  def sql?
43
54
  type == :sql
44
55
  end
45
56
 
57
+ # @api private
46
58
  def sqlite?
47
59
  ['sqlite', 'sqlite3'].include?(engine)
48
60
  end
49
61
 
50
62
  private
51
63
 
64
+ # @api private
52
65
  def platform
53
66
  Hanami::Utils.jruby? ? :jruby : :mri
54
67
  end
55
68
 
69
+ # @api private
56
70
  def platform_prefix
57
71
  'jdbc:'.freeze if Hanami::Utils.jruby?
58
72
  end
59
73
 
74
+ # @api private
60
75
  def uri
61
76
  {
62
77
  development: environment_uri(:development),
@@ -64,10 +79,12 @@ module Hanami
64
79
  }
65
80
  end
66
81
 
82
+ # @api private
67
83
  def gem
68
84
  SUPPORTED_ENGINES[engine][platform]
69
85
  end
70
86
 
87
+ # @api private
71
88
  def base_uri
72
89
  case engine
73
90
  when 'mysql', 'mysql2'
@@ -83,6 +100,7 @@ module Hanami
83
100
  end
84
101
  end
85
102
 
103
+ # @api private
86
104
  def environment_uri(environment)
87
105
  case engine
88
106
  when 'sqlite', 'sqlite3'