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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/FEATURES.md +2 -0
- data/LICENSE.md +1 -1
- data/README.md +1 -1
- data/hanami.gemspec +8 -8
- data/lib/hanami.rb +0 -5
- data/lib/hanami/action/csrf_protection.rb +35 -0
- data/lib/hanami/app.rb +1 -1
- data/lib/hanami/application.rb +2 -0
- data/lib/hanami/application_configuration.rb +1 -12
- data/lib/hanami/application_name.rb +8 -2
- data/lib/hanami/application_namespace.rb +2 -0
- data/lib/hanami/assets/asset.rb +1 -0
- data/lib/hanami/cli.rb +7 -0
- data/lib/hanami/cli_base.rb +3 -0
- data/lib/hanami/cli_sub_commands/assets.rb +2 -0
- data/lib/hanami/cli_sub_commands/db.rb +15 -2
- data/lib/hanami/cli_sub_commands/destroy.rb +6 -0
- data/lib/hanami/cli_sub_commands/generate.rb +7 -2
- data/lib/hanami/commands/assets/precompile.rb +4 -0
- data/lib/hanami/commands/command.rb +13 -0
- data/lib/hanami/commands/console.rb +6 -0
- data/lib/hanami/commands/db/apply.rb +3 -0
- data/lib/hanami/commands/db/console.rb +7 -0
- data/lib/hanami/commands/db/create.rb +3 -0
- data/lib/hanami/commands/db/drop.rb +3 -0
- data/lib/hanami/commands/db/migrate.rb +5 -0
- data/lib/hanami/commands/db/prepare.rb +3 -0
- data/lib/hanami/commands/db/version.rb +3 -0
- data/lib/hanami/commands/generate/abstract.rb +13 -1
- data/lib/hanami/commands/generate/action.rb +21 -0
- data/lib/hanami/commands/generate/app.rb +21 -0
- data/lib/hanami/commands/generate/mailer.rb +16 -3
- data/lib/hanami/commands/generate/migration.rb +13 -2
- data/lib/hanami/commands/generate/model.rb +14 -1
- data/lib/hanami/commands/generate/secret_token.rb +6 -0
- data/lib/hanami/commands/new/abstract.rb +39 -4
- data/lib/hanami/commands/new/app.rb +15 -0
- data/lib/hanami/commands/new/container.rb +14 -0
- data/lib/hanami/commands/routes.rb +2 -0
- data/lib/hanami/commands/server.rb +4 -0
- data/lib/hanami/components/app/assets.rb +4 -0
- data/lib/hanami/components/app/controller.rb +4 -0
- data/lib/hanami/components/app/routes.rb +6 -0
- data/lib/hanami/components/app/view.rb +4 -0
- data/lib/hanami/components/component.rb +2 -0
- data/lib/hanami/components/components.rb +12 -5
- data/lib/hanami/components/routes_inspector.rb +2 -0
- data/lib/hanami/config/cookies.rb +1 -0
- data/lib/hanami/config/framework_configuration.rb +1 -0
- data/lib/hanami/config/load_paths.rb +4 -0
- data/lib/hanami/config/mapper.rb +11 -0
- data/lib/hanami/config/routes.rb +4 -0
- data/lib/hanami/config/security.rb +2 -0
- data/lib/hanami/config/sessions.rb +6 -0
- data/lib/hanami/configuration.rb +102 -0
- data/lib/hanami/environment.rb +13 -0
- data/lib/hanami/environment_application_configurations.rb +7 -0
- data/lib/hanami/generators/app/application.rb.tt +31 -23
- data/lib/hanami/generators/app/favicon.ico +0 -0
- data/lib/hanami/generators/database_config.rb +19 -1
- data/lib/hanami/generators/generatable.rb +13 -0
- data/lib/hanami/generators/generator.rb +8 -0
- data/lib/hanami/generators/template_engine.rb +9 -0
- data/lib/hanami/generators/test_framework.rb +12 -0
- data/lib/hanami/hanamirc.rb +2 -0
- data/lib/hanami/mailer/glue.rb +1 -0
- data/lib/hanami/middleware.rb +24 -0
- data/lib/hanami/rendering_policy.rb +15 -0
- data/lib/hanami/routes.rb +14 -12
- data/lib/hanami/routing/default.rb +7 -0
- data/lib/hanami/server.rb +6 -0
- data/lib/hanami/version.rb +1 -1
- data/lib/hanami/views/default.rb +3 -0
- data/lib/hanami/views/default_template_finder.rb +2 -0
- data/lib/hanami/views/null_view.rb +2 -0
- data/lib/hanami/welcome.rb +7 -0
- metadata +18 -19
- 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
|
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.
|
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
|
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
|
-
|
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
|
-
|
21
|
-
|
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.
|
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')
|