rails-new-app 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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