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
@@ -4,12 +4,17 @@ require 'hanami/utils/blank'
4
4
  require 'securerandom'
5
5
 
6
6
  module Hanami
7
+ # @api private
7
8
  module Commands
9
+ # @api private
8
10
  class Generate
11
+ # @api private
9
12
  class App < Abstract
10
13
 
14
+ # @api private
11
15
  attr_reader :base_path
12
16
 
17
+ # @api private
13
18
  def initialize(options, application_name)
14
19
  @environment = Hanami::Environment.new(options)
15
20
  @options = Hanami::Utils::Hash.new(options).symbolize!
@@ -24,6 +29,7 @@ module Hanami
24
29
  @base_path = Pathname.pwd
25
30
  end
26
31
 
32
+ # @api private
27
33
  def map_templates
28
34
  add_mapping('application.rb.tt', 'application.rb')
29
35
  add_mapping('config/routes.rb.tt', 'config/routes.rb')
@@ -40,6 +46,7 @@ module Hanami
40
46
  add_mapping('.gitkeep', "../../spec/#{ app_name }/views/.gitkeep")
41
47
  end
42
48
 
49
+ # @api private
43
50
  def template_options
44
51
  {
45
52
  app_name: app_name,
@@ -51,6 +58,7 @@ module Hanami
51
58
  }
52
59
  end
53
60
 
61
+ # @api private
54
62
  def post_process_templates
55
63
  add_require_app
56
64
  add_mount_app
@@ -59,10 +67,12 @@ module Hanami
59
67
 
60
68
  private
61
69
 
70
+ # @api private
62
71
  def application_base_url
63
72
  options.fetch(:application_base_url, "/#{app_name}")
64
73
  end
65
74
 
75
+ # @api private
66
76
  def add_require_app
67
77
  # Add "require_relative '../apps/web/application'"
68
78
  generator.inject_into_file base_path.join('config/environment.rb'), after: /require_relative '\.\.\/lib\/.*'/ do
@@ -70,12 +80,14 @@ module Hanami
70
80
  end
71
81
  end
72
82
 
83
+ # @api private
73
84
  def add_mount_app
74
85
  generator.inject_into_file base_path.join('config/environment.rb'), after: /Hanami.configure do/ do |match|
75
86
  "\n mount #{ classified_app_name }::Application, at: '#{ application_base_url }'"
76
87
  end
77
88
  end
78
89
 
90
+ # @api private
79
91
  def add_web_session_secret
80
92
  ['development', 'test'].each do |environment|
81
93
  # Add WEB_SESSIONS_SECRET="abc123" (random hex)
@@ -85,42 +97,51 @@ module Hanami
85
97
  end
86
98
  end
87
99
 
100
+ # @api private
88
101
  def hanamirc
89
102
  @hanamirc ||= Hanamirc.new(base_path)
90
103
  end
91
104
 
105
+ # @api private
92
106
  def target_path
93
107
  base_path.join(application_base_path)
94
108
  end
95
109
 
110
+ # @api private
96
111
  def app_name
97
112
  @application_name.to_s
98
113
  end
99
114
 
115
+ # @api private
100
116
  def upcase_app_name
101
117
  @application_name.to_env_s
102
118
  end
103
119
 
120
+ # @api private
104
121
  def application_base_path
105
122
  ["apps", @application_name].join(::File::SEPARATOR)
106
123
  end
107
124
 
125
+ # @api private
108
126
  def classified_app_name
109
127
  Utils::String.new(app_name).classify.tr('::', '')
110
128
  end
111
129
 
130
+ # @api private
112
131
  def assert_application_name!(value)
113
132
  if argument_blank?(value)
114
133
  raise ArgumentError.new('Application name is missing')
115
134
  end
116
135
  end
117
136
 
137
+ # @api private
118
138
  def assert_architecture!
119
139
  if !environment.container?
120
140
  raise ArgumentError.new('App generator is only available for container architecture.')
121
141
  end
122
142
  end
123
143
 
144
+ # @api private
124
145
  def assert_application_base_url!
125
146
  if options.key?(:application_base_url) && Utils::Blank.blank?(options[:application_base_url])
126
147
  warn "`' is not a valid URL"
@@ -1,13 +1,23 @@
1
1
  require "hanami/commands/generate/abstract"
2
2
 
3
3
  module Hanami
4
+ # @api private
4
5
  module Commands
6
+ # @api private
5
7
  class Generate
6
8
  # @since 0.5.0
7
9
  # @api private
8
10
  class Mailer < Abstract
9
-
10
- attr_reader :name, :name_underscored, :from, :to, :subject
11
+ # @api private
12
+ attr_reader :name
13
+ # @api private
14
+ attr_reader :name_underscored
15
+ # @api private
16
+ attr_reader :from
17
+ # @api private
18
+ attr_reader :to
19
+ # @api private
20
+ attr_reader :subject
11
21
 
12
22
  # @since 0.5.0
13
23
  # @api private
@@ -47,7 +57,7 @@ module Hanami
47
57
  assert_name!
48
58
  end
49
59
 
50
- # @since 0.x.x
60
+ # @since 0.5.0
51
61
  # @api private
52
62
  def map_templates
53
63
  add_mapping("mailer_spec.rb.#{test_framework.framework}.tt", mailer_spec_path)
@@ -56,6 +66,7 @@ module Hanami
56
66
  add_mapping("template.html.tt", html_template_path)
57
67
  end
58
68
 
69
+ # @api private
59
70
  def template_options
60
71
  {
61
72
  mailer: name,
@@ -105,10 +116,12 @@ module Hanami
105
116
  core_root.join("mailers", "templates", "#{ name_underscored }#{ format }.#{ DEFAULT_ENGINE }")
106
117
  end
107
118
 
119
+ # @api private
108
120
  def spec_root
109
121
  Pathname.new("spec")
110
122
  end
111
123
 
124
+ # @api private
112
125
  def core_root
113
126
  Pathname.new("lib").join(project_name)
114
127
  end
@@ -2,11 +2,16 @@ require 'hanami/commands/generate/abstract'
2
2
  require 'hanami/utils/file_list'
3
3
 
4
4
  module Hanami
5
+ # @api private
5
6
  module Commands
7
+ # @api private
6
8
  class Generate
9
+ # @api private
7
10
  class Migration < Abstract
8
-
9
- attr_reader :name, :underscored_name
11
+ # @api private
12
+ attr_reader :name
13
+ # @api private
14
+ attr_reader :underscored_name
10
15
 
11
16
  # @since 0.6.0
12
17
  # @api private
@@ -22,6 +27,7 @@ module Hanami
22
27
  # 20150612160502_create_books.rb
23
28
  FILENAME_PATTERN = '%{timestamp}_%{name}.rb'.freeze
24
29
 
30
+ # @api private
25
31
  def initialize(options, name)
26
32
  super(options)
27
33
 
@@ -32,20 +38,24 @@ module Hanami
32
38
  assert_migration_name!
33
39
  end
34
40
 
41
+ # @api private
35
42
  def map_templates
36
43
  add_mapping('migration.rb.tt', destination_path)
37
44
  end
38
45
 
39
46
  private
40
47
 
48
+ # @api private
41
49
  def destination_path
42
50
  existing_migration_path || new_migration_path
43
51
  end
44
52
 
53
+ # @api private
45
54
  def existing_migration_path
46
55
  Utils::FileList["#{Hanami::Model.configuration.migrations}/[0-9]*_#{underscored_name}.rb"].first
47
56
  end
48
57
 
58
+ # @api private
49
59
  def new_migration_path
50
60
  timestamp = Time.now.utc.strftime(TIMESTAMP_FORMAT)
51
61
  filename = FILENAME_PATTERN % { timestamp: timestamp, name: underscored_name}
@@ -53,6 +63,7 @@ module Hanami
53
63
  Hanami::Model.configuration.migrations.join(filename)
54
64
  end
55
65
 
66
+ # @api private
56
67
  def assert_migration_name!
57
68
  if argument_blank?(name)
58
69
  raise ArgumentError.new('Migration name is missing')
@@ -2,12 +2,21 @@ require 'hanami/commands/generate/abstract'
2
2
  require 'hanami/commands/generate/migration'
3
3
 
4
4
  module Hanami
5
+ # @api private
5
6
  module Commands
7
+ # @api private
6
8
  class Generate
9
+ # @api private
7
10
  class Model < Abstract
8
11
 
9
- attr_reader :input, :model_name, :table_name
12
+ # @api private
13
+ attr_reader :input
14
+ # @api private
15
+ attr_reader :model_name
16
+ # @api private
17
+ attr_reader :table_name
10
18
 
19
+ # @api private
11
20
  def initialize(options, model_name)
12
21
  super(options)
13
22
  @input = Utils::String.new(model_name).underscore
@@ -21,6 +30,7 @@ module Hanami
21
30
  assert_model_name!
22
31
  end
23
32
 
33
+ # @api private
24
34
  def map_templates
25
35
  add_mapping('entity.rb.tt', entity_path)
26
36
  add_mapping('repository.rb.tt', repository_path)
@@ -31,6 +41,7 @@ module Hanami
31
41
  add_mapping("repository_spec.#{ test_framework.framework }.tt", repository_spec_path)
32
42
  end
33
43
 
44
+ # @api private
34
45
  def template_options
35
46
  {
36
47
  model_name: model_name,
@@ -67,10 +78,12 @@ module Hanami
67
78
  end
68
79
  end
69
80
 
81
+ # @api private
70
82
  def skip_migration?
71
83
  options.fetch(:skip_migration, false)
72
84
  end
73
85
 
86
+ # @api private
74
87
  def model_root
75
88
  Pathname.new('lib').join(project_name)
76
89
  end
@@ -3,14 +3,19 @@ require 'hanami/application_name'
3
3
  require 'securerandom'
4
4
 
5
5
  module Hanami
6
+ # @api private
6
7
  module Commands
8
+ # @api private
7
9
  class Generate
10
+ # @api private
8
11
  class SecretToken
9
12
 
13
+ # @api private
10
14
  def initialize(application_name)
11
15
  @application_name = application_name
12
16
  end
13
17
 
18
+ # @api private
14
19
  def start
15
20
  if Hanami::Utils::Blank.blank?(@application_name)
16
21
  puts SecureRandom.hex(32)
@@ -21,6 +26,7 @@ module Hanami
21
26
  end
22
27
 
23
28
  private
29
+ # @api private
24
30
  def upcase_app_name
25
31
  @application_name.upcase
26
32
  end
@@ -8,18 +8,34 @@ require 'hanami/utils'
8
8
  require 'hanami/utils/hash'
9
9
 
10
10
  module Hanami
11
+ # @api private
11
12
  module Commands
13
+ # @api private
12
14
  class New
15
+ # @api private
13
16
  class Abstract
14
17
 
15
18
  include Hanami::Generators::Generatable
16
19
 
20
+ # @api private
17
21
  DEFAULT_ARCHITECTURE = 'container'.freeze
22
+ # @api private
18
23
  DEFAULT_APPLICATION_BASE_URL = '/'.freeze
19
24
 
20
- attr_reader :options, :target_path, :database_config,
21
- :test_framework, :hanami_model_version, :template_engine
22
-
25
+ # @api private
26
+ attr_reader :options
27
+ # @api private
28
+ attr_reader :target_path
29
+ # @api private
30
+ attr_reader :database_config
31
+ # @api private
32
+ attr_reader :test_framework
33
+ # @api private
34
+ attr_reader :hanami_model_version
35
+ # @api private
36
+ attr_reader :template_engine
37
+
38
+ # @api private
23
39
  def initialize(options, name)
24
40
  @options = Hanami::Utils::Hash.new(options).symbolize!
25
41
  @name = name
@@ -29,12 +45,13 @@ module Hanami
29
45
  assert_name!
30
46
  assert_architecture!
31
47
 
32
- @hanami_model_version = '~> 1.0.0.beta2'
48
+ @hanami_model_version = '~> 1.0.0.beta3'
33
49
  @database_config = Hanami::Generators::DatabaseConfig.new(options[:database], project_name)
34
50
  @test_framework = Hanami::Generators::TestFramework.new(hanamirc, @options[:test])
35
51
  @template_engine = Hanami::Generators::TemplateEngine.new(hanamirc, @options[:template])
36
52
  end
37
53
 
54
+ # @api private
38
55
  def start
39
56
  FileUtils.mkdir_p(project_directory)
40
57
  Dir.chdir(project_directory) do
@@ -46,20 +63,24 @@ module Hanami
46
63
 
47
64
  private
48
65
 
66
+ # @api private
49
67
  def hanamirc
50
68
  @hanamirc ||= Hanamirc.new(Pathname.new('.'))
51
69
  end
52
70
 
71
+ # @api private
53
72
  def start_in_app_dir
54
73
  raise NotImplementedError
55
74
  end
56
75
 
76
+ # @api private
57
77
  def add_sql_templates
58
78
  return if !database_config.sql?
59
79
 
60
80
  add_mapping('schema.sql.tt', 'db/schema.sql')
61
81
  end
62
82
 
83
+ # @api private
63
84
  def add_git_templates
64
85
  return if git_dir_present?
65
86
 
@@ -68,64 +89,78 @@ module Hanami
68
89
  add_mapping(source, target)
69
90
  end
70
91
 
92
+ # @api private
71
93
  def real_project_name
72
94
  @name == '.' ? ::File.basename(Dir.getwd) : @name
73
95
  end
74
96
 
97
+ # @api private
75
98
  def project_name
76
99
  ApplicationName.new(real_project_name)
77
100
  end
78
101
 
102
+ # @api private
79
103
  def project_directory
80
104
  @name == '.' ? '.' : project_name
81
105
  end
82
106
 
107
+ # @api private
83
108
  def target
84
109
  Pathname.new('.')
85
110
  end
86
111
 
112
+ # @api private
87
113
  def init_git
88
114
  return if git_dir_present?
89
115
 
90
116
  generator.run("git init #{Shellwords.escape(target)}", capture: true)
91
117
  end
92
118
 
119
+ # @api private
93
120
  def git_dir_present?
94
121
  File.directory?(target.join('.git'))
95
122
  end
96
123
 
124
+ # @api private
97
125
  def hanami_version
98
126
  Hanami::Version.gem_requirement
99
127
  end
100
128
 
129
+ # @api private
101
130
  def hanami_head?
102
131
  options.fetch(:hanami_head, false)
103
132
  end
104
133
 
134
+ # @api private
105
135
  def code_reloading?
106
136
  !Hanami::Utils.jruby?
107
137
  end
108
138
 
139
+ # @api private
109
140
  def architecture
110
141
  options.fetch(:architecture, DEFAULT_ARCHITECTURE)
111
142
  end
112
143
 
144
+ # @api private
113
145
  def assert_name!
114
146
  if argument_blank?(@name) || @name.include?(File::SEPARATOR)
115
147
  raise ArgumentError.new("APPLICATION_NAME is required and must not contain #{File::SEPARATOR}.")
116
148
  end
117
149
  end
118
150
 
151
+ # @api private
119
152
  def assert_architecture!
120
153
  if !['app', 'container'].include?(architecture)
121
154
  raise ArgumentError.new("Architecture must be one of 'app', 'container' but was '#{architecture}'")
122
155
  end
123
156
  end
124
157
 
158
+ # @api private
125
159
  def application_base_url
126
160
  options[:application_base_url] || DEFAULT_APPLICATION_BASE_URL
127
161
  end
128
162
 
163
+ # @api private
129
164
  def assert_options!
130
165
  if options.nil?
131
166
  raise ArgumentError.new('options must not be nil')