rails-interactive 0.1.9 → 2.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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +57 -57
  3. data/.rubocop.yml +9 -0
  4. data/Gemfile.lock +77 -72
  5. data/README.md +1 -1
  6. data/bin/console +2 -9
  7. data/lib/cli/category.rb +18 -0
  8. data/lib/cli/command.rb +29 -0
  9. data/lib/cli/command_handler.rb +32 -0
  10. data/lib/cli/config/categories.yml +51 -0
  11. data/lib/cli/config/commands.yml +128 -0
  12. data/lib/cli/message.rb +55 -0
  13. data/lib/cli/prompt.rb +42 -0
  14. data/lib/{rails_interactive → cli}/templates/setup_avo.rb +0 -0
  15. data/lib/{rails_interactive → cli}/templates/setup_awesome_print.rb +0 -0
  16. data/lib/{rails_interactive → cli}/templates/setup_better_errors.rb +0 -0
  17. data/lib/{rails_interactive → cli}/templates/setup_brakeman.rb +0 -0
  18. data/lib/{rails_interactive → cli}/templates/setup_bullet.rb +0 -0
  19. data/lib/{rails_interactive → cli}/templates/setup_cancancan.rb +0 -0
  20. data/lib/{rails_interactive → cli}/templates/setup_devise.rb +0 -0
  21. data/lib/{rails_interactive → cli}/templates/setup_faker.rb +0 -0
  22. data/lib/cli/templates/setup_friendly_id.rb +5 -0
  23. data/lib/{rails_interactive → cli}/templates/setup_graphql.rb +0 -0
  24. data/lib/{rails_interactive → cli}/templates/setup_haml.rb +0 -0
  25. data/lib/{rails_interactive → cli}/templates/setup_kaminari.rb +0 -0
  26. data/lib/{rails_interactive → cli}/templates/setup_letter_opener.rb +0 -0
  27. data/lib/{rails_interactive → cli}/templates/setup_omniauth.rb +0 -0
  28. data/lib/{rails_interactive → cli}/templates/setup_pundit.rb +0 -0
  29. data/lib/{rails_interactive → cli}/templates/setup_rails_admin.rb +0 -0
  30. data/lib/{rails_interactive → cli}/templates/setup_rspec.rb +0 -0
  31. data/lib/{rails_interactive → cli}/templates/setup_rubocop.rb +0 -0
  32. data/lib/{rails_interactive → cli}/templates/setup_sidekiq.rb +0 -0
  33. data/lib/{rails_interactive → cli}/templates/setup_slim.rb +0 -0
  34. data/lib/{rails_interactive → cli}/templates/setup_standardrb.rb +0 -0
  35. data/lib/cli/utils.rb +38 -0
  36. data/lib/{rails_interactive → cli}/version.rb +3 -1
  37. data/lib/rails_interactive.rb +71 -100
  38. data/rails-interactive.gemspec +4 -2
  39. metadata +60 -26
  40. data/lib/rails_interactive/message.rb +0 -52
  41. data/lib/rails_interactive/prompt.rb +0 -40
  42. data/lib/rails_interactive/templates/setup_friendly_id.rb +0 -26
@@ -0,0 +1,128 @@
1
+ ---
2
+ -
3
+ identifier: rubocop
4
+ name: Rubocop
5
+ category: code_quality
6
+ description: "A Ruby static code analyzer and formatter, based on the community Ruby style guide. For details: https://github.com/rubocop/rubocop"
7
+ dependencies: null
8
+ -
9
+ identifier: graphql
10
+ name: GraphQL
11
+ category: features
12
+ description: "Ruby implementation of GraphQL. For details: https://github.com/rmosolgo/graphql-ruby"
13
+ dependencies: null
14
+ -
15
+ identifier: avo
16
+ name: Avo
17
+ category: admin_panel
18
+ description: "Configuration-based, no-maintenance, extendable Ruby on Rails admin. For details: https://github.com/avo-hq/avo"
19
+ dependencies: null
20
+ -
21
+ identifier: awesome_print
22
+ name: AwesomePrint
23
+ category: development
24
+ description: "Pretty print your Ruby objects with style. For details: https://github.com/awesome-print/awesome_print"
25
+ dependencies: null
26
+ -
27
+ identifier: better_errors
28
+ name: BetterErrors
29
+ category: development
30
+ description: "Better error page for Rack apps. For details: https://github.com/BetterErrors/better_errors"
31
+ dependencies: null
32
+ -
33
+ identifier: brakeman
34
+ name: Brakeman
35
+ category: security
36
+ description: "A static analysis security vulnerability scanner for Ruby on Rails applications. For details: https://github.com/presidentbeef/brakeman"
37
+ dependencies: null
38
+ -
39
+ identifier: bullet
40
+ name: Bullet
41
+ category: development
42
+ description: "Bullet helps to solve N+1 queries and unused eager loading. For details: https://github.com/flyerhzm/bullet"
43
+ dependencies: null
44
+ -
45
+ identifier: cancancan
46
+ name: CanCanCan
47
+ category: authorization
48
+ description: "CanCanCan is an authorization library for Ruby and Ruby on Rails which restricts what resources a given user is allowed to access. For details: https://github.com/CanCanCommunity/cancancan"
49
+ dependencies: null
50
+ -
51
+ identifier: devise
52
+ name: Devise
53
+ category: authentication
54
+ description: "Flexible authentication solution for Rails with Warden. For details: https://github.com/heartcombo/devise"
55
+ dependencies: null
56
+ -
57
+ identifier: faker
58
+ name: Faker
59
+ category: development
60
+ description: "A library for generating fake data such as names, addresses, and phone numbers. For details: https://github.com/faker-ruby/faker"
61
+ dependencies: null
62
+ -
63
+ identifier: friendly_id
64
+ name: FriendlyID
65
+ category: development
66
+ description: "FriendlyId is the 'Swiss Army bulldozer' of slugging and permalink plugins for Active Record. It lets you create pretty URLs and work with human-friendly strings as if they were numeric ids. For details: https://github.com/norman/friendly_id"
67
+ dependencies: null
68
+ -
69
+ identifier: haml
70
+ name: Haml
71
+ category: template_engine
72
+ description: "HTML Abstraction Markup Language. For details: https://github.com/haml/haml"
73
+ dependencies: null
74
+ -
75
+ identifier: kaminari
76
+ name: Kaminari
77
+ category: features
78
+ description: "A Scope & Engine based, clean, powerful, customizable and sophisticated paginator for Ruby webapps. For details: https://github.com/kaminari/kaminari"
79
+ dependencies: null
80
+ -
81
+ identifier: letter_opener
82
+ name: LetterOpener
83
+ category: development
84
+ description: "Preview email in the default browser instead of sending it on development mode. For details: https://github.com/ryanb/letter_opener"
85
+ dependencies: null
86
+ -
87
+ identifier: omniauth
88
+ name: OmniAuth
89
+ category: authentication
90
+ description: "OmniAuth is a flexible authentication system utilizing Rack middleware. For details: https://github.com/omniauth/omniauth"
91
+ dependencies:
92
+ - devise
93
+ -
94
+ identifier: pundit
95
+ name: Pundit
96
+ category: authorization
97
+ description: "Minimal authorization through OO design and pure Ruby classes. For details: https://github.com/varvet/pundit"
98
+ dependencies: null
99
+ -
100
+ identifier: rails_admin
101
+ name: RailsAdmin
102
+ category: admin_panel
103
+ description: "RailsAdmin is a Rails engine that provides an easy-to-use interface for managing your data. For details: https://github.com/railsadminteam/rails_admin"
104
+ dependencies: null
105
+ -
106
+ identifier: rspec
107
+ name: RSpec
108
+ category: testing
109
+ description: "A unit test framework for the Ruby programming language. For details: https://github.com/rspec"
110
+ dependencies: null
111
+ -
112
+ identifier: sidekiq
113
+ name: Sidekiq
114
+ category: background_job
115
+ description: "Simple, efficient background processing for Ruby. For details: https://github.com/mperham/sidekiq"
116
+ dependencies: null
117
+ -
118
+ identifier: slim
119
+ name: Slim
120
+ category: template_engine
121
+ description: "Slim is a template language whose goal is to reduce the syntax to the essential parts without becoming cryptic. For details: https://github.com/slim-template/slim"
122
+ dependencies: null
123
+ -
124
+ identifier: standart_rb
125
+ name: StandartRB
126
+ category: code_quality
127
+ description: " Ruby Style Guide, with linter & automatic code fixer. For details: https://github.com/testdouble/standard"
128
+ dependencies: null
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "colorize"
4
+
5
+ module RailsInteractive
6
+ class CLI
7
+ # Utils class for the interactive CLI module
8
+ class Message
9
+ def self.greet
10
+ render_ascii
11
+ puts "Welcome to Rails Interactive CLI".colorize(:yellow)
12
+ end
13
+
14
+ def self.help
15
+ puts "bin/interactive new - Create a new Rails Project".colorize(:yellow)
16
+ puts "bin/interactive help - List all commands".colorize(:yellow)
17
+ exit
18
+ end
19
+
20
+ def self.render_ascii
21
+ # rubocop:disable Naming/HeredocDelimiterNaming
22
+ puts <<-'EOF'
23
+ _____ _ _ _____ _ _ _
24
+ | __ \ (_) | |_ _| | | | | (_)
25
+ | |__) |__ _ _| |___ | | _ __ | |_ ___ _ __ __ _ ___| |_ ___ _____
26
+ | _ // _` | | / __| | | | '_ \| __/ _ \ '__/ _` |/ __| __| \ \ / / _ \
27
+ | | \ \ (_| | | \__ \_| |_| | | | || __/ | | (_| | (__| |_| |\ V / __/
28
+ |_| \_\__,_|_|_|___/_____|_| |_|\__\___|_| \__,_|\___|\__|_| \_/ \___|
29
+
30
+ EOF
31
+ # rubocop:enable Naming/HeredocDelimiterNaming
32
+ end
33
+
34
+ def self.prepare
35
+ puts ""
36
+ puts "Project created successfully ✅".colorize(:green)
37
+ puts "Go to your project folder and ready to go 🎉".colorize(:green)
38
+ rails_commands
39
+ end
40
+
41
+ def self.rails_commands
42
+ puts "You can run several commands:".colorize(:green)
43
+
44
+ puts "Starts the webpack development server".colorize(:cyan)
45
+ puts "> bin/webpack-dev-server".colorize(:yellow)
46
+
47
+ puts "Starts the rails server".colorize(:cyan)
48
+ puts "> bin/rails s or bin/rails server".colorize(:yellow)
49
+
50
+ puts "Starts the rails console".colorize(:cyan)
51
+ puts "> bin/rails c or bin/rails console".colorize(:yellow)
52
+ end
53
+ end
54
+ end
55
+ end
data/lib/cli/prompt.rb ADDED
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tty/prompt"
4
+
5
+ module RailsInteractive
6
+ class CLI
7
+ # Prompt class for commands
8
+ class Prompt
9
+ # Create a new instance
10
+ #
11
+ # @param msg [String] the message to display
12
+ # @param type [String] the type of prompt
13
+ # @param options [Array] the options to display
14
+ # @param required [Boolean] whether the prompt value is required
15
+ #
16
+ # @return [Interactive::Prompt] the new instance
17
+ def initialize(msg, type, options = nil, required: false)
18
+ @msg = msg
19
+ @type = type
20
+ @options = options
21
+ @required = required
22
+ @prompt = TTY::Prompt.new
23
+ end
24
+
25
+ # Perform the prompt
26
+ #
27
+ # @return [String] the value of the prompt
28
+ def perform
29
+ case @type
30
+ when "ask"
31
+ @prompt.ask(@msg, required: @required)
32
+ when "select"
33
+ @prompt.select(@msg, @options, required: @required)
34
+ when "multi_select"
35
+ @prompt.multi_select(@msg, @options)
36
+ else
37
+ puts "Invalid parameter"
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ run "bundle add 'friendly_id'"
4
+
5
+ rails_command "generate friendly_id"
data/lib/cli/utils.rb ADDED
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fileutils"
4
+
5
+ module RailsInteractive
6
+ class CLI
7
+ class Utils
8
+ def self.humanize(value)
9
+ return nil if value.nil?
10
+
11
+ value
12
+ .gsub(/^[\s_]+|[\s_]+$/, "")
13
+ .gsub(/[_\s]+/, " ")
14
+ .gsub(/^[a-z]/, &:upcase)
15
+ end
16
+
17
+ def self.remove_templates(_project_name)
18
+ FileUtils.rm_rf("templates")
19
+ end
20
+
21
+ def self.go_to_project_directory(project_name)
22
+ Dir.chdir "./#{project_name}"
23
+ end
24
+
25
+ def self.copy_templates_to_project(project_name)
26
+ FileUtils.cp_r "#{__dir__}/templates", "./#{project_name}"
27
+
28
+ go_to_project_directory(project_name)
29
+ end
30
+
31
+ def self.sign_project
32
+ file = "README.md"
33
+ msg = "\n> This project was generated by [Rails Interactive CLI](https://github.com/oguzsh/rails-interactive)"
34
+ File.write(file, msg, mode: "a+")
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsInteractive
4
- VERSION = "0.1.9"
4
+ class CLI
5
+ VERSION = "2.1.0"
6
+ end
5
7
  end
@@ -1,14 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "rails_interactive/prompt"
4
- require "rails_interactive/message"
5
- require "fileutils"
3
+ require "cli/prompt"
4
+ require "cli/message"
5
+ require "cli/command"
6
+ require "cli/category"
7
+ require "cli/utils"
8
+ require "cli/command_handler"
6
9
 
7
10
  module RailsInteractive
8
11
  # CLI class for the interactive CLI module
9
12
  class CLI
10
13
  def initialize
11
14
  @inputs = {}
15
+ @commands = Command.new
16
+ @categories = Category.new
17
+ @handler = CommandHandler.new
12
18
  end
13
19
 
14
20
  def perform(key)
@@ -23,137 +29,102 @@ module RailsInteractive
23
29
  end
24
30
  end
25
31
 
32
+ private
33
+
34
+ def categories_with_commands
35
+ @categories.all.each do |category|
36
+ commands = []
37
+ @commands.all.each { |command| commands << command if command["category"] == category["name"] }
38
+ category["commands"] = commands
39
+ end
40
+ end
41
+
26
42
  def initialize_project
27
43
  name
28
44
  type
29
45
  database
30
- features
31
- code_quality_tool
32
- template_engines
33
- admin_panel
34
- testing_tools
35
- development_tools
36
-
37
- create
38
- end
39
-
40
- # rubocop:disable Metrics/MethodLength
41
- def create
42
- # Install gems
43
- system("bin/setup")
44
- # Create project
45
- system(setup)
46
-
47
- copy_templates_to_project
48
-
49
- # Move to project folder and install gems
50
- Dir.chdir "./#{@inputs[:name]}"
51
46
 
52
- # Features Templates
53
- handle_multi_options(key: :features)
47
+ categories_with_commands.each do |category|
48
+ category_name = category["name"]
49
+ category_type = category["type"]
50
+ category_command_list = create_command_list(category["commands"], category_type)
54
51
 
55
- # Code Quality Template
56
- system("bin/rails app:template LOCATION=templates/setup_#{@inputs[:code_quality_tool]}.rb")
57
-
58
- # HTML Template Engines
59
- system("bin/rails app:template LOCATION=templates/setup_#{@inputs[:template_engine]}.rb")
60
-
61
- # Admin Panel Template
62
- system("bin/rails app:template LOCATION=templates/setup_#{@inputs[:admin_panel]}.rb")
63
-
64
- # Testing tools Template
65
- handle_multi_options(key: :testing_tools)
66
-
67
- # Development tools Template
68
- handle_multi_options(key: :development_tools)
52
+ @inputs[category_name.to_sym] =
53
+ Prompt.new("Choose #{Utils.humanize(category_name)} gems: ", category_type.to_s,
54
+ category_command_list).perform
55
+ end
69
56
 
70
- # Prepare project requirements and give instructions
71
- sign_project
72
- Message.prepare
57
+ create_project
73
58
  end
74
- # rubocop:enable Metrics/MethodLength
75
59
 
76
60
  def setup
77
61
  base = "rails new"
78
62
  cmd = ""
79
63
 
80
- @inputs.first(3).each { |_key, value| cmd += "#{value} " }
64
+ @inputs.first(3).each { |_key, value| cmd += "#{value} " unless value.empty? }
81
65
 
82
- "#{base} #{cmd}".strip!
66
+ "#{base} #{cmd} -q"
83
67
  end
84
68
 
85
- def copy_templates_to_project
86
- FileUtils.cp_r "#{__dir__}/rails_interactive/templates", "./#{@inputs[:name]}"
87
- end
88
-
89
- private
90
-
91
- def handle_multi_options(key:)
92
- @inputs[key].each do |value|
93
- system("bin/rails app:template LOCATION=templates/setup_#{value}.rb")
94
- end
69
+ def create_project
70
+ # Install gems
71
+ system("bin/setup")
72
+ # Create project
73
+ system(setup)
74
+ # Install gems
75
+ intall_gems
76
+ # Prepare project requirements and give instructions
77
+ Utils.sign_project
78
+ Message.prepare
95
79
  end
96
80
 
97
- def name
98
- @inputs[:name] = Prompt.new("Enter the name of the project: ", "ask", required: true).perform
99
- end
81
+ def create_command_list(commands, category_type)
82
+ return nil if commands.nil? || category_type.nil?
100
83
 
101
- def type
102
- types = { "App" => "", "API" => "--api" }
103
- @inputs[:type] = Prompt.new("Choose project type: ", "select", types, required: true).perform
104
- end
84
+ list = category_type == "select" ? {} : []
105
85
 
106
- def database
107
- database_types = { "PostgreSQL" => "-d postgresql", "MySQL" => "-d mysql", "SQLite" => "" }
86
+ commands.each do |command|
87
+ if list.is_a?(Hash)
88
+ list["None"] = nil
89
+ list[command["name"]] = command["identifier"]
90
+ else
91
+ list << command["identifier"]
92
+ end
93
+ end
108
94
 
109
- @inputs[:database] = Prompt.new("Choose project's database: ", "select", database_types, required: true).perform
95
+ list
110
96
  end
111
97
 
112
- def features
113
- features = %w[devise cancancan omniauth pundit brakeman sidekiq graphql kaminari]
98
+ def intall_gems
99
+ # Copy template files to project folder
100
+ Utils.copy_templates_to_project(@inputs[:name])
114
101
 
115
- @inputs[:features] = Prompt.new("Choose project features: ", "multi_select", features).perform
116
- end
117
-
118
- def code_quality_tool
119
- code_quality_tool = { "Rubocop" => "rubocop", "StandardRB" => "standardrb" }
102
+ @inputs.each do |key, value|
103
+ next if %i[name type database].include?(key) || value.is_a?(Array) && value.empty? || value.nil?
120
104
 
121
- @inputs[:code_quality_tool] =
122
- Prompt.new("Choose project code quality tool: ", "select", code_quality_tool).perform
123
- end
105
+ dependencies = @commands.dependencies(value)
124
106
 
125
- def admin_panel
126
- admin_panel = { "RailsAdmin" => "rails_admin", "Avo" => "avo" }
107
+ @handler.handle_multi_options(value, dependencies) if value.is_a?(Array)
108
+ @handler.handle_option(value, dependencies) if value.is_a?(String)
109
+ end
127
110
 
128
- @inputs[:admin_panel] =
129
- Prompt.new("Choose project's admin panel: ", "select", admin_panel).perform
111
+ # Remove templates folder from project folder
112
+ Utils.remove_templates(@inputs[:name])
130
113
  end
131
114
 
132
- def testing_tools
133
- testing_tools = %w[rspec]
134
-
135
- @inputs[:testing_tools] =
136
- Prompt.new("Choose project's testing tools: ", "multi_select", testing_tools).perform
115
+ def name
116
+ @inputs[:name] = Prompt.new("Project name: ", "ask", required: true).perform
137
117
  end
138
118
 
139
- def template_engines
140
- template_engines = { "HAML" => "haml", "SLIM" => "slim" }
141
-
142
- @inputs[:template_engine] =
143
- Prompt.new("Choose project's template engine: ", "select", template_engines).perform
119
+ def type
120
+ types = { "App" => "", "Api" => "--api" }
121
+ @inputs[:type] = Prompt.new("Type: ", "select", types, required: true).perform
144
122
  end
145
123
 
146
- def development_tools
147
- development_tools = %w[bullet faker friendly_id better_errors letter_opener awesome_print]
148
-
149
- @inputs[:development_tools] =
150
- Prompt.new("Choose project's development tools: ", "multi_select", development_tools).perform
151
- end
124
+ def database
125
+ database_types = { "PostgreSQL" => "-d postgresql", "MySQL" => "-d mysql", "SQLite" => "" }
152
126
 
153
- def sign_project
154
- file = "README.md"
155
- msg = "\n> This project was generated by [Rails Interactive CLI](https://github.com/oguzsh/rails-interactive)"
156
- File.write(file, msg, mode: "a+")
127
+ @inputs[:database] = Prompt.new("Database: ", "select", database_types, required: true).perform
157
128
  end
158
129
  end
159
130
  end
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "lib/rails_interactive/version"
3
+ require_relative "lib/cli/version"
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "rails-interactive"
7
- spec.version = RailsInteractive::VERSION
7
+ spec.version = RailsInteractive::CLI::VERSION
8
8
  spec.authors = ["Oguzhan Ince"]
9
9
  spec.email = ["oguzhan824@gmail.com"]
10
10
 
@@ -29,9 +29,11 @@ Gem::Specification.new do |spec|
29
29
  spec.add_development_dependency "bundler"
30
30
  spec.add_development_dependency "byebug", "~> 11.1.2"
31
31
  spec.add_development_dependency "colorize"
32
+ spec.add_development_dependency "pry"
32
33
  spec.add_development_dependency "rake"
33
34
  spec.add_development_dependency "rspec"
34
35
  spec.add_development_dependency "rubocop"
36
+ spec.add_development_dependency "yaml"
35
37
 
36
38
  spec.add_dependency "tty-prompt"
37
39