Skip to content

Commit 8677a26

Browse files
committed
Add debug gem for development and implement scaffold generator tests
1 parent c4ab22e commit 8677a26

File tree

8 files changed

+231
-175
lines changed

8 files changed

+231
-175
lines changed

Gemfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,7 @@ gem "minitest", "~> 5.0"
99
gem "rake", "~> 13.0"
1010
gem "rubocop", "~> 1.21"
1111
gem "tty-prompt", "~> 0.23.1"
12+
13+
group :development do
14+
gem "debug", platforms: %i[mri windows], require: "debug/prelude"
15+
end

Gemfile.lock

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ GEM
9090
connection_pool (2.4.1)
9191
crass (1.0.6)
9292
date (3.3.4)
93+
debug (1.8.0)
94+
irb (>= 1.5.0)
95+
reline (>= 0.3.1)
9396
drb (2.2.0)
9497
ruby2_keywords
9598
erubi (1.12.0)
@@ -228,6 +231,7 @@ PLATFORMS
228231
x86_64-linux
229232

230233
DEPENDENCIES
234+
debug
231235
minitest (~> 5.0)
232236
next_rails_scaffold!
233237
rake (~> 13.0)
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# frozen_string_literal: true
2+
3+
require "open3"
4+
require "tty-prompt"
5+
6+
module NextRailsScaffold
7+
module Generators
8+
NodePackageManagerStruct = Struct.new(:fetch, :run, :add, :lock_file, :version) do
9+
def to_s = run.split.first
10+
11+
def available?
12+
version.present?
13+
end
14+
15+
def version
16+
@version ||= NodePackageManager.get_version(to_s)
17+
end
18+
end
19+
20+
NODE_REQUIRED_VERSION = ENV.fetch("NODE_REQUIRED_VERSION", ">= 18.20")
21+
NEXT_VERSION = ENV.fetch("NEXT_VERSION", "15.1.6")
22+
23+
PACKAGE_MANAGERS = {
24+
"npm" => NodePackageManagerStruct.new("npx", "npm run", "npm install", "package-lock.json"),
25+
"yarn" => NodePackageManagerStruct.new("npx", "yarn", "yarn add", "yarn.lock"),
26+
"pnpm" => NodePackageManagerStruct.new("pnpm dlx", "pnpm", "pnpm add", "pnpm-lock.yaml"),
27+
"bun" => NodePackageManagerStruct.new("bunx", "bun run", "bun add", "bun.lock.json")
28+
}.freeze
29+
30+
class NodePackageManager
31+
attr_reader :selected_package_manager
32+
33+
def self.get_version(command)
34+
Open3.capture3(command, "--version").first.gsub(/[^0-9.]/, "")
35+
rescue Errno::ENOENT
36+
nil
37+
end
38+
39+
def initialize(shell)
40+
@prompt = TTY::Prompt.new
41+
@shell = shell
42+
end
43+
44+
def check_node!
45+
node_version = self.class.get_version("node")
46+
47+
return if Gem::Dependency.new("", NODE_REQUIRED_VERSION).match?("", node_version)
48+
49+
raise node_version ? "Your Node version is '#{node_version}'" : "Node not found"
50+
end
51+
52+
def check_pm_version!
53+
package_manager = @shell.base.options[:package_manager]
54+
55+
unless package_manager
56+
PACKAGE_MANAGERS.each do |manager, details|
57+
if File.exist?(details.lock_file)
58+
package_manager = manager
59+
break
60+
end
61+
end
62+
end
63+
64+
until PACKAGE_MANAGERS.keys.include?(package_manager)
65+
raise "Invalid package manager" unless package_manager.nil?
66+
67+
package_manager = @prompt.select(
68+
"Which package manager do you want to use?",
69+
PACKAGE_MANAGERS.keys.map { |pm| { name: pm, value: pm, disabled: !PACKAGE_MANAGERS[pm].available? } }
70+
)
71+
end
72+
73+
@selected_package_manager = PACKAGE_MANAGERS[package_manager]
74+
end
75+
76+
def create_next_app!
77+
return if File.exist?("package.json")
78+
79+
system(
80+
"#{selected_package_manager.fetch} create-next-app@#{NEXT_VERSION} . --use-#{selected_package_manager} " \
81+
"--no-app --src-dir --import-alias \"@/*\" #{Rails.env.test? ? "--yes" : ""}"
82+
)
83+
84+
if selected_package_manager.to_s == "yarn" &&
85+
Gem::Dependency.new("", ">= 2.0").match?("", selected_package_manager.version)
86+
system("yarn config set nodeLinker node-modules")
87+
end
88+
end
89+
90+
def install_hygen!
91+
return if Dir.exist?("_templates")
92+
93+
system("#{selected_package_manager.add} -D hygen hygen-add")
94+
system("#{selected_package_manager.fetch} hygen-add next-rails-scaffold")
95+
end
96+
end
97+
end
98+
end
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# frozen_string_literal: true
2+
3+
require "rails/generators/rails/scaffold/scaffold_generator"
4+
require_relative "node_package_manager"
5+
6+
module NextRailsScaffold
7+
module Generators
8+
class ScaffoldGenerator < Rails::Generators::ScaffoldGenerator
9+
include ::NextRailsScaffold::Actions
10+
11+
source_root File.expand_path("templates", __dir__)
12+
13+
argument :attributes, type: :array, default: [], banner: "field:type field:type"
14+
class_option :package_manager, type: :string, desc: "Package manager to use for frontend project"
15+
class_option :skip_build, type: :boolean, default: false, desc: "Skip running Next.js build"
16+
class_option :skip_routes, type: :boolean, default: false, desc: "Skip adding resources to routes.rb"
17+
18+
attr_accessor :selected_package_manager
19+
20+
def initialize(args, *options) # :nodoc:
21+
super
22+
self.attributes = shell.base.attributes
23+
end
24+
25+
def add_resource_route
26+
return if options[:actions].present? || options[:skip_routes]
27+
28+
route "resources :#{file_name.pluralize}", namespace: regular_class_path, scope: "/api"
29+
end
30+
31+
def create_root_folder
32+
empty_directory "frontend"
33+
end
34+
35+
# Check Javascript dependencies and create a new Next.js project. Install the the useful packages and create the
36+
# scaffold code for frontend application.
37+
def create_frontend_project
38+
return say_status :remove, "skip frontend folder", :yellow if shell.base.behavior == :revoke
39+
40+
append_gitignore!
41+
42+
node_package_manager = NodePackageManager.new(shell)
43+
44+
inside("frontend") do
45+
node_package_manager.check_node!
46+
node_package_manager.check_pm_version!
47+
node_package_manager.create_next_app!
48+
node_package_manager.install_hygen!
49+
50+
return if Rails.env.test?
51+
52+
selected_package_manager = node_package_manager.selected_package_manager
53+
language = File.exist?("tsconfig.json") ? "typescript" : "javascript"
54+
55+
run("#{selected_package_manager.fetch} hygen scaffold #{language} #{name} #{mapped_attributes.join(" ")}")
56+
if !options[:skip_build] && !@prompt.no?("Do you want to build your Next.js project?")
57+
run("#{selected_package_manager.run} build")
58+
end
59+
end
60+
end
61+
62+
private
63+
64+
def append_gitignore!
65+
path = File.join(destination_root, ".gitignore")
66+
67+
return unless File.exist?(path)
68+
69+
rows = <<~HEREDOC
70+
71+
# Ignoring node modules for Rails and Next.js projects
72+
node_modules/
73+
HEREDOC
74+
75+
append_to_file path, rows
76+
end
77+
78+
def mapped_attributes
79+
attributes.map { |attr| "#{attr.name}:#{attr.type}" }
80+
end
81+
end
82+
end
83+
end

lib/generators/rails/next_rails_scaffold/next_rails_scaffold_generator.rb

Lines changed: 0 additions & 158 deletions
This file was deleted.

0 commit comments

Comments
 (0)