railsforge 1.0.2 → 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.
- checksums.yaml +4 -4
- data/README.md +129 -435
- data/lib/railsforge/analyzers/controller_analyzer.rb +29 -55
- data/lib/railsforge/analyzers/database_analyzer.rb +16 -30
- data/lib/railsforge/analyzers/metrics_analyzer.rb +8 -22
- data/lib/railsforge/analyzers/model_analyzer.rb +29 -46
- data/lib/railsforge/analyzers/performance_analyzer.rb +34 -94
- data/lib/railsforge/analyzers/refactor_analyzer.rb +77 -57
- data/lib/railsforge/analyzers/security_analyzer.rb +34 -91
- data/lib/railsforge/analyzers/spec_analyzer.rb +17 -31
- data/lib/railsforge/cli.rb +28 -645
- data/lib/railsforge/cli_minimal.rb +10 -55
- data/lib/railsforge/diff.rb +57 -0
- data/lib/railsforge/doctor.rb +52 -225
- data/lib/railsforge/formatter.rb +128 -0
- data/lib/railsforge/issue.rb +23 -0
- data/lib/railsforge/loader.rb +5 -64
- data/lib/railsforge/version.rb +1 -1
- metadata +15 -82
- data/lib/railsforge/api_generator.rb +0 -397
- data/lib/railsforge/audit.rb +0 -289
- data/lib/railsforge/config.rb +0 -181
- data/lib/railsforge/database_analyzer.rb +0 -300
- data/lib/railsforge/feature_generator.rb +0 -560
- data/lib/railsforge/generator.rb +0 -313
- data/lib/railsforge/generators/api_generator.rb +0 -392
- data/lib/railsforge/generators/base_generator.rb +0 -75
- data/lib/railsforge/generators/demo_generator.rb +0 -307
- data/lib/railsforge/generators/devops_generator.rb +0 -287
- data/lib/railsforge/generators/form_generator.rb +0 -180
- data/lib/railsforge/generators/job_generator.rb +0 -176
- data/lib/railsforge/generators/monitoring_generator.rb +0 -134
- data/lib/railsforge/generators/policy_generator.rb +0 -220
- data/lib/railsforge/generators/presenter_generator.rb +0 -173
- data/lib/railsforge/generators/query_generator.rb +0 -174
- data/lib/railsforge/generators/serializer_generator.rb +0 -166
- data/lib/railsforge/generators/service_generator.rb +0 -122
- data/lib/railsforge/generators/stimulus_controller_generator.rb +0 -129
- data/lib/railsforge/generators/test_generator.rb +0 -289
- data/lib/railsforge/generators/view_component_generator.rb +0 -169
- data/lib/railsforge/graph.rb +0 -270
- data/lib/railsforge/mailer_generator.rb +0 -191
- data/lib/railsforge/plugins/plugin_loader.rb +0 -60
- data/lib/railsforge/plugins.rb +0 -30
- data/lib/railsforge/profiles.rb +0 -99
- data/lib/railsforge/refactor_analyzer.rb +0 -401
- data/lib/railsforge/refactor_controller.rb +0 -277
- data/lib/railsforge/refactors/refactor_controller.rb +0 -117
- data/lib/railsforge/template_loader.rb +0 -105
- data/lib/railsforge/templates/v1/form/spec_template.rb +0 -18
- data/lib/railsforge/templates/v1/form/template.rb +0 -28
- data/lib/railsforge/templates/v1/job/spec_template.rb +0 -17
- data/lib/railsforge/templates/v1/job/template.rb +0 -13
- data/lib/railsforge/templates/v1/policy/spec_template.rb +0 -41
- data/lib/railsforge/templates/v1/policy/template.rb +0 -57
- data/lib/railsforge/templates/v1/presenter/spec_template.rb +0 -12
- data/lib/railsforge/templates/v1/presenter/template.rb +0 -13
- data/lib/railsforge/templates/v1/query/spec_template.rb +0 -12
- data/lib/railsforge/templates/v1/query/template.rb +0 -16
- data/lib/railsforge/templates/v1/serializer/spec_template.rb +0 -13
- data/lib/railsforge/templates/v1/serializer/template.rb +0 -11
- data/lib/railsforge/templates/v1/service/spec_template.rb +0 -12
- data/lib/railsforge/templates/v1/service/template.rb +0 -25
- data/lib/railsforge/templates/v1/stimulus_controller/template.rb +0 -35
- data/lib/railsforge/templates/v1/view_component/template.rb +0 -24
- data/lib/railsforge/templates/v2/job/template.rb +0 -49
- data/lib/railsforge/templates/v2/query/template.rb +0 -66
- data/lib/railsforge/templates/v2/service/spec_template.rb +0 -33
- data/lib/railsforge/templates/v2/service/template.rb +0 -71
- data/lib/railsforge/templates/v3/job/template.rb +0 -72
- data/lib/railsforge/templates/v3/query/spec_template.rb +0 -54
- data/lib/railsforge/templates/v3/query/template.rb +0 -115
- data/lib/railsforge/templates/v3/service/spec_template.rb +0 -51
- data/lib/railsforge/templates/v3/service/template.rb +0 -93
- data/lib/railsforge/wizard.rb +0 -265
- data/lib/railsforge/wizard_tui.rb +0 -286
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
# RefactorController module for RailsForge
|
|
2
|
-
# Automatically refactors fat controllers by extracting service objects
|
|
3
|
-
|
|
4
|
-
require 'fileutils'
|
|
5
|
-
|
|
6
|
-
module RailsForge
|
|
7
|
-
module Refactors
|
|
8
|
-
# RefactorController class extracts services from fat controller methods
|
|
9
|
-
class RefactorController
|
|
10
|
-
MIN_METHOD_LINES = 15
|
|
11
|
-
|
|
12
|
-
def initialize(base_path = nil)
|
|
13
|
-
@base_path = base_path || find_rails_app_path
|
|
14
|
-
raise RefactorControllerError, "Not in a Rails application" unless @base_path
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# Refactor a specific controller
|
|
18
|
-
def refactor(controller_name)
|
|
19
|
-
controller_file = find_controller_file(controller_name)
|
|
20
|
-
raise RefactorControllerError, "Controller not found" unless controller_file
|
|
21
|
-
|
|
22
|
-
content = File.read(controller_file)
|
|
23
|
-
long_methods = find_long_methods(content)
|
|
24
|
-
|
|
25
|
-
if long_methods.empty?
|
|
26
|
-
puts "No methods to extract"
|
|
27
|
-
return { extracted: [] }
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
puts "Found #{long_methods.count} method(s) to extract"
|
|
31
|
-
|
|
32
|
-
extracted = []
|
|
33
|
-
long_methods.each do |method|
|
|
34
|
-
service = extract_to_service(controller_name, method)
|
|
35
|
-
extracted << service if service
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
{ extracted: extracted }
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
private
|
|
42
|
-
|
|
43
|
-
def find_rails_app_path
|
|
44
|
-
path = Dir.pwd
|
|
45
|
-
10.times do
|
|
46
|
-
return path if File.exist?(File.join(path, "config", "application.rb"))
|
|
47
|
-
parent = File.dirname(path)
|
|
48
|
-
break if parent == path
|
|
49
|
-
path = parent
|
|
50
|
-
end
|
|
51
|
-
nil
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def find_controller_file(name)
|
|
55
|
-
dir = File.join(@base_path, "app", "controllers")
|
|
56
|
-
return nil unless Dir.exist?(dir)
|
|
57
|
-
|
|
58
|
-
Dir.glob(File.join(dir, "**", "*_controller.rb")).find do |f|
|
|
59
|
-
File.basename(f).include?(name.underscore)
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def find_long_methods(content)
|
|
64
|
-
methods = []
|
|
65
|
-
lines = content.lines
|
|
66
|
-
in_method = false
|
|
67
|
-
method_lines = []
|
|
68
|
-
method_name = nil
|
|
69
|
-
|
|
70
|
-
lines.each_with_index do |line, i|
|
|
71
|
-
if line =~ /\bdef\s+(\w+)/
|
|
72
|
-
methods << { name: method_name, lines: method_lines.count } if in_method
|
|
73
|
-
in_method = true
|
|
74
|
-
method_name = $1
|
|
75
|
-
method_lines = [line]
|
|
76
|
-
elsif in_method
|
|
77
|
-
method_lines << line
|
|
78
|
-
if line.strip == "end" && method_lines.count > 1
|
|
79
|
-
methods << { name: method_name, lines: method_lines.count, content: method_lines.join }
|
|
80
|
-
in_method = false
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
methods.select { |m| m[:lines] >= MIN_METHOD_LINES }
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def extract_to_service(controller_name, method_info)
|
|
89
|
-
service_dir = File.join(@base_path, "app", "services", controller_name.underscore)
|
|
90
|
-
FileUtils.mkdir_p(service_dir)
|
|
91
|
-
|
|
92
|
-
service_name = "#{method_info[:name]}_service"
|
|
93
|
-
service_path = File.join(service_dir, "#{service_name}.rb")
|
|
94
|
-
|
|
95
|
-
return nil if File.exist?(service_path)
|
|
96
|
-
|
|
97
|
-
File.write(service_path, <<~RUBY)
|
|
98
|
-
# Extracted from controller: #{controller_name}
|
|
99
|
-
class #{controller_name}#{method_info[:name].capitalize}Service
|
|
100
|
-
def initialize(params = {})
|
|
101
|
-
@params = params
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def call
|
|
105
|
-
# TODO: Implement extracted logic
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
RUBY
|
|
109
|
-
|
|
110
|
-
puts " Created app/services/#{controller_name.underscore}/#{service_name}.rb"
|
|
111
|
-
{ name: service_name }
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
class RefactorControllerError < StandardError; end
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
end
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
# TemplateLoader module handles loading template versions
|
|
2
|
-
require 'fileutils'
|
|
3
|
-
|
|
4
|
-
module RailsForge
|
|
5
|
-
# Template module for managing generator templates
|
|
6
|
-
module Template
|
|
7
|
-
# Error class for template loading issues
|
|
8
|
-
class TemplateError < StandardError; end
|
|
9
|
-
|
|
10
|
-
# Template directory path
|
|
11
|
-
TEMPLATES_DIR = File.expand_path('../templates', __FILE__)
|
|
12
|
-
|
|
13
|
-
# Default template version
|
|
14
|
-
DEFAULT_VERSION = "v1"
|
|
15
|
-
|
|
16
|
-
# Get available template versions
|
|
17
|
-
# @return [Array<String>] Array of version names
|
|
18
|
-
def self.available_versions
|
|
19
|
-
return [] unless Dir.exist?(TEMPLATES_DIR)
|
|
20
|
-
|
|
21
|
-
Dir.glob(File.join(TEMPLATES_DIR, 'v*')).map do |dir|
|
|
22
|
-
File.basename(dir)
|
|
23
|
-
end.sort
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# Load template for a specific generator and version
|
|
27
|
-
# @param generator_type [String] Type of generator (service, query, etc.)
|
|
28
|
-
# @param version [String] Template version (e.g., "v1")
|
|
29
|
-
# @return [Hash] Template configuration
|
|
30
|
-
def self.load_template(generator_type, version = DEFAULT_VERSION)
|
|
31
|
-
template_path = File.join(TEMPLATES_DIR, version, generator_type, "template.rb")
|
|
32
|
-
|
|
33
|
-
unless File.exist?(template_path)
|
|
34
|
-
raise TemplateError, "Template not found for #{generator_type} version #{version}"
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
{
|
|
38
|
-
template_path: template_path,
|
|
39
|
-
version: version,
|
|
40
|
-
generator_type: generator_type
|
|
41
|
-
}
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# Get template content
|
|
45
|
-
# @param generator_type [String] Type of generator
|
|
46
|
-
# @param version [String] Template version
|
|
47
|
-
# @return [String] Template content
|
|
48
|
-
def self.get_content(generator_type, version = DEFAULT_VERSION)
|
|
49
|
-
template_info = load_template(generator_type, version)
|
|
50
|
-
File.read(template_info[:template_path])
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
# Check if template exists
|
|
54
|
-
# @param generator_type [String] Type of generator
|
|
55
|
-
# @param version [String] Template version
|
|
56
|
-
# @return [Boolean] True if template exists
|
|
57
|
-
def self.exists?(generator_type, version = DEFAULT_VERSION)
|
|
58
|
-
template_path = File.join(TEMPLATES_DIR, version, generator_type, "template.rb")
|
|
59
|
-
File.exist?(template_path)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
# List templates in a version
|
|
63
|
-
# @param version [String] Template version
|
|
64
|
-
# @return [Array<String>] List of generator types
|
|
65
|
-
def self.list_templates(version = DEFAULT_VERSION)
|
|
66
|
-
version_path = File.join(TEMPLATES_DIR, version)
|
|
67
|
-
return [] unless Dir.exist?(version_path)
|
|
68
|
-
|
|
69
|
-
Dir.glob(File.join(version_path, '*')).select do |dir|
|
|
70
|
-
File.directory?(dir)
|
|
71
|
-
end.map do |dir|
|
|
72
|
-
File.basename(dir)
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# Show available versions with their templates
|
|
77
|
-
# @return [String] Formatted list
|
|
78
|
-
def self.show_available
|
|
79
|
-
output = "Available template versions:\n\n"
|
|
80
|
-
|
|
81
|
-
available_versions.each do |version|
|
|
82
|
-
output += " #{version}:\n"
|
|
83
|
-
templates = list_templates(version)
|
|
84
|
-
templates.each do |template|
|
|
85
|
-
output += " - #{template}\n"
|
|
86
|
-
end
|
|
87
|
-
output += "\n"
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
output
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# Get spec template content
|
|
94
|
-
# @param generator_type [String] Type of generator
|
|
95
|
-
# @param version [String] Template version
|
|
96
|
-
# @return [String] Spec template content
|
|
97
|
-
def self.get_spec_content(generator_type, version = DEFAULT_VERSION)
|
|
98
|
-
spec_path = File.join(TEMPLATES_DIR, version, generator_type, "spec_template.rb")
|
|
99
|
-
|
|
100
|
-
return nil unless File.exist?(spec_path)
|
|
101
|
-
|
|
102
|
-
File.read(spec_path)
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
end
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
require 'rails_helper'
|
|
2
|
-
|
|
3
|
-
RSpec.describe <%= name.camelize %>Form do
|
|
4
|
-
let(:params) { {} }
|
|
5
|
-
subject { described_class.new(<%= name.underscore %>_params: params) }
|
|
6
|
-
|
|
7
|
-
describe '#valid?' do
|
|
8
|
-
it 'is valid with valid params' do
|
|
9
|
-
expect(subject.valid?).to be_truthy
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
describe '#save' do
|
|
14
|
-
it 'saves successfully' do
|
|
15
|
-
expect(subject.save).to be_truthy
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# Form class for <%= name %>
|
|
2
|
-
# Encapsulates form validation logic
|
|
3
|
-
#
|
|
4
|
-
# Usage:
|
|
5
|
-
# form = <%= name.camelize %>Form.new(params)
|
|
6
|
-
# if form.valid?
|
|
7
|
-
# form.save
|
|
8
|
-
# end
|
|
9
|
-
class <%= name.camelize %>Form
|
|
10
|
-
include ActiveModel::Model
|
|
11
|
-
|
|
12
|
-
attr_accessor <%= name.underscore %>_attributes
|
|
13
|
-
|
|
14
|
-
validate :validate_<%= name.underscore %>
|
|
15
|
-
|
|
16
|
-
def save
|
|
17
|
-
return false unless valid?
|
|
18
|
-
|
|
19
|
-
# TODO: Implement save logic
|
|
20
|
-
true
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
private
|
|
24
|
-
|
|
25
|
-
def validate_<%= name.underscore %>
|
|
26
|
-
# TODO: Add validations
|
|
27
|
-
end
|
|
28
|
-
end
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
require 'rails_helper'
|
|
2
|
-
|
|
3
|
-
RSpec.describe <%= name.camelize %>Job do
|
|
4
|
-
let(:args) { [] }
|
|
5
|
-
|
|
6
|
-
it 'enqueues the job' do
|
|
7
|
-
expect {
|
|
8
|
-
described_class.perform_later(*args)
|
|
9
|
-
}.to have_enqueued_job(described_class)
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
describe '#perform' do
|
|
13
|
-
it 'performs the job' do
|
|
14
|
-
expect { subject.perform(*args) }.not_to raise_error
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# Background job for <%= name %>
|
|
2
|
-
# Handles async processing
|
|
3
|
-
#
|
|
4
|
-
# Usage:
|
|
5
|
-
# <%= name.camelize %>Job.perform_later(record)
|
|
6
|
-
# <%= name.camelize %>Job.perform_now(record)
|
|
7
|
-
class <%= name.camelize %>Job < ApplicationJob
|
|
8
|
-
queue_as :default
|
|
9
|
-
|
|
10
|
-
def perform(*args)
|
|
11
|
-
# TODO: Implement job logic
|
|
12
|
-
end
|
|
13
|
-
end
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
require 'rails_helper'
|
|
2
|
-
|
|
3
|
-
RSpec.describe <%= name.camelize %>Policy do
|
|
4
|
-
let(:user) { nil }
|
|
5
|
-
let(:record) { <%= name.camelize %>.new }
|
|
6
|
-
subject { described_class.new(user, record) }
|
|
7
|
-
|
|
8
|
-
describe '#index?' do
|
|
9
|
-
it 'allows everyone' do
|
|
10
|
-
expect(subject.index?).to be_truthy
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
describe '#show?' do
|
|
15
|
-
it 'allows everyone' do
|
|
16
|
-
expect(subject.show?).to be_truthy
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
describe '#create?' do
|
|
21
|
-
it 'requires user' do
|
|
22
|
-
expect(subject.create?).to be_falsey
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
it 'allows authenticated user' do
|
|
26
|
-
user = User.new
|
|
27
|
-
expect(described_class.new(user, record).create?).to be_truthy
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
describe 'Scope' do
|
|
32
|
-
let(:scope) { <%= name.camelize %>.all }
|
|
33
|
-
subject { described_class::Scope.new(user, scope) }
|
|
34
|
-
|
|
35
|
-
describe '#resolve' do
|
|
36
|
-
it 'returns all records' do
|
|
37
|
-
expect(subject.resolve).to eq(scope.all)
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
# Policy class for <%= name %>
|
|
2
|
-
# Handles authorization logic
|
|
3
|
-
#
|
|
4
|
-
# Usage:
|
|
5
|
-
# authorize <%= name.underscore %>
|
|
6
|
-
# policy_scope(<%= name.underscore %>)
|
|
7
|
-
class <%= name.camelize %>Policy
|
|
8
|
-
attr_reader :user, :record
|
|
9
|
-
|
|
10
|
-
def initialize(user, record)
|
|
11
|
-
@user = user
|
|
12
|
-
@record = record
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def index?
|
|
16
|
-
true
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def show?
|
|
20
|
-
true
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def create?
|
|
24
|
-
user.present?
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def new?
|
|
28
|
-
create?
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def update?
|
|
32
|
-
user.present?
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def edit?
|
|
36
|
-
update?
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def destroy?
|
|
40
|
-
user.present?
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
class Scope
|
|
44
|
-
def initialize(user, scope)
|
|
45
|
-
@user = user
|
|
46
|
-
@scope = scope
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def resolve
|
|
50
|
-
scope.all
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
private
|
|
54
|
-
|
|
55
|
-
attr_reader :user, :scope
|
|
56
|
-
end
|
|
57
|
-
end
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
require 'rails_helper'
|
|
2
|
-
|
|
3
|
-
RSpec.describe <%= name.camelize %>Presenter do
|
|
4
|
-
let(:<%= name.underscore %>) { <%= name.camelize %>.new }
|
|
5
|
-
subject { described_class.new(<%= name.underscore %>) }
|
|
6
|
-
|
|
7
|
-
describe 'initialization' do
|
|
8
|
-
it 'initializes successfully' do
|
|
9
|
-
expect(subject).to be_a(described_class)
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
end
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# Presenter class for <%= name %>
|
|
2
|
-
# Handles view presentation logic
|
|
3
|
-
#
|
|
4
|
-
# Usage:
|
|
5
|
-
# presenter = <%= name.camelize %>Presenter.new(@<%= name.underscore %>)
|
|
6
|
-
# presenter.full_name
|
|
7
|
-
class <%= name.camelize %>Presenter
|
|
8
|
-
def initialize(<%= name.underscore %>)
|
|
9
|
-
@<%= name.underscore %> = <%= name.underscore %>
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
# TODO: Add presenter methods
|
|
13
|
-
end
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
require 'rails_helper'
|
|
2
|
-
|
|
3
|
-
RSpec.describe <%= name.camelize %>Query do
|
|
4
|
-
let(:scope) { <%= name.camelize %>.all }
|
|
5
|
-
subject { described_class.new(scope: scope) }
|
|
6
|
-
|
|
7
|
-
describe '#call' do
|
|
8
|
-
it 'returns scope' do
|
|
9
|
-
expect(subject.call).to eq(scope)
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
end
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# Query class for <%= name %>
|
|
2
|
-
# Encapsulates database queries
|
|
3
|
-
#
|
|
4
|
-
# Usage:
|
|
5
|
-
# result = <%= name.camelize %>Query.call
|
|
6
|
-
# result = <%= name.camelize %>Query.call(scope: User.active)
|
|
7
|
-
class <%= name.camelize %>Query
|
|
8
|
-
def initialize(scope: nil)
|
|
9
|
-
@scope = scope || <%= name.camelize %>.all
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def call
|
|
13
|
-
# TODO: Implement query logic
|
|
14
|
-
@scope
|
|
15
|
-
end
|
|
16
|
-
end
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
require 'rails_helper'
|
|
2
|
-
|
|
3
|
-
RSpec.describe <%= name.camelize %>Serializer do
|
|
4
|
-
let(:<%= name.underscore %>) { <%= name.camelize %>.new<% attributes.each do |attr| %>
|
|
5
|
-
<%= name.underscore %>.<%= attr %> = 'test'<% end %> }
|
|
6
|
-
subject { described_class.new(<%= name.underscore %>) }
|
|
7
|
-
|
|
8
|
-
describe 'serialization' do
|
|
9
|
-
it 'includes id' do
|
|
10
|
-
expect(subject.as_json[:id]).to eq(<%= name.underscore %>.id)
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
end
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# Serializer class for <%= name %>
|
|
2
|
-
# Handles JSON serialization
|
|
3
|
-
#
|
|
4
|
-
# Usage:
|
|
5
|
-
# render json: <%= name.camelize %>Serializer.new(<%= name.underscore %>)
|
|
6
|
-
class <%= name.camelize %>Serializer < ApplicationSerializer
|
|
7
|
-
attributes :id<% attributes.each do |attr| %>
|
|
8
|
-
:<%= attr %><% end %>
|
|
9
|
-
|
|
10
|
-
# TODO: Add custom methods
|
|
11
|
-
end
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# Service class for <%= name %>
|
|
2
|
-
# Encapsulates business logic
|
|
3
|
-
#
|
|
4
|
-
# Usage:
|
|
5
|
-
# result = <%= name.camelize %>Service.call(params)
|
|
6
|
-
#
|
|
7
|
-
# @example Basic service
|
|
8
|
-
# class CreateUserService
|
|
9
|
-
# def initialize(user_params)
|
|
10
|
-
# @user_params = user_params
|
|
11
|
-
# end
|
|
12
|
-
#
|
|
13
|
-
# def call
|
|
14
|
-
# User.create!(@user_params)
|
|
15
|
-
# end
|
|
16
|
-
# end
|
|
17
|
-
class <%= name.camelize %>Service
|
|
18
|
-
def initialize(<%= name.underscore %>_params = {})
|
|
19
|
-
@params = <%= name.underscore %>_params
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def call
|
|
23
|
-
# TODO: Implement service logic
|
|
24
|
-
end
|
|
25
|
-
end
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
// Stimulus controller: <%= class_name %>
|
|
2
|
-
import { Controller } from "@hotwired/stimulus"
|
|
3
|
-
|
|
4
|
-
export default class <%= class_name %> extends Controller {
|
|
5
|
-
// Define static targets
|
|
6
|
-
static targets = ["output", "input"]
|
|
7
|
-
|
|
8
|
-
// Connect lifecycle
|
|
9
|
-
connect() {
|
|
10
|
-
console.log("<%= class_name %> connected")
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// Disconnect lifecycle
|
|
14
|
-
disconnect() {
|
|
15
|
-
console.log("<%= class_name %> disconnected")
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Example action
|
|
19
|
-
// Usage: data-action="<%= underscore_name %>#greet"
|
|
20
|
-
greet() {
|
|
21
|
-
console.log("Hello from <%= class_name %>!")
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Example: Handle input changes
|
|
25
|
-
// Usage: data-action="input-><%= underscore_name %>#handleInput"
|
|
26
|
-
handleInput(event) {
|
|
27
|
-
const value = event.target.value
|
|
28
|
-
console.log("Input value:", value)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Example: Toggle visibility
|
|
32
|
-
toggle() {
|
|
33
|
-
this.outputTarget.classList.toggle("hidden")
|
|
34
|
-
}
|
|
35
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# ViewComponent template for <%= class_name %>
|
|
2
|
-
class <%= class_name %> < ViewComponent::Base
|
|
3
|
-
# Define component properties
|
|
4
|
-
# renders_maybe :some_child
|
|
5
|
-
|
|
6
|
-
# Initialize with data
|
|
7
|
-
# @param title [String] Component title
|
|
8
|
-
def initialize(title: "", classes: "")
|
|
9
|
-
@title = title
|
|
10
|
-
@classes = classes
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
# Check if title is present
|
|
14
|
-
# @return [Boolean]
|
|
15
|
-
def title?
|
|
16
|
-
@title.present?
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# CSS classes for the component
|
|
20
|
-
# @return [String]
|
|
21
|
-
def classes
|
|
22
|
-
"component #{@classes}"
|
|
23
|
-
end
|
|
24
|
-
end
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# Job template v2
|
|
2
|
-
# Enhanced job with error handling and callbacks
|
|
3
|
-
class <%= class_name %> < ApplicationJob
|
|
4
|
-
# Configure queue
|
|
5
|
-
queue_as :default
|
|
6
|
-
|
|
7
|
-
# Retry configuration
|
|
8
|
-
retry_on StandardError, wait: :exponentially_longer, attempts: 5
|
|
9
|
-
|
|
10
|
-
# Discard configuration
|
|
11
|
-
discard_on ActiveJob::DeserializationError
|
|
12
|
-
|
|
13
|
-
# Perform the job
|
|
14
|
-
# @param args [Array] Job arguments
|
|
15
|
-
def perform(*args)
|
|
16
|
-
# TODO: Implement job logic
|
|
17
|
-
Rails.logger.info "Executing #{self.class.name}"
|
|
18
|
-
|
|
19
|
-
# Example:
|
|
20
|
-
# SomeService.call(*args)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
# Called before job execution
|
|
24
|
-
# @return [void]
|
|
25
|
-
def before_perform
|
|
26
|
-
Rails.logger.info "Starting #{self.class.name}"
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
# Called after job execution
|
|
30
|
-
# @return [void]
|
|
31
|
-
def after_perform
|
|
32
|
-
Rails.logger.info "Completed #{self.class.name}"
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
# Called on job failure
|
|
36
|
-
# @param exception [StandardError] The exception that was raised
|
|
37
|
-
# @return [void]
|
|
38
|
-
def on_failure(exception)
|
|
39
|
-
Rails.logger.error "#{self.class.name} failed: #{exception.message}"
|
|
40
|
-
# Notify error tracking service (e.g., Sentry, Bugsnag)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# Called when job is retried
|
|
44
|
-
# @param exception [StandardError] The exception that caused the retry
|
|
45
|
-
# @return [void]
|
|
46
|
-
def on_retry(exception)
|
|
47
|
-
Rails.logger.warn "#{self.class.name} retrying: #{exception.message}"
|
|
48
|
-
end
|
|
49
|
-
end
|