hoboken 0.0.1.beta2 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +5 -5
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +33 -0
  3. data/.github/ISSUE_TEMPLATE/code_change.md +11 -0
  4. data/.github/PULL_REQUEST_TEMPLATE.md +25 -0
  5. data/.github/dependabot.yml +7 -0
  6. data/.github/workflows/ruby.yml +28 -0
  7. data/.gitignore +3 -0
  8. data/.rubocop.yml +41 -0
  9. data/.ruby-version +1 -0
  10. data/.tool-versions +1 -0
  11. data/CHANGELOG.md +131 -0
  12. data/CODE_OF_CONDUCT.md +8 -0
  13. data/CONTRIBUTING.md +16 -0
  14. data/Gemfile +2 -0
  15. data/IDEAS.md +57 -0
  16. data/LICENSE.txt +1 -1
  17. data/README.md +28 -17
  18. data/Rakefile +14 -8
  19. data/bin/hoboken +2 -1
  20. data/hoboken.gemspec +63 -16
  21. data/lib/hoboken/actions.rb +11 -6
  22. data/lib/hoboken/add_ons/active_record.rb +142 -0
  23. data/lib/hoboken/add_ons/airbrake.rb +64 -0
  24. data/lib/hoboken/add_ons/github_action.rb +14 -0
  25. data/lib/hoboken/add_ons/heroku.rb +29 -0
  26. data/lib/hoboken/add_ons/internationalization.rb +28 -0
  27. data/lib/hoboken/add_ons/metrics.rb +60 -0
  28. data/lib/hoboken/add_ons/omniauth.rb +174 -0
  29. data/lib/hoboken/add_ons/rubocop.rb +46 -0
  30. data/lib/hoboken/add_ons/sequel.rb +135 -0
  31. data/lib/hoboken/add_ons/sidekiq.rb +137 -0
  32. data/lib/hoboken/add_ons/travis.rb +15 -0
  33. data/lib/hoboken/add_ons/turnip.rb +109 -0
  34. data/lib/hoboken/add_ons/twbs.rb +50 -0
  35. data/lib/hoboken/add_ons/vcr.rb +54 -0
  36. data/lib/hoboken/generate.rb +146 -46
  37. data/lib/hoboken/templates/Gemfile.erb.tt +43 -8
  38. data/lib/hoboken/templates/README.md.tt +117 -35
  39. data/lib/hoboken/templates/Rakefile.tt +20 -16
  40. data/lib/hoboken/templates/active_record.rake +11 -0
  41. data/lib/hoboken/templates/airbrake.rb.tt +13 -0
  42. data/lib/hoboken/templates/classic.rb.tt +25 -11
  43. data/lib/hoboken/templates/classic_environment.rb.tt +51 -0
  44. data/lib/hoboken/templates/config.ru.tt +4 -2
  45. data/lib/hoboken/templates/console +19 -0
  46. data/lib/hoboken/templates/db.rb.tt +24 -0
  47. data/lib/hoboken/templates/example_worker.rb.tt +14 -0
  48. data/lib/hoboken/templates/github_action.tt +28 -0
  49. data/lib/hoboken/templates/gitignore +8 -0
  50. data/lib/hoboken/templates/metrics.rake.tt +12 -9
  51. data/lib/hoboken/templates/modular.rb.tt +28 -15
  52. data/lib/hoboken/templates/modular_environment.rb.tt +62 -0
  53. data/lib/hoboken/templates/puma.rb.tt +21 -0
  54. data/lib/hoboken/templates/rspec.rake.tt +9 -0
  55. data/lib/hoboken/templates/rubocop.yml.tt +51 -0
  56. data/lib/hoboken/templates/seeds.rb +12 -0
  57. data/lib/hoboken/templates/sequel.rake +21 -0
  58. data/lib/hoboken/templates/server +15 -0
  59. data/lib/hoboken/templates/setup +28 -0
  60. data/lib/hoboken/templates/sidekiq.rb.tt +21 -0
  61. data/lib/hoboken/templates/spec/app_spec.rb.tt +13 -0
  62. data/lib/hoboken/templates/spec/example_worker_spec.rb.tt +16 -0
  63. data/lib/hoboken/templates/spec/rack_matchers.rb.tt +58 -0
  64. data/lib/hoboken/templates/spec/spec_helper.rb.tt +37 -0
  65. data/lib/hoboken/templates/spec/turnip_helper.rb.tt +10 -0
  66. data/lib/hoboken/templates/styles.css.tt +1 -1
  67. data/lib/hoboken/templates/support/rack_helpers.rb.tt +55 -0
  68. data/lib/hoboken/templates/support/rack_test_assertions.rb.tt +113 -0
  69. data/lib/hoboken/templates/test/test_helper.rb.tt +47 -0
  70. data/lib/hoboken/templates/test/unit/app_test.rb.tt +11 -3
  71. data/lib/hoboken/templates/test/unit/example_worker_test.rb.tt +20 -0
  72. data/lib/hoboken/templates/test_unit.rake.tt +18 -0
  73. data/lib/hoboken/templates/vcr_setup.rb.tt +15 -0
  74. data/lib/hoboken/templates/views/index.erb.tt +11 -4
  75. data/lib/hoboken/templates/views/layout.erb.tt +7 -4
  76. data/lib/hoboken/version.rb +3 -1
  77. data/lib/hoboken.rb +147 -325
  78. data/test/fixtures/Gemfile +3 -3
  79. data/test/fixtures/Gemfile.pristine +3 -2
  80. data/test/integration/active_record_test.rb +66 -0
  81. data/test/integration/airbrake_test.rb +31 -0
  82. data/test/integration/generate_classic_test.rb +75 -0
  83. data/test/integration/generate_modular_test.rb +83 -0
  84. data/test/integration/github_action_test.rb +13 -0
  85. data/test/integration/heroku_test.rb +14 -0
  86. data/test/integration/internationalization_test.rb +26 -0
  87. data/test/integration/metrics_test.rb +54 -0
  88. data/test/integration/omniauth_test.rb +143 -0
  89. data/test/integration/rubocop_test.rb +39 -0
  90. data/test/integration/sequel_test.rb +64 -0
  91. data/test/integration/sidekiq_test.rb +105 -0
  92. data/test/integration/travis_test.rb +13 -0
  93. data/test/integration/turnip_test.rb +51 -0
  94. data/test/integration/twitter_bootstrap_test.rb +39 -0
  95. data/test/integration/vcr_test.rb +54 -0
  96. data/test/test_helper.rb +109 -0
  97. data/test/unit/hoboken_actions_test.rb +82 -53
  98. data/www/Gemfile +4 -0
  99. data/www/README.md +2 -0
  100. data/www/config.rb +11 -0
  101. data/www/source/documentation.html.erb +274 -0
  102. data/www/source/images/hoboken-running.png +0 -0
  103. data/www/source/images/hoboken.png +0 -0
  104. data/www/source/images/sinatra.png +0 -0
  105. data/www/source/index.html.erb +44 -0
  106. data/www/source/javascripts/all.js +1 -0
  107. data/www/source/layouts/layout.erb +38 -0
  108. data/www/source/stylesheets/all.css.scss +116 -0
  109. data/www/source/stylesheets/normalize.css +375 -0
  110. metadata +655 -29
  111. data/lib/hoboken/templates/sprockets.rake +0 -33
  112. data/lib/hoboken/templates/sprockets_chain.rb +0 -26
  113. data/lib/hoboken/templates/sprockets_helper.rb +0 -13
  114. data/lib/hoboken/templates/test/support/rack_test_assertions.rb.tt +0 -79
  115. data/lib/hoboken/templates/test/unit/test_helper.rb.tt +0 -36
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hoboken
4
+ module AddOns
5
+ # Background processing via the Sidekiq gem.
6
+ #
7
+ class Sidekiq < ::Hoboken::Group
8
+ def add_gems
9
+ gem 'sidekiq', version: '6.2'
10
+ end
11
+
12
+ def adjust_rackup_config
13
+ gsub_file('config.ru', /run .*::App.*\n/) do |match|
14
+ <<~CODE
15
+ require 'sidekiq/web'
16
+
17
+ if 'production' == ENV.fetch('RACK_ENV', 'production')
18
+ Sidekiq::Web.use Rack::Auth::Basic do |username, password|
19
+ [username, password] == [ENV['SIDEKIQ_USERNAME'], ENV['SIDEKIQ_PASSWORD']]
20
+ end
21
+ end
22
+
23
+ Sidekiq::Web.use Rack::Session::Cookie, secret: ENV['SESSION_SECRET']
24
+ run Rack::URLMap.new('/' => #{match[4...-1].chomp}, '/sidekiq' => Sidekiq::Web)
25
+ CODE
26
+ end
27
+ end
28
+
29
+ def setup_config
30
+ template('hoboken/templates/sidekiq.rb.tt', 'config/sidekiq.rb')
31
+ location = "require_relative '../app'"
32
+ insert_into_file('config/environment.rb', before: location) do
33
+ "require_relative 'sidekiq'\n\n"
34
+ end
35
+ end
36
+
37
+ def example_worker
38
+ empty_directory('workers')
39
+ template('hoboken/templates/example_worker.rb.tt', 'workers/example_worker.rb')
40
+ end
41
+
42
+ def worker_test_and_helper
43
+ return if rspec?
44
+
45
+ insert_into_file('test/test_helper.rb', after: "require 'rack/test'") do
46
+ "\nrequire 'sidekiq/testing'"
47
+ end
48
+
49
+ template(
50
+ 'hoboken/templates/test/unit/example_worker_test.rb.tt',
51
+ 'test/unit/example_worker_test.rb'
52
+ )
53
+ end
54
+
55
+ # rubocop:disable Metrics/MethodLength
56
+ def worker_spec_and_helper
57
+ return unless rspec?
58
+
59
+ insert_into_file('spec/spec_helper.rb', after: "require 'rack/test'") do
60
+ "\nrequire 'sidekiq/testing'"
61
+ end
62
+
63
+ snippet = <<~CODE
64
+ config.before(:each, sidekiq: true) do
65
+ Sidekiq::Worker.clear_all
66
+ end
67
+ CODE
68
+
69
+ location = /RSpec\.configure do \|config\|\n/
70
+ insert_into_file('spec/spec_helper.rb', after: location) do
71
+ "#{indent(snippet, 2)}\n"
72
+ end
73
+
74
+ template(
75
+ 'hoboken/templates/spec/example_worker_spec.rb.tt',
76
+ 'spec/example_worker_spec.rb'
77
+ )
78
+ end
79
+ # rubocop:enable Metrics/MethodLength
80
+
81
+ def add_worker_to_procfile
82
+ append_file('Procfile') do
83
+ "\nworker: bundle exec sidekiq " \
84
+ '-r ./config/sidekiq.rb ' \
85
+ '-e $RACK_ENV ' \
86
+ '-c ${MAX_THREADS:-5} ' \
87
+ "-v\n"
88
+ end
89
+ end
90
+
91
+ # rubocop:disable Metrics/MethodLength
92
+ def update_readme
93
+ snippet = <<~CODE
94
+ <tr>
95
+ <td>REDIS_URL</td>
96
+ <td>Yes</td>
97
+ <td>localhost:6379</td>
98
+ <td>Redis connection URL</td>
99
+ </tr>
100
+ <tr>
101
+ <td>SIDEKIQ_PASSWORD</td>
102
+ <td>Production Only</td>
103
+ <td>None</td>
104
+ <td>Password for SidekiqUI Basic Auth</td>
105
+ </tr>
106
+ <tr>
107
+ <td>SIDEKIQ_USERNAME</td>
108
+ <td>Production Only</td>
109
+ <td>None</td>
110
+ <td>Username for SidekiqUI Basic Auth</td>
111
+ </tr>
112
+ CODE
113
+
114
+ insert_into_file('README.md', after: /<tbody>\n/) do
115
+ indent(snippet, 8)
116
+ end
117
+ end
118
+ # rubocop:enable Metrics/MethodLength
119
+
120
+ def reminders
121
+ text = <<~TEXT
122
+
123
+ Gemfile updated... don't forget to 'bundle install'
124
+
125
+ You can configure a Sidekiq error handing service in `config/sidekiq.rb`.
126
+
127
+ Sidekiq UI is available at '/sidekiq'. In production environments
128
+ the UI is protected with HTTP Basic Auth. Don't forget to set
129
+ `SIDEKIQ_USERNAME` and `SIDEKIQ_PASSWORD` in your production
130
+ environment or you won't be able to access the Sidekiq UI.
131
+ TEXT
132
+
133
+ say text, :green
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hoboken
4
+ module AddOns
5
+ # Basic Travis-CI YAML config.
6
+ #
7
+ class Travis < ::Hoboken::Group
8
+ def travis_yml
9
+ create_file('.travis.yml') do
10
+ 'language: ruby'
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hoboken
4
+ module AddOns
5
+ # Gherkin extension for RSpec
6
+ #
7
+ class Turnip < ::Hoboken::Group
8
+ def add_gems
9
+ return unless rspec?
10
+
11
+ gem 'turnip', version: '4.3', group: :test
12
+ end
13
+
14
+ # rubocop:disable Metrics/MethodLength
15
+ def add_sample_files
16
+ return unless rspec?
17
+
18
+ empty_directory('spec/features')
19
+ empty_directory('spec/support/steps')
20
+ create_file('spec/features/example.feature') do
21
+ <<~TEXT
22
+ @feature
23
+ Feature: An Example
24
+ This is an example feature spec that can be deleted.
25
+
26
+ Scenario: Name of some scenario
27
+ Given nothing
28
+ When I do nothing
29
+ Then nothing should happen
30
+ TEXT
31
+ end
32
+
33
+ create_file('spec/support/steps/example_steps.rb') do
34
+ <<~CODE
35
+ # frozen_string_literal: true
36
+
37
+ # Steps for the example feature that can be deleted.
38
+
39
+ step 'nothing' do
40
+ # ...
41
+ end
42
+
43
+ step 'I do nothing' do
44
+ # ...
45
+ end
46
+
47
+ step 'nothing should happen' do
48
+ # ...
49
+ end
50
+ CODE
51
+ end
52
+ end
53
+ # rubocop:enable Metrics/MethodLength
54
+
55
+ def add_helper
56
+ return unless rspec?
57
+
58
+ template(
59
+ 'hoboken/templates/spec/turnip_helper.rb.tt',
60
+ 'spec/turnip_helper.rb'
61
+ )
62
+ end
63
+
64
+ def rake_task
65
+ return unless rspec?
66
+
67
+ create_file('tasks/turnip.rake') do
68
+ <<~TEXT
69
+ # frozen_string_literal: true
70
+
71
+ require 'rspec/core/rake_task'
72
+
73
+ desc 'Run turnip acceptance tests'
74
+ RSpec::Core::RakeTask.new(:turnip) do |t|
75
+ t.pattern = './spec{,/*/**}/*.feature'
76
+ t.rspec_opts = ['-r turnip/rspec']
77
+ end
78
+ TEXT
79
+ end
80
+ end
81
+
82
+ def default_rake_task
83
+ return unless rspec?
84
+
85
+ gsub_file('Rakefile', /task default:.*/, 'task default: %w[spec turnip]')
86
+ end
87
+
88
+ def ci_task
89
+ return unless rspec?
90
+
91
+ gsub_file('Rakefile', /task ci:.*/) do |match|
92
+ if match.include?('rubocop')
93
+ 'task ci: %w[spec turnip rubocop]'
94
+ else
95
+ 'task ci: %w[spec turnip]'
96
+ end
97
+ end
98
+ end
99
+
100
+ def reminders
101
+ if rspec?
102
+ say "Gemfile updated... don't forget to 'bundle install'", :green
103
+ else
104
+ say 'Turnip requires RSpec to be setup', :red
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hoboken
4
+ module AddOns
5
+ # Twitter Bootstrap support.
6
+ #
7
+ class TwitterBootstrap < ::Hoboken::Group
8
+ def add_gem
9
+ gem 'bootstrap', version: '5.0.0.beta3', group: :assets
10
+ end
11
+
12
+ def update_app
13
+ indentation = classic? ? 2 : 6
14
+ location = /configure do\n/
15
+ insert_into_file('config/environment.rb', after: location) do
16
+ indent("require 'bootstrap'\n", indentation)
17
+ end
18
+ end
19
+
20
+ def update_asset_files
21
+ prepend_file('assets/stylesheets/styles.scss') do
22
+ <<~CODE
23
+ @import "bootstrap";
24
+
25
+ CODE
26
+ end
27
+
28
+ prepend_file('assets/javascripts/app.js') do
29
+ <<~CODE
30
+ //= require popper
31
+ //= require bootstrap-sprockets
32
+ CODE
33
+ end
34
+ end
35
+
36
+ def remove_normalize_css
37
+ gsub_file(
38
+ 'views/layout.erb',
39
+ '<link rel="stylesheet" type="text/css" ' \
40
+ 'href="//cdnjs.cloudflare.com/ajax/libs/normalize/2.1.3/normalize.min.css">',
41
+ ''
42
+ )
43
+ end
44
+
45
+ def reminders
46
+ say "\nGemfile updated... don't forget to 'bundle install'"
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hoboken
4
+ module AddOns
5
+ # Record your test suite's HTTP interactions and replay them during
6
+ # future test runs.
7
+ #
8
+ class Vcr < ::Hoboken::Group
9
+ def add_gems
10
+ gem 'vcr', version: '6.0', group: :test
11
+ gem 'webmock', version: '3.13', group: :test
12
+ end
13
+
14
+ def add_directories
15
+ empty_directory(File.join(location, 'fixtures', 'vcr_cassettes'))
16
+ end
17
+
18
+ def add_setup_file
19
+ template(
20
+ 'hoboken/templates/vcr_setup.rb.tt',
21
+ File.join(location, 'support/vcr_setup.rb')
22
+ )
23
+ end
24
+
25
+ def require_vcr_in_test_helper
26
+ return if rspec?
27
+
28
+ snippet_location = "require_relative 'support/rack_helpers'"
29
+ insert_into_file('test/test_helper.rb', after: snippet_location) do
30
+ "\nrequire_relative 'support/vcr_setup'"
31
+ end
32
+ end
33
+
34
+ def require_vcr_in_spec_helper
35
+ return unless rspec?
36
+
37
+ snippet_location = "require 'support/rack_helpers'"
38
+ insert_into_file('spec/spec_helper.rb', after: snippet_location) do
39
+ "\nrequire 'support/vcr_setup'"
40
+ end
41
+ end
42
+
43
+ def reminders
44
+ say "Gemfile updated... don't forget to 'bundle install'", :green
45
+ end
46
+
47
+ private
48
+
49
+ def location
50
+ rspec? ? 'spec' : 'test'
51
+ end
52
+ end
53
+ end
54
+ end
@@ -1,111 +1,197 @@
1
- require "rbconfig"
1
+ # frozen_string_literal: true
2
+
3
+ require 'rbconfig'
2
4
 
3
5
  module Hoboken
6
+ # Main project generator.
7
+ #
8
+ # rubocop:disable Metrics/ClassLength
4
9
  class Generate < Thor::Group
5
10
  include Thor::Actions
6
11
 
7
- NULL = RbConfig::CONFIG['host_os'] =~ /mingw|mswin/ ? 'NUL' : '/dev/null'
12
+ NULL = RbConfig::CONFIG['host_os'].match?(/mingw|mswin/) ? 'NUL' : '/dev/null'
8
13
 
9
14
  argument :name
10
15
 
11
16
  class_option :ruby_version,
12
17
  type: :string,
13
- desc: "Ruby version for Gemfile",
18
+ desc: 'Ruby version for Gemfile',
14
19
  default: RUBY_VERSION
15
20
 
16
21
  class_option :tiny,
17
22
  type: :boolean,
18
- desc: "Generate views inline; do not create /public folder",
23
+ desc: 'Generate views inline; do not create /public folder',
19
24
  default: false
20
25
 
21
26
  class_option :type,
22
27
  type: :string,
23
- desc: "Architecture type (classic or modular)",
28
+ desc: 'Architecture type (classic or modular)',
24
29
  default: :classic
25
30
 
26
31
  class_option :git,
27
32
  type: :boolean,
28
- desc: "Create a Git repository and make initial commit",
33
+ desc: 'Create a Git repository and make initial commit',
34
+ default: false
35
+
36
+ class_option :api_only,
37
+ type: :boolean,
38
+ desc: 'API only, no views, public folder, etc.',
29
39
  default: false
30
40
 
41
+ class_option :test_framework,
42
+ type: :string,
43
+ desc: 'Testing framework; can be either test-unit or rspec',
44
+ default: 'test-unit'
45
+
31
46
  def self.source_root
32
47
  File.dirname(__FILE__)
33
48
  end
34
49
 
35
50
  def app_folder
36
51
  empty_directory(snake_name)
37
- apply_template("classic.rb.tt", "app.rb")
38
- apply_template("Gemfile.erb.tt", "Gemfile")
39
- apply_template("config.ru.tt", "config.ru")
40
- apply_template("README.md.tt", "README.md")
41
- apply_template("Rakefile.tt", "Rakefile")
52
+ apply_template('classic.rb.tt', 'app.rb')
53
+ apply_template('Gemfile.erb.tt', 'Gemfile')
54
+ apply_template('config.ru.tt', 'config.ru')
55
+ apply_template('README.md.tt', 'README.md')
56
+ apply_template('Rakefile.tt', 'Rakefile')
57
+
58
+ create_file("#{snake_name}/Procfile") do
59
+ 'web: bundle exec puma -C config/puma.rb'
60
+ end
42
61
  end
43
62
 
44
- def view_folder
45
- empty_directory("#{snake_name}/views")
46
- apply_template("views/layout.erb.tt", "views/layout.erb")
47
- apply_template("views/index.erb.tt", "views/index.erb")
63
+ def bin_folder
64
+ empty_directory("#{snake_name}/bin")
65
+ %w[console server setup].each do |f|
66
+ target = "#{snake_name}/bin/#{f}"
67
+ copy_file("templates/#{f}", target)
68
+ chmod(target, 0o755)
69
+ end
48
70
  end
49
71
 
50
- def inline_views
51
- return unless options[:tiny]
52
- combined_views = %w(layout index).map do |f|
53
- "@@#{f}\n" + File.read("#{snake_name}/views/#{f}.erb")
54
- end.join("\n")
72
+ def config_folder
73
+ empty_directory("#{snake_name}/config")
74
+ apply_template('puma.rb.tt', 'config/puma.rb')
75
+ apply_template('classic_environment.rb.tt', 'config/environment.rb')
76
+ end
55
77
 
56
- append_to_file("#{snake_name}/app.rb", "\n__END__\n\n#{combined_views}")
57
- remove_dir("#{snake_name}/views")
78
+ def view_folder
79
+ return if options[:api_only]
80
+
81
+ empty_directory("#{snake_name}/views")
82
+ apply_template('views/layout.erb.tt', 'views/layout.erb')
83
+ apply_template('views/index.erb.tt', 'views/index.erb')
58
84
  end
59
85
 
60
- def public_folder
61
- return if options[:tiny]
86
+ def asset_pipeline
87
+ return if options[:api_only]
88
+
62
89
  inside snake_name do
63
- empty_directory("public")
64
- %w(css img js).each { |f| empty_directory("public/#{f}") }
90
+ empty_directory('assets')
91
+ empty_directory('public')
92
+ %w[stylesheets images javascripts].each { |f| empty_directory("assets/#{f}") }
65
93
  end
66
- apply_template("styles.css.tt", "public/css/styles.css")
67
- create_file("#{snake_name}/public/js/app.js", "")
68
94
 
69
- %w(favicon hoboken sinatra).each do |f|
70
- copy_file("templates/#{f}.png", "#{snake_name}/public/img/#{f}.png")
95
+ apply_template('styles.css.tt', 'assets/stylesheets/styles.scss')
96
+ create_file("#{snake_name}/assets/javascripts/app.js", '')
97
+
98
+ %w[favicon hoboken sinatra].each do |f|
99
+ copy_file("templates/#{f}.png", "#{snake_name}/assets/images/#{f}.png")
71
100
  end
72
101
  end
73
102
 
74
103
  def test_folder
104
+ return unless 'test-unit' == options[:test_framework]
105
+
75
106
  empty_directory("#{snake_name}/test/unit")
107
+ empty_directory("#{snake_name}/test/integration")
76
108
  empty_directory("#{snake_name}/test/support")
77
- apply_template("test/unit/test_helper.rb.tt", "test/unit/test_helper.rb")
78
- apply_template("test/unit/app_test.rb.tt", "test/unit/app_test.rb")
79
- apply_template("test/support/rack_test_assertions.rb.tt", "test/support/rack_test_assertions.rb")
109
+ apply_template('test_unit.rake.tt', 'tasks/test_unit.rake')
110
+ apply_template('test/test_helper.rb.tt', 'test/test_helper.rb')
111
+ apply_template('test/unit/app_test.rb.tt', 'test/unit/app_test.rb')
112
+ apply_template('support/rack_helpers.rb.tt', 'test/support/rack_helpers.rb')
113
+ apply_template('support/rack_test_assertions.rb.tt',
114
+ 'test/support/rack_test_assertions.rb')
115
+ end
116
+
117
+ def rspec_setup
118
+ return unless 'rspec' == options[:test_framework]
119
+
120
+ empty_directory("#{snake_name}/spec")
121
+ empty_directory("#{snake_name}/spec/support")
122
+ create_file("#{snake_name}/.rspec") { '--require spec_helper' }
123
+ apply_template('rspec.rake.tt', 'tasks/rspec.rake')
124
+ apply_template('spec/app_spec.rb.tt', 'spec/app_spec.rb')
125
+ apply_template('spec/spec_helper.rb.tt', 'spec/spec_helper.rb')
126
+ apply_template('support/rack_helpers.rb.tt', 'spec/support/rack_helpers.rb')
127
+ apply_template('spec/rack_matchers.rb.tt', 'spec/support/rack_matchers.rb')
128
+ end
129
+
130
+ def env_file
131
+ inside snake_name do
132
+ create_file('.env') do
133
+ "RACK_ENV=development\nPORT=9292\nSESSION_SECRET=secret"
134
+ end
135
+ end
80
136
  end
81
137
 
138
+ # rubocop:disable Metrics/AbcSize
82
139
  def make_modular
83
- return unless "modular" == options[:type]
140
+ return unless 'modular' == options[:type]
141
+
84
142
  empty_directory("#{snake_name}/helpers")
85
143
  remove_file("#{snake_name}/app.rb")
86
- apply_template("modular.rb.tt", "app.rb")
87
- ["config.ru", "test/unit/test_helper.rb"].each do |f|
144
+ remove_file("#{snake_name}/config/environment.rb")
145
+ apply_template('modular.rb.tt', 'app.rb')
146
+ apply_template('modular_environment.rb.tt', 'config/environment.rb')
147
+
148
+ files = [].tap do |f|
149
+ f << 'config.ru'
150
+ f << 'test/support/rack_helpers.rb' if 'test-unit' == options[:test_framework]
151
+ f << 'spec/support/rack_helpers.rb' if 'rspec' == options[:test_framework]
152
+ end
153
+
154
+ files.each do |f|
88
155
  path = File.join(snake_name, f)
89
156
  gsub_file(path, /Sinatra::Application/, "#{camel_name}::App")
90
157
  end
91
158
  end
159
+ # rubocop:enable Metrics/AbcSize
160
+
161
+ def inline_views
162
+ return unless options[:tiny]
163
+ return if options[:api_only]
164
+
165
+ combined_views = %w[layout index].map { |f|
166
+ "@@#{f}\n" + File.read("#{snake_name}/views/#{f}.erb")
167
+ }.join("\n")
168
+
169
+ append_to_file("#{snake_name}/app.rb", "\n__END__\n\n#{combined_views}")
170
+ remove_dir("#{snake_name}/views")
171
+ end
92
172
 
93
173
  def create_git_repository
94
174
  return unless options[:git]
95
- if system("git --version >#{NULL} 2>&1")
96
- copy_file("templates/gitignore", "#{snake_name}/.gitignore")
175
+
176
+ if git?
177
+ copy_file('templates/gitignore', "#{snake_name}/.gitignore")
97
178
  inside snake_name do
98
- run("git init .")
99
- run("git add .")
100
- run("git commit -m \"Initial commit.\"")
179
+ run('git init .')
180
+ run('git add .')
181
+ run('git commit -m "Initial commit."')
101
182
  end
102
183
  else
103
- say "\nYou asked that a Git repository be created for the project, but no Git executable could be found."
184
+ say "\nYou asked that a Git repository be created for the " \
185
+ 'project, but no Git executable could be found.'
104
186
  end
105
187
  end
106
188
 
107
189
  def directions
108
- say "\nSuccessfully created #{name}. Don't forget to `bundle install`"
190
+ say "\nSuccessfully created #{name}."
191
+ end
192
+
193
+ def self.exit_on_failure?
194
+ true
109
195
  end
110
196
 
111
197
  private
@@ -115,19 +201,33 @@ module Hoboken
115
201
  end
116
202
 
117
203
  def camel_name
118
- Thor::Util.camel_case(name)
204
+ Thor::Util.camel_case(name.split('/').last)
119
205
  end
120
206
 
121
207
  def titleized_name
122
- snake_name.split("_").map(&:capitalize).join(" ")
208
+ snake_name.split('_').map(&:capitalize).join(' ')
123
209
  end
124
210
 
125
211
  def author
126
- `git config user.name`.chomp
212
+ if git?
213
+ `git config user.name`.chomp
214
+ else
215
+ say "\nNo Git executable found. Using result of `whoami` as author name."
216
+ `whoami`.chomp
217
+ end
218
+ end
219
+
220
+ def git?
221
+ system("git --version >#{NULL} 2>&1")
127
222
  end
128
223
 
129
224
  def apply_template(src, dest)
130
225
  template("templates/#{src}", "#{snake_name}/#{dest}")
131
226
  end
227
+
228
+ def ruby_three_one_or_greater?
229
+ Gem::Version.new(RUBY_VERSION).release >= Gem::Version.new('3.1')
230
+ end
132
231
  end
232
+ # rubocop:enable Metrics/ClassLength
133
233
  end