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
@@ -1,52 +1,65 @@
1
1
  require 'hanami/generators/generator'
2
2
 
3
3
  module Hanami
4
+ # @api private
4
5
  module Generators
6
+ # @api private
5
7
  module Generatable
6
8
 
9
+ # @api private
7
10
  def start
8
11
  map_templates
9
12
  process_templates
10
13
  end
11
14
 
15
+ # @api private
12
16
  def destroy
13
17
  generator.behavior = :revoke
14
18
  self
15
19
  end
16
20
 
21
+ # @api private
17
22
  def generator
18
23
  @generator ||= Hanami::Generators::Generator.new(template_source_path, target_path)
19
24
  end
20
25
 
26
+ # @api private
21
27
  def map_templates
22
28
  raise NotImplementedError, "must implement the map_templates method"
23
29
  end
24
30
 
31
+ # @api private
25
32
  def add_mapping(source, target)
26
33
  generator.add_mapping(source, target)
27
34
  end
28
35
 
36
+ # @api private
29
37
  def process_templates
30
38
  generator.process_templates(template_options)
31
39
  post_process_templates
32
40
  end
33
41
 
42
+ # @api private
34
43
  def post_process_templates
35
44
  nil
36
45
  end
37
46
 
47
+ # @api private
38
48
  def template_options
39
49
  {}
40
50
  end
41
51
 
52
+ # @api private
42
53
  def template_source_path
43
54
  raise NotImplementedError, "must implement the template_source_path method"
44
55
  end
45
56
 
57
+ # @api private
46
58
  def target_path
47
59
  raise NotImplementedError, "must implement the target_path method"
48
60
  end
49
61
 
62
+ # @api private
50
63
  def argument_blank?(value)
51
64
  Hanami::Utils::Blank.blank?(value)
52
65
  end
@@ -2,17 +2,22 @@ require 'thor'
2
2
  require 'forwardable'
3
3
 
4
4
  module Hanami
5
+ # @api private
5
6
  module Generators
7
+ # @api private
6
8
  class Generator
7
9
 
8
10
  extend Forwardable
9
11
 
12
+ # @api private
10
13
  def_delegators :@processor, :run, :behavior=, :inject_into_file, :append_to_file, :prepend_to_file, :gsub_file
11
14
 
15
+ # @api private
12
16
  class Processor < Thor
13
17
  include Thor::Actions
14
18
  end
15
19
 
20
+ # @api private
16
21
  def initialize(template_source_path, target_path)
17
22
  @template_source_path = template_source_path
18
23
  @target_path = target_path
@@ -21,10 +26,12 @@ module Hanami
21
26
  @processor.class.source_root(@template_source_path)
22
27
  end
23
28
 
29
+ # @api private
24
30
  def add_mapping(source, target)
25
31
  @template_mappings << [source, target]
26
32
  end
27
33
 
34
+ # @api private
28
35
  def process_templates(options = {})
29
36
  @template_mappings.each do |src, dst|
30
37
  @processor.template(@template_source_path.join(src), @target_path.join(dst), options)
@@ -32,6 +39,7 @@ module Hanami
32
39
  end
33
40
 
34
41
  # Modelled after Thor's `inject_into_class`
42
+ # @api private
35
43
  def prepend_after_leading_comments(path, *args, &block)
36
44
  config = args.last.is_a?(Hash) ? args.pop : {}
37
45
  # Either prepend after the last comment line,
@@ -1,14 +1,20 @@
1
1
  module Hanami
2
+ # @api private
2
3
  module Generators
4
+ # @api private
3
5
  class TemplateEngine
4
6
  class UnsupportedTemplateEngine < ::StandardError
5
7
  end
6
8
 
9
+ # @api private
7
10
  SUPPORTED_ENGINES = %w(erb haml slim).freeze
11
+ # @api private
8
12
  DEFAULT_ENGINE = 'erb'.freeze
9
13
 
14
+ # @api private
10
15
  attr_reader :name
11
16
 
17
+ # @api private
12
18
  def initialize(hanamirc, engine)
13
19
  @name = (engine || hanamirc.options.fetch(:template))
14
20
  assert_engine!
@@ -16,6 +22,7 @@ module Hanami
16
22
 
17
23
  private
18
24
 
25
+ # @api private
19
26
  def assert_engine!
20
27
  if !supported_engine?
21
28
  warn "`#{name}' is not a valid template engine. Please use one of: #{valid_template_engines.join(', ')}"
@@ -23,10 +30,12 @@ module Hanami
23
30
  end
24
31
  end
25
32
 
33
+ # @api private
26
34
  def valid_template_engines
27
35
  SUPPORTED_ENGINES.map { |name| "`#{name}'"}
28
36
  end
29
37
 
38
+ # @api private
30
39
  def supported_engine?
31
40
  SUPPORTED_ENGINES.include?(@name.to_s)
32
41
  end
@@ -1,28 +1,38 @@
1
1
  require 'hanami/hanamirc'
2
2
  module Hanami
3
+ # @api private
3
4
  module Generators
5
+ # @api private
4
6
  class TestFramework
7
+ # @api private
5
8
  RSPEC = 'rspec'.freeze
9
+ # @api private
6
10
  MINITEST = 'minitest'.freeze
11
+ # @api private
7
12
  VALID_FRAMEWORKS = [MINITEST, RSPEC].freeze
8
13
 
14
+ # @api private
9
15
  attr_reader :framework
10
16
 
17
+ # @api private
11
18
  def initialize(hanamirc, framework)
12
19
  @framework = (framework || hanamirc.options.fetch(:test))
13
20
  assert_framework!
14
21
  end
15
22
 
23
+ # @api private
16
24
  def rspec?
17
25
  framework == RSPEC
18
26
  end
19
27
 
28
+ # @api private
20
29
  def minitest?
21
30
  framework == MINITEST
22
31
  end
23
32
 
24
33
  private
25
34
 
35
+ # @api private
26
36
  def assert_framework!
27
37
  if !supported_framework?
28
38
  warn "`#{framework}' is not a valid test framework. Please use one of: #{valid_test_frameworks.join(', ')}"
@@ -30,10 +40,12 @@ module Hanami
30
40
  end
31
41
  end
32
42
 
43
+ # @api private
33
44
  def valid_test_frameworks
34
45
  VALID_FRAMEWORKS.map { |name| "`#{name}'"}
35
46
  end
36
47
 
48
+ # @api private
37
49
  def supported_framework?
38
50
  VALID_FRAMEWORKS.include?(framework)
39
51
  end
@@ -135,10 +135,12 @@ module Hanami
135
135
 
136
136
  private
137
137
 
138
+ # @api private
138
139
  def symbolize(hash)
139
140
  Utils::Hash.new(hash).symbolize!
140
141
  end
141
142
 
143
+ # @api private
142
144
  def file_options
143
145
  symbolize(exists? ? parse_file(path_file) : {})
144
146
  end
@@ -1,3 +1,4 @@
1
+ # @api private
1
2
  module Hanami::Mailer
2
3
  # @since 0.5.0
3
4
  # @api private
@@ -63,6 +63,17 @@ module Hanami
63
63
  # @since 0.2.0
64
64
  #
65
65
  # @see Hanami::Middleware#prepend
66
+ #
67
+ # @example
68
+ # # apps/web/application.rb
69
+ # module Web
70
+ # class Application < Hanami::Application
71
+ # configure do
72
+ # # ...
73
+ # use MyRackMiddleware, foo: 'bar'
74
+ # end
75
+ # end
76
+ # end
66
77
  def use(middleware, *args, &blk)
67
78
  stack.push [middleware, args, blk]
68
79
  stack.uniq!
@@ -79,6 +90,17 @@ module Hanami
79
90
  # @since 0.6.0
80
91
  #
81
92
  # @see Hanami::Middleware#use
93
+ #
94
+ # @example
95
+ # # apps/web/application.rb
96
+ # module Web
97
+ # class Application < Hanami::Application
98
+ # configure do
99
+ # # ...
100
+ # prepend MyRackMiddleware, foo: 'bar'
101
+ # end
102
+ # end
103
+ # end
82
104
  def prepend(middleware, *args, &blk)
83
105
  stack.unshift [middleware, args, blk]
84
106
  stack.uniq!
@@ -109,6 +131,8 @@ module Hanami
109
131
  end
110
132
  end
111
133
 
134
+ # @api private
135
+ # @since 0.9.0
112
136
  def routes
113
137
  Components["#{configuration.app_name}.routes"]
114
138
  end
@@ -8,16 +8,24 @@ module Hanami
8
8
  # @since 0.1.0
9
9
  # @api private
10
10
  class RenderingPolicy
11
+ # @api private
11
12
  STATUS = 0
13
+ # @api private
12
14
  HEADERS = 1
15
+ # @api private
13
16
  BODY = 2
14
17
 
18
+ # @api private
15
19
  HANAMI_ACTION = 'hanami.action'.freeze
20
+ # @api private
16
21
  RACK_EXCEPTION = 'rack.exception'.freeze
17
22
 
23
+ # @api private
18
24
  SUCCESSFUL_STATUSES = (200..201).freeze
25
+ # @api private
19
26
  RENDERABLE_FORMATS = [:all, :html].freeze
20
27
 
28
+ # @api private
21
29
  def initialize(configuration)
22
30
  @controller_pattern = %r{#{ configuration.controller_pattern.gsub(/\%\{(controller|action)\}/) { "(?<#{ $1 }>(.*))" } }}
23
31
  @view_pattern = configuration.view_pattern
@@ -25,6 +33,7 @@ module Hanami
25
33
  @templates = configuration.templates
26
34
  end
27
35
 
36
+ # @api private
28
37
  def render(env, response)
29
38
  body = _render(env, response)
30
39
 
@@ -33,6 +42,7 @@ module Hanami
33
42
  end
34
43
 
35
44
  private
45
+ # @api private
36
46
  def _render(env, response)
37
47
  if action = renderable?(env)
38
48
  _render_action(action, env, response) ||
@@ -40,6 +50,7 @@ module Hanami
40
50
  end
41
51
  end
42
52
 
53
+ # @api private
43
54
  def _render_action(action, env, response)
44
55
  begin
45
56
  view_for(action, response).render(
@@ -51,20 +62,24 @@ module Hanami
51
62
  end
52
63
  end
53
64
 
65
+ # @api private
54
66
  def _render_status_page(action, response)
55
67
  if render_status_page?(action, response)
56
68
  Hanami::Views::Default.render(@templates, response[STATUS], response: response, format: :html)
57
69
  end
58
70
  end
59
71
 
72
+ # @api private
60
73
  def renderable?(env)
61
74
  ((action = env.delete(HANAMI_ACTION)) && action.renderable?) and action
62
75
  end
63
76
 
77
+ # @api private
64
78
  def render_status_page?(action, response)
65
79
  RENDERABLE_FORMATS.include?(action.format) && !SUCCESSFUL_STATUSES.include?(response[STATUS])
66
80
  end
67
81
 
82
+ # @api private
68
83
  def view_for(action, response)
69
84
  view = if response[BODY].respond_to?(:empty?) && response[BODY].empty?
70
85
  captures = @controller_pattern.match(action.class.name)
data/lib/hanami/routes.rb CHANGED
@@ -7,6 +7,7 @@ module Hanami
7
7
  # to the `Routes` constant, under the application namespace.
8
8
  #
9
9
  # @since 0.1.0
10
+ # @api private
10
11
  class Routes
11
12
  # Initialize the factory
12
13
  #
@@ -15,6 +16,7 @@ module Hanami
15
16
  # @return [Hanami::Routes] the factory
16
17
  #
17
18
  # @since 0.1.0
19
+ # @api private
18
20
  def initialize(routes)
19
21
  @routes = routes
20
22
  end
@@ -36,7 +38,7 @@ module Hanami
36
38
  # @example Basic example
37
39
  # require 'hanami'
38
40
  #
39
- # module Bookshelf
41
+ # module Web
40
42
  # class Application < Hanami::Application
41
43
  # configure do
42
44
  # routes do
@@ -46,16 +48,16 @@ module Hanami
46
48
  # end
47
49
  # end
48
50
  #
49
- # Bookshelf::Routes.path(:login)
51
+ # Web.routes.path(:login)
50
52
  # # => '/login'
51
53
  #
52
- # Bookshelf::Routes.path(:login, return_to: '/dashboard')
54
+ # Web.routes.path(:login, return_to: '/dashboard')
53
55
  # # => '/login?return_to=%2Fdashboard'
54
56
  #
55
57
  # @example Dynamic finders
56
58
  # require 'hanami'
57
59
  #
58
- # module Bookshelf
60
+ # module Web
59
61
  # class Application < Hanami::Application
60
62
  # configure do
61
63
  # routes do
@@ -65,10 +67,10 @@ module Hanami
65
67
  # end
66
68
  # end
67
69
  #
68
- # Bookshelf::Routes.login_path
70
+ # Web.routes.login_path
69
71
  # # => '/login'
70
72
  #
71
- # Bookshelf::Routes.login_path(return_to: '/dashboard')
73
+ # Web.routes.login_path(return_to: '/dashboard')
72
74
  # # => '/login?return_to=%2Fdashboard'
73
75
  def path(name, *args)
74
76
  Utils::Escape::SafeString.new(@routes.path(name, *args))
@@ -91,7 +93,7 @@ module Hanami
91
93
  # @example Basic example
92
94
  # require 'hanami'
93
95
  #
94
- # module Bookshelf
96
+ # module Web
95
97
  # class Application < Hanami::Application
96
98
  # configure do
97
99
  # routes do
@@ -104,16 +106,16 @@ module Hanami
104
106
  # end
105
107
  # end
106
108
  #
107
- # Bookshelf::Routes.url(:login)
109
+ # Web.routes.url(:login)
108
110
  # # => 'https://bookshelf.org/login'
109
111
  #
110
- # Bookshelf::Routes.url(:login, return_to: '/dashboard')
112
+ # Web.routes.url(:login, return_to: '/dashboard')
111
113
  # # => 'https://bookshelf.org/login?return_to=%2Fdashboard'
112
114
  #
113
115
  # @example Dynamic finders
114
116
  # require 'hanami'
115
117
  #
116
- # module Bookshelf
118
+ # module Web
117
119
  # class Application < Hanami::Application
118
120
  # configure do
119
121
  # routes do
@@ -126,10 +128,10 @@ module Hanami
126
128
  # end
127
129
  # end
128
130
  #
129
- # Bookshelf::Routes.login_url
131
+ # Web.routes.login_url
130
132
  # # => 'https://bookshelf.org/login'
131
133
  #
132
- # Bookshelf::Routes.login_url(return_to: '/dashboard')
134
+ # Web.routes.login_url(return_to: '/dashboard')
133
135
  # # => 'https://bookshelf.org/login?return_to=%2Fdashboard'
134
136
  def url(name, *args)
135
137
  Utils::Escape::SafeString.new(@routes.url(name, *args))
@@ -1,21 +1,28 @@
1
1
  module Hanami
2
+ # @api private
2
3
  module Routing
3
4
  # The default Rack application that responds when a resource cannot be found.
4
5
  #
5
6
  # @since 0.1.0
6
7
  # @api private
7
8
  class Default
9
+ # @api private
8
10
  DEFAULT_CODE = 404
11
+ # @api private
9
12
  DEFAULT_BODY = ['Not Found'].freeze
13
+ # @api private
10
14
  CONTENT_TYPE = 'Content-Type'.freeze
11
15
 
16
+ # @api private
12
17
  class NullAction
13
18
  include Hanami::Action
14
19
 
20
+ # @api private
15
21
  def call(env)
16
22
  end
17
23
  end
18
24
 
25
+ # @api private
19
26
  def call(env)
20
27
  action = NullAction.new.tap { |a| a.call(env) }
21
28
  [ DEFAULT_CODE, {CONTENT_TYPE => action.content_type}, DEFAULT_BODY, action ]