rails-interactive 1.0.0 → 2.1.1

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  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 +50 -0
  10. data/lib/cli/config/categories.yml +51 -0
  11. data/lib/cli/config/commands.yml +142 -0
  12. data/lib/cli/message.rb +55 -0
  13. data/lib/cli/prompt.rb +42 -0
  14. data/lib/cli/templates/setup_active_admin.rb +8 -0
  15. data/lib/cli/templates/setup_avo.rb +10 -0
  16. data/lib/cli/templates/setup_awesome_print.rb +4 -0
  17. data/lib/cli/templates/setup_better_errors.rb +8 -0
  18. data/lib/cli/templates/setup_brakeman.rb +6 -0
  19. data/lib/cli/templates/setup_bullet.rb +7 -0
  20. data/lib/cli/templates/setup_cancancan.rb +7 -0
  21. data/lib/cli/templates/setup_devise.rb +10 -0
  22. data/lib/cli/templates/setup_faker.rb +5 -0
  23. data/lib/cli/templates/setup_friendly_id.rb +5 -0
  24. data/lib/cli/templates/setup_graphql.rb +10 -0
  25. data/lib/cli/templates/setup_haml.rb +18 -0
  26. data/lib/cli/templates/setup_kaminari.rb +7 -0
  27. data/lib/cli/templates/setup_letter_opener.rb +15 -0
  28. data/lib/cli/templates/setup_omniauth.rb +61 -0
  29. data/lib/cli/templates/setup_pundit.rb +15 -0
  30. data/lib/cli/templates/setup_rails_admin.rb +10 -0
  31. data/lib/cli/templates/setup_rspec.rb +13 -0
  32. data/lib/cli/templates/setup_rubocop.rb +10 -0
  33. data/lib/cli/templates/setup_sassc_rails.rb +4 -0
  34. data/lib/cli/templates/setup_sidekiq.rb +32 -0
  35. data/lib/cli/templates/setup_slim.rb +19 -0
  36. data/lib/cli/templates/setup_standardrb.rb +10 -0
  37. data/lib/cli/utils.rb +38 -0
  38. data/lib/{rails_interactive → cli}/version.rb +3 -1
  39. data/lib/rails_interactive.rb +80 -32
  40. data/rails-interactive.gemspec +4 -2
  41. metadata +62 -5
  42. data/lib/rails_interactive/message.rb +0 -54
  43. data/lib/rails_interactive/prompt.rb +0 -40
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,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ run "bundle add activeadmin"
4
+ run "bundle add bcrypt"
5
+ Bundler.with_unbundled_env { run "bundle" }
6
+
7
+ rails_command "generate active_admin:install"
8
+ rails_command "db:migrate"
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ run "rails db:prepare"
4
+ run "bundle add avo"
5
+
6
+ Bundler.with_unbundled_env { run "bundle install" }
7
+
8
+ rails_command("generate avo:install")
9
+
10
+ puts "Avo is installed! You can go to http://localhost:3000/avo for next steps"
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ run 'bundle add awesome_print --group "development"'
4
+ Bundler.with_unbundled_env { run "bundle install" }
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ gem_group :development do
4
+ gem "better_errors"
5
+ gem "binding_of_caller"
6
+ end
7
+
8
+ Bundler.with_unbundled_env { run "bundle install" }
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ run 'bundle add brakeman --group "development"'
4
+ Bundler.with_unbundled_env { run "bundle install" }
5
+ run "bundle binstubs brakeman"
6
+ run "bin/brakeman"
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ run "bundle add bullet --group 'development'"
4
+
5
+ Bundler.with_unbundled_env { run "bundle install" }
6
+
7
+ run "bundle exec rails g bullet:install"
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ run "bundle add cancancan"
4
+
5
+ Bundler.with_unbundled_env { run "bundle install" }
6
+
7
+ rails_command "generate cancan:ability"
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ run "bundle add devise"
4
+ Bundler.with_unbundled_env { run "bundle install" }
5
+
6
+ rails_command "generate devise:install"
7
+
8
+ run "rails generate devise User"
9
+ run "rails db:prepare"
10
+ run "rails db:migrate"
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ run "bundle add faker --group 'development' 'test'"
4
+
5
+ Bundler.with_unbundled_env { run "bundle install" }
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ run "bundle add 'friendly_id'"
4
+
5
+ rails_command "generate friendly_id"
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ run "rails db:prepare"
4
+ run "bundle add graphql"
5
+
6
+ Bundler.with_unbundled_env { run "bundle install" }
7
+
8
+ rails_command("generate graphql:install")
9
+
10
+ puts "GraphQL is installed!"
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ def bundle_install
4
+ Bundler.with_unbundled_env { run "bundle install" }
5
+ end
6
+
7
+ run "bundle add haml"
8
+ bundle_install
9
+
10
+ if yes?("Would you like to convert your existing *.erb files to *.haml files? [y/n]")
11
+ run "bundle add erb2haml --group 'development'"
12
+ bundle_install
13
+ if yes?("Would you like to keep the original *.erb files? [y/n]")
14
+ rake "haml:convert_erbs"
15
+ else
16
+ rake "haml:replace_erbs"
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ run "bundle add kaminari"
4
+
5
+ Bundler.with_unbundled_env { run "bundle install" }
6
+
7
+ puts "Kaminari is installed!"
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ run 'bundle add letter_opener --group "development"'
4
+
5
+ Bundler.with_unbundled_env { run "bundle install" }
6
+
7
+ inject_into_file "config/environments/development.rb", after: "config.action_mailer.perform_caching = false\n" do
8
+ <<-RUBY
9
+
10
+ config.action_mailer.delivery_method = :letter_opener
11
+ config.action_mailer.perform_deliveries = true
12
+ RUBY
13
+ end
14
+
15
+ puts "Letter Opener is now installed!"
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ run "bundle add omniauth"
4
+
5
+ run "bundle install"
6
+
7
+ # rubocop:disable Layout/LineLength
8
+ rails_command "generate model identity user:references provider:string:index uid:string:index token:string:index refresh_token:string:index"
9
+ # rubocop:enable Layout/LineLength
10
+
11
+ rails_command "generate migration AddIdentityToUsers identities_count:integer"
12
+
13
+ rails_command "db:migrate"
14
+
15
+ inject_into_file "config/routes.rb", after: "devise_for :users\n" do
16
+ " # devise_for :users, controllers: { omniauth_callbacks: 'omniauth' }"
17
+ end
18
+
19
+ inject_into_file "app/models/user.rb", after: ":database_authenticatable, " do
20
+ ":omniauthable, "
21
+ end
22
+
23
+ inject_into_file "app/models/identity.rb", after: "belongs_to :user" do
24
+ ", counter_cache: true"
25
+ end
26
+
27
+ inject_into_file "app/models/user.rb", after: "class User < ApplicationRecord\n" do
28
+ # rubocop:disable Naming/HeredocDelimiterNaming
29
+ <<-EOF
30
+ has_many :identities, dependent: :destroy
31
+
32
+ def self.from_omniauth(auth)
33
+ if auth.present? && auth.provider.present? && auth.uid.present?
34
+ identity = Identity.where(provider: auth.provider, uid: auth.uid).first_or_initialize
35
+ if auth.credentials.present?
36
+ identity.token = auth.credentials.token
37
+ identity.refresh_token = auth.credentials.refresh_token
38
+ end
39
+ if identity.user.nil? && auth.info.email.present?
40
+ user = User.where(email: auth.info.email).first_or_initialize
41
+ user.name = auth.info.name
42
+ user.password = Devise.friendly_token if user.new_record?
43
+ user.save!
44
+ identity.user = user
45
+ end
46
+ identity.save!
47
+ identity.user
48
+ end
49
+ end
50
+
51
+ EOF
52
+ # rubocop:enable Naming/HeredocDelimiterNaming
53
+ end
54
+
55
+ file "app/controllers/omniauth_controller.rb", <<~CODE
56
+ class OmniauthController < Devise::OmniauthCallbacksController
57
+
58
+ end
59
+ CODE
60
+
61
+ puts "IMPORTANT: Add devise_for :users, controllers: { omniauth_callbacks: 'omniauth' } to your routes.rb"
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ run "bundle add pundit"
4
+
5
+ puts "Add - Pundit module to Application Controller"
6
+ puts ""
7
+
8
+ inject_into_file "app/controllers/application_controller.rb",
9
+ after: "class ApplicationController < ActionController::Base\n" do
10
+ " include Pundit\n"
11
+ end
12
+
13
+ puts "Run - Pundit Generator"
14
+
15
+ rails_command("generate pundit:install")
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ run "rails db:prepare"
4
+ run "bundle add rails_admin"
5
+
6
+ Bundler.with_unbundled_env { run "bundle install" }
7
+
8
+ rails_command("generate rails_admin:install")
9
+
10
+ puts "RailsAdmin is installed! You can go to your admin panel at /admin"
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ run "spring stop"
4
+
5
+ gem_group :development, :test do
6
+ gem "rspec-rails"
7
+ end
8
+
9
+ Bundler.with_unbundled_env { run "bundle install" }
10
+
11
+ rails_command "generate rspec:install"
12
+
13
+ puts "RSpec is installed!"
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ gem_group :development do
4
+ gem "rubocop", require: false
5
+ end
6
+
7
+ Bundler.with_unbundled_env { run "bundle install" }
8
+
9
+ run "rubocop --auto-gen-config"
10
+ run "bundle binstubs rubocop"
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ run "bundle add sassc-rails"
4
+ Bundler.with_unbundled_env { run "bundle" }
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ def file_contains?(filename, string)
4
+ File.foreach(filename).detect { |line| line.include?(string) }
5
+ end
6
+
7
+ run "bundle add sidekiq"
8
+ run "bundle add redis" unless file_contains? "Gemfile", "Gem 'redis'"
9
+
10
+ Bundler.with_unbundled_env { run "bundle install" }
11
+
12
+ # rubocop:disable Naming/HeredocDelimiterNaming
13
+ application do
14
+ <<~EOF
15
+ config.active_job.queue_adapter = :sidekiq
16
+ EOF
17
+ end
18
+
19
+ inject_into_file "config/routes.rb" do
20
+ <<~EOF
21
+ require "sidekiq/web"
22
+ if Rails.env.production?
23
+ Sidekiq::Web.use Rack::Auth::Basic do |username, password|
24
+ ActiveSupport::SecurityUtils.secure_compare(::Digest::SHA256.hexdigest(username), ::Digest::SHA256.hexdigest(ENV["SIDEKIQ_USERNAME"])) &
25
+ ActiveSupport::SecurityUtils.secure_compare(::Digest::SHA256.hexdigest(password), ::Digest::SHA256.hexdigest(ENV["SIDEKIQ_PASSWORD"]))
26
+ end
27
+ end
28
+ EOF
29
+ end
30
+ # rubocop:enable Naming/HeredocDelimiterNaming
31
+
32
+ route 'mount Sidekiq::Web => "/sidekiq"'
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ def bundle_install
4
+ Bundler.with_unbundled_env { run "bundle install" }
5
+ end
6
+
7
+ run "bundle add slim-rails"
8
+
9
+ bundle_install
10
+
11
+ if yes?("Would you like to convert your existing *.erb files to *.slim files? [y/n]")
12
+ run "bundle add html2slim --group 'development'"
13
+ bundle_install
14
+ if yes?("Would you like to keep the original *.erb files? [y/n]")
15
+ run "erb2slim app/views"
16
+ else
17
+ run "erb2slim app/views -d"
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ gem_group :development, :test do
4
+ gem "standard"
5
+ end
6
+
7
+ Bundler.with_unbundled_env { run "bundle install" }
8
+
9
+ puts "You can then run Standard from the command line with:"
10
+ puts "bundle exec standardrb"
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 = "1.0.0"
4
+ class CLI
5
+ VERSION = "2.1.1"
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,67 +29,109 @@ 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
- css_frameworks
31
46
 
32
- create
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)
51
+
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
56
+
57
+ create_project
33
58
  end
34
59
 
35
- def create
60
+ def setup
61
+ base = "rails new"
62
+ cmd = ""
63
+
64
+ @inputs.first(3).each { |_key, value| cmd += "#{value} " unless value.empty? }
65
+
66
+ "#{base} #{cmd} -q"
67
+ end
68
+
69
+ def create_project
36
70
  # Install gems
37
71
  system("bin/setup")
38
-
39
72
  # Create project
40
73
  system(setup)
41
-
74
+ # Install gems
75
+ intall_gems
42
76
  # Prepare project requirements and give instructions
43
- Dir.chdir "./#{@inputs[:name]}"
44
- system("rails db:create")
45
-
46
- sign_project
77
+ Utils.sign_project
47
78
  Message.prepare
48
79
  end
49
80
 
50
- def setup
51
- base = "rails new"
52
- cmd = ""
81
+ def create_command_list(commands, category_type)
82
+ return nil if commands.nil? || category_type.nil?
83
+
84
+ list = category_type == "select" ? {} : []
53
85
 
54
- @inputs.each { |_key, value| cmd += "#{value} " }
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
55
94
 
56
- "#{base} #{cmd}".strip!
95
+ list
57
96
  end
58
97
 
59
- private
98
+ def intall_gems
99
+ # Copy template files to project folder
100
+ Utils.copy_templates_to_project(@inputs[:name])
101
+
102
+ @inputs.each do |key, value|
103
+ next if %i[name type database].include?(key) || value.is_a?(Array) && value.empty? || value.nil?
104
+
105
+ dependencies = @commands.dependencies(value)
106
+
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
110
+
111
+ # Remove templates folder from project folder
112
+ Utils.remove_templates(@inputs[:name])
113
+ end
60
114
 
61
115
  def name
62
- @inputs[:name] = Prompt.new("Enter the name of the project: ", "ask", required: true).perform
116
+ @inputs[:name] = Prompt.new("Project name: ", "ask", required: true).perform
63
117
  end
64
118
 
65
119
  def type
66
- types = { "App" => "", "API" => "--api" }
67
- @inputs[:type] = Prompt.new("Choose project type: ", "select", types, required: true).perform
120
+ types = { "App" => "", "Api" => "--api" }
121
+ @inputs[:type] = Prompt.new("Type: ", "select", types, required: true).perform
68
122
  end
69
123
 
70
124
  def database
71
125
  database_types = { "PostgreSQL" => "-d postgresql", "MySQL" => "-d mysql", "SQLite" => "" }
72
126
 
73
- @inputs[:database] = Prompt.new("Choose project's database: ", "select", database_types, required: true).perform
127
+ @inputs[:database] = Prompt.new("Database: ", "select", database_types, required: true).perform
74
128
  end
75
129
 
76
- def css_frameworks
77
- css_frameworks = { "None" => "", "Bootstrap" => "--css=bootstrap", "Tailwind" => "--css=tailwind" }
78
-
79
- @inputs[:css_framework] =
80
- Prompt.new("Choose project's CSS framework: ", "select", css_frameworks, required: true).perform
81
- end
130
+ def admin_panel
131
+ admin_panel = { "ActiveAdmin" => "active_admin" }
82
132
 
83
- def sign_project
84
- file = "README.md"
85
- msg = "\n> This project was generated by [Rails Interactive CLI](https://github.com/oguzsh/rails-interactive)"
86
- File.write(file, msg, mode: "a+")
133
+ @inputs[:admin_panel] =
134
+ Prompt.new("Choose project admin panel: ", "select", admin_panel).perform
87
135
  end
88
136
  end
89
137
  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