rails-new-app 0.0.3 → 0.1.0

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/tests.yml +28 -0
  3. data/.gitignore +2 -0
  4. data/Gemfile +14 -0
  5. data/Gemfile.lock +60 -0
  6. data/README.md +60 -20
  7. data/Rakefile +9 -0
  8. data/lib/rails-new-app.rb +1 -1
  9. data/lib/rails-new-app/processors/authentication_processor.rb +16 -0
  10. data/lib/rails-new-app/processors/authorization_processor.rb +18 -0
  11. data/lib/rails-new-app/runner.rb +97 -146
  12. data/lib/rails-new-app/screens.rb +8 -0
  13. data/lib/rails-new-app/screens/app_name_screen.rb +28 -0
  14. data/lib/rails-new-app/screens/auth_screen.rb +26 -0
  15. data/lib/rails-new-app/screens/authentication_screen.rb +27 -0
  16. data/lib/rails-new-app/screens/authorization_screen.rb +27 -0
  17. data/lib/rails-new-app/screens/choice_screen.rb +52 -0
  18. data/lib/rails-new-app/{steps/code_coverage_step.rb → screens/code_coverage_screen.rb} +3 -3
  19. data/lib/rails-new-app/{steps/database_step.rb → screens/database_screen.rb} +7 -5
  20. data/lib/rails-new-app/{steps/form_builder_step.rb → screens/form_builder_screen.rb} +2 -2
  21. data/lib/rails-new-app/{steps/java_script_framework_step.rb → screens/java_script_framework_screen.rb} +2 -2
  22. data/lib/rails-new-app/screens/menu_screen.rb +61 -0
  23. data/lib/rails-new-app/{steps/pagination_step.rb → screens/pagination_screen.rb} +2 -2
  24. data/lib/rails-new-app/screens/review_and_confirm_screen.rb +59 -0
  25. data/lib/rails-new-app/{steps/ruby_linter_step.rb → screens/ruby_linter_screen.rb} +2 -2
  26. data/lib/rails-new-app/screens/screen.rb +66 -0
  27. data/lib/rails-new-app/{steps/template_engine_step.rb → screens/template_engine_screen.rb} +2 -2
  28. data/lib/rails-new-app/{steps/test_factory_step.rb → screens/test_factory_screen.rb} +3 -3
  29. data/lib/rails-new-app/{steps/test_fake_data.rb → screens/test_fake_data_screen.rb} +3 -3
  30. data/lib/rails-new-app/{steps/test_runner_step.rb → screens/test_runner_screen.rb} +3 -3
  31. data/lib/rails-new-app/{steps/yes_no_choice_step.rb → screens/yes_no_choice_screen.rb} +1 -1
  32. data/lib/rails-new-app/templates/cancancan-config.rb +1 -0
  33. data/lib/rails-new-app/templates/cancancan-gemfile.rb +1 -0
  34. data/lib/rails-new-app/templates/devise-config.rb +1 -0
  35. data/lib/rails-new-app/templates/devise-gemfile.rb +1 -0
  36. data/lib/rails-new-app/templates/pagy-config.rb +1 -1
  37. data/lib/rails-new-app/templates/pundit-config.rb +7 -0
  38. data/lib/rails-new-app/templates/pundit-gemfile.rb +1 -0
  39. data/lib/rails-new-app/version.rb +1 -1
  40. metadata +34 -18
  41. data/lib/rails-new-app/steps.rb +0 -7
  42. data/lib/rails-new-app/steps/app_name_step.rb +0 -20
  43. data/lib/rails-new-app/steps/choice_step.rb +0 -45
  44. data/lib/rails-new-app/steps/rails_version_step.rb +0 -34
  45. data/lib/rails-new-app/steps/step.rb +0 -75
@@ -0,0 +1,8 @@
1
+ # require generic screens first
2
+ path = File.expand_path("../screens", __FILE__)
3
+ require "#{path}/screen"
4
+ require "#{path}/choice_screen"
5
+ require "#{path}/yes_no_choice_screen"
6
+ require "#{path}/menu_screen"
7
+ # require the rest
8
+ Dir.glob("#{path}/*").sort.each { |f| require f }
@@ -0,0 +1,28 @@
1
+ module RailsNewApp
2
+ class AppNameScreen < Screen
3
+ def screen_text
4
+ [].tap do |ls|
5
+ ls << "The selected name is invalid." if @error
6
+ ls << "Type the name of the app:"
7
+ end.join("\n")
8
+ end
9
+
10
+ def after_valid
11
+ puts "Your app is: #{@input}\n"
12
+ end
13
+
14
+ def valid?(input)
15
+ if /\A[a-z_]+\z/i.match?(input.strip)
16
+ @error = false
17
+ true
18
+ else
19
+ @error = true
20
+ false
21
+ end
22
+ end
23
+
24
+ def next_step
25
+ @input != "" ? :menu : :rerender
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,26 @@
1
+ module RailsNewApp
2
+ class AuthScreen < ChoiceScreen
3
+ def options
4
+ ["Authentication", "Authorization"]
5
+ end
6
+
7
+ def step_question
8
+ "Type the option to go to a submenu:"
9
+ end
10
+
11
+ def return_value
12
+ nil
13
+ end
14
+
15
+ def self.default
16
+ {}
17
+ end
18
+
19
+ def next_step
20
+ case @input
21
+ when 1 then :authentication
22
+ when 2 then :authorization
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,27 @@
1
+ module RailsNewApp
2
+ class AuthenticationScreen < ChoiceScreen
3
+ def step_question
4
+ "Type the option number of the Authentication gem to use:"
5
+ end
6
+
7
+ def options
8
+ ["None", "Devise"]
9
+ end
10
+
11
+ def lowercase_keys
12
+ ["", "devise"]
13
+ end
14
+
15
+ def after_valid
16
+ puts "Selected authentication gem is: #{option}\n"
17
+ end
18
+
19
+ def self.default
20
+ {
21
+ option_number: 1,
22
+ name: "None",
23
+ key: ""
24
+ }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ module RailsNewApp
2
+ class AuthorizationScreen < ChoiceScreen
3
+ def step_question
4
+ "Type the option number of the Authorization gem to use:"
5
+ end
6
+
7
+ def options
8
+ ["None", "Pundit", "Can Can Can"]
9
+ end
10
+
11
+ def lowercase_keys
12
+ ["", "pundit", "cancancan"]
13
+ end
14
+
15
+ def after_valid
16
+ puts "Selected authorization gem is: #{option}\n"
17
+ end
18
+
19
+ def self.default
20
+ {
21
+ option_number: 1,
22
+ name: "None",
23
+ key: ""
24
+ }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,52 @@
1
+ module RailsNewApp
2
+ class ChoiceScreen < Screen
3
+ def options
4
+ []
5
+ end
6
+
7
+ def option
8
+ options[@input - 1]
9
+ end
10
+
11
+ def screen_text
12
+ [].tap do |ls|
13
+ ls << @error if @error
14
+ ls << step_question
15
+ ls << ""
16
+
17
+ current = config[self.class.key] ? config[self.class.key][:option_number] : nil
18
+ options.each_with_index do |op, idx|
19
+ aux = idx + 1
20
+ is_current = aux == current ? " (current)" : ""
21
+ ls << "#{aux} ) #{op}#{is_current}"
22
+ end
23
+ ls << ""
24
+ ls << "0 ) Back to menu"
25
+ end.join("\n")
26
+ end
27
+
28
+ def clean_input(input)
29
+ input.to_i
30
+ end
31
+
32
+ def valid?(input)
33
+ if options[input - 1]
34
+ @error = false
35
+ true
36
+ else
37
+ @error = "Invalid option, choose again:"
38
+ false
39
+ end
40
+ end
41
+
42
+ def return_value
43
+ lower = lowercase_keys[@input - 1]
44
+
45
+ {
46
+ option_number: @input,
47
+ name: option,
48
+ key: lower
49
+ }
50
+ end
51
+ end
52
+ end
@@ -1,5 +1,5 @@
1
1
  module RailsNewApp
2
- class CodeCoverageStep < ChoiceStep
2
+ class CodeCoverageScreen < ChoiceScreen
3
3
  def step_question
4
4
  warning =
5
5
  if config[:test_runner][:key] == ""
@@ -24,8 +24,8 @@ module RailsNewApp
24
24
 
25
25
  def self.default
26
26
  {
27
- option_number: 0,
28
- name: "None (Default)",
27
+ option_number: 1,
28
+ name: "None",
29
29
  key: ""
30
30
  }
31
31
  end
@@ -1,15 +1,15 @@
1
1
  module RailsNewApp
2
- class DatabaseStep < ChoiceStep
2
+ class DatabaseScreen < ChoiceScreen
3
3
  def rails_new_options
4
4
  %W[mysql postgresql sqlite3 oracle sqlserver jdbcmysql jdbcsqlite3 jdbcpostgresql jdbc]
5
5
  end
6
6
 
7
7
  def options
8
- ["None", "SQLite", "MySQL / MariaDB", "PostgreSQL"]
8
+ ["SQLite", "MySQL / MariaDB", "PostgreSQL"]
9
9
  end
10
10
 
11
11
  def lowercase_keys
12
- ["", "sqlite3", "mysql", "postgresql"]
12
+ ["sqlite3", "mysql", "postgresql"]
13
13
  end
14
14
 
15
15
  def step_question
@@ -23,15 +23,17 @@ module RailsNewApp
23
23
  def return_value
24
24
  super.tap do |h|
25
25
  h[:in_rails_new] = rails_new_options.include?(h[:key])
26
+ h[:is_default] = h[:key] == :sqlite3
26
27
  end
27
28
  end
28
29
 
29
30
  def self.default
30
31
  {
31
- option_number: "1",
32
+ option_number: 1,
32
33
  name: "SQLite",
33
34
  key: "sqlite3",
34
- in_rails_new: true
35
+ in_rails_new: true,
36
+ is_default: true
35
37
  }
36
38
  end
37
39
  end
@@ -1,5 +1,5 @@
1
1
  module RailsNewApp
2
- class FormBuilderStep < ChoiceStep
2
+ class FormBuilderScreen < ChoiceScreen
3
3
  def step_question
4
4
  "Type the option number of the Form Builder gem to use:"
5
5
  end
@@ -18,7 +18,7 @@ module RailsNewApp
18
18
 
19
19
  def self.default
20
20
  {
21
- option_number: 0,
21
+ option_number: 1,
22
22
  name: "None",
23
23
  key: ""
24
24
  }
@@ -1,5 +1,5 @@
1
1
  module RailsNewApp
2
- class JavaScriptFrameworkStep < ChoiceStep
2
+ class JavaScriptFrameworkScreen < ChoiceScreen
3
3
  def rails_new_options
4
4
  %W[react vue angular elm stimulus]
5
5
  end
@@ -28,7 +28,7 @@ module RailsNewApp
28
28
 
29
29
  def self.default
30
30
  {
31
- option_number: 0,
31
+ option_number: 1,
32
32
  name: "None",
33
33
  key: "",
34
34
  in_rails_new: false
@@ -0,0 +1,61 @@
1
+ module RailsNewApp
2
+ class MenuScreen < Screen
3
+ def initialize(screens)
4
+ @screens = screens
5
+ @current_page = 1
6
+ end
7
+
8
+ def get_screen(option)
9
+ SCREENS.find { |x| x[:option] == option.to_s && x[:page] == @current_page }
10
+ end
11
+
12
+ def screen_text
13
+ [].tap do |ls|
14
+ @screens.each do |s|
15
+ next if s[:option].nil?
16
+ next if s[:page] != @current_page
17
+
18
+ screen_name = s[:class].clean_name
19
+ ls << "#{s[:option]} : #{screen_name}"
20
+ end
21
+ ls << ""
22
+ ls << "n : Next menu" if @current_page == 1
23
+ ls << "p : Previous menu" if @current_page == 2
24
+ ls << "0 : Review and confirm"
25
+ ls << ""
26
+ ls << "Type the number of the menu and press enter:"
27
+ end.join("\n")
28
+ end
29
+
30
+ def valid?(input)
31
+ case input
32
+ when "0" then true
33
+ when "n" then @current_page == 1
34
+ when "p" then @current_page == 2
35
+ when /\A\d\z/ then get_screen(input)
36
+ else false
37
+ end
38
+ end
39
+
40
+ def go_to_next_page
41
+ @current_page += 1
42
+ end
43
+
44
+ def go_to_previous_page
45
+ @current_page -= 1
46
+ end
47
+
48
+ def next_step
49
+ case @input
50
+ when "0" then :review_and_confirm
51
+ when "n"
52
+ go_to_next_page
53
+ :rerender
54
+ when "p"
55
+ go_to_previous_page
56
+ :rerender
57
+ else get_screen(@input)[:class].key
58
+ end
59
+ end
60
+ end
61
+ end
@@ -1,5 +1,5 @@
1
1
  module RailsNewApp
2
- class PaginationStep < ChoiceStep
2
+ class PaginationScreen < ChoiceScreen
3
3
  def step_question
4
4
  "Type the option number of the Pagination gem to use:"
5
5
  end
@@ -18,7 +18,7 @@ module RailsNewApp
18
18
 
19
19
  def self.default
20
20
  {
21
- option_number: 0,
21
+ option_number: 1,
22
22
  name: "None",
23
23
  key: ""
24
24
  }
@@ -0,0 +1,59 @@
1
+ module RailsNewApp
2
+ class ReviewAndConfirmScreen < Screen
3
+ def screen_text
4
+ [].tap do |ls|
5
+ ls << <<~REVIEW
6
+ ===== New Rails app config =====
7
+
8
+ App name: #{config[:app_name]}
9
+ Ruby version: #{RUBY_VERSION}
10
+ Database: #{config[:database]}
11
+ Test runner: #{config[:test_runner]}
12
+ Code coverage: #{config[:code_coverage]}
13
+ Test factories: #{config[:test_factory]}
14
+ Test fake data: #{config[:test_fake_data]}
15
+ JS framework: #{config[:java_script_framework]}
16
+ Ruby Linter: #{config[:ruby_linter]}
17
+ Template engine: #{config[:template_engine]}
18
+ Form builder: #{config[:form_builder]}
19
+ Pagination: #{config[:pagination]}
20
+ Authorization: #{config[:authorization]}
21
+ Authentication: #{config[:authentication]}
22
+
23
+ REVIEW
24
+
25
+ message = "Type 'Y(es)' to confirm, 'B(ack) to go back, or 'N(o)' to abort"
26
+ if config[:app_name] == ""
27
+ ls << <<~WARNING
28
+ =====================================
29
+ App name is required
30
+ =====================================
31
+
32
+ WARNING
33
+ message.gsub!("Type 'Y(es)' to confirm, ", "Type ")
34
+ end
35
+
36
+ ls << message
37
+ end
38
+ end
39
+
40
+ def valid?(input)
41
+ if /\A*Y(es)?\z|\A*B(ack)?\z|\A*N(o)?\z/i.match?(input)
42
+ @error = false
43
+ true
44
+ else
45
+ @error = "Invalid option"
46
+ false
47
+ end
48
+ end
49
+
50
+ def next_step
51
+ case @input
52
+ when /\A*B(ack)?\z/i then :menu
53
+ when /\A*Y(es)?\z/i then :finish
54
+ when /\A*N(o)?\z/i then :abort
55
+ else :rerender
56
+ end
57
+ end
58
+ end
59
+ end
@@ -1,5 +1,5 @@
1
1
  module RailsNewApp
2
- class RubyLinterStep < ChoiceStep
2
+ class RubyLinterScreen < ChoiceScreen
3
3
  def step_question
4
4
  "Type the option number of the Ruby Linter gem to use:"
5
5
  end
@@ -18,7 +18,7 @@ module RailsNewApp
18
18
 
19
19
  def self.default
20
20
  {
21
- option_number: 0,
21
+ option_number: 1,
22
22
  name: "None",
23
23
  key: ""
24
24
  }
@@ -0,0 +1,66 @@
1
+ module RailsNewApp
2
+ class Screen
3
+ attr_reader :config
4
+
5
+ def initialize(config)
6
+ @config = config
7
+ @input = ""
8
+ end
9
+
10
+ def self.clean_name
11
+ to_s.gsub("Screen", "").gsub("RailsNewApp::", "")
12
+ end
13
+
14
+ def self.key
15
+ clean_name.underscore.to_sym
16
+ end
17
+
18
+ def screen_text
19
+ raise "screen text must be re-defined"
20
+ end
21
+
22
+ def process_user_input(input)
23
+ if validate_user_input(input)
24
+ [next_step, return_value]
25
+ else
26
+ [:rerender, nil]
27
+ end
28
+ end
29
+
30
+ def validate_user_input(input)
31
+ input = clean_input(input)
32
+ if valid?(input)
33
+ @input = input
34
+ true
35
+ end
36
+ end
37
+
38
+ # clean the input if needed before validations
39
+ def clean_input(input)
40
+ input.strip
41
+ end
42
+
43
+ # validate the input
44
+ def valid?(input)
45
+ @error = false
46
+ true
47
+ end
48
+
49
+ # after valid message
50
+ def after_valid
51
+ end
52
+
53
+ # process @input to return a different value
54
+ def return_value
55
+ @input
56
+ end
57
+
58
+ def self.default
59
+ ""
60
+ end
61
+
62
+ def next_step
63
+ :menu
64
+ end
65
+ end
66
+ end