railsforge 1.0.0 → 1.0.2
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 +7 -11
- data/bin/railsforge +3 -3
- data/lib/railsforge/cli.rb +19 -5
- data/lib/railsforge/cli_minimal.rb +93 -0
- data/lib/railsforge/generators/api_generator.rb +392 -0
- data/lib/railsforge/generators/base_generator.rb +6 -1
- data/lib/railsforge/generators/form_generator.rb +180 -0
- data/lib/railsforge/generators/job_generator.rb +176 -0
- data/lib/railsforge/generators/policy_generator.rb +220 -0
- data/lib/railsforge/generators/presenter_generator.rb +173 -0
- data/lib/railsforge/generators/query_generator.rb +174 -0
- data/lib/railsforge/generators/serializer_generator.rb +166 -0
- data/lib/railsforge/loader.rb +79 -48
- data/lib/railsforge/templates/v3/job/template.rb +1 -1
- data/lib/railsforge/templates/v3/service/template.rb +13 -4
- data/lib/railsforge/version.rb +1 -1
- metadata +20 -41
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# Presenter generator for RailsForge
|
|
2
|
+
# Generates presenter object files
|
|
3
|
+
|
|
4
|
+
require_relative 'base_generator'
|
|
5
|
+
|
|
6
|
+
module RailsForge
|
|
7
|
+
module Generators
|
|
8
|
+
# PresenterGenerator creates presenter files
|
|
9
|
+
class PresenterGenerator < BaseGenerator
|
|
10
|
+
# Error class for invalid presenter names
|
|
11
|
+
class InvalidPresenterNameError < StandardError; end
|
|
12
|
+
|
|
13
|
+
# Template version
|
|
14
|
+
TEMPLATE_VERSION = "v1"
|
|
15
|
+
|
|
16
|
+
# Initialize the generator
|
|
17
|
+
# @param name [String] Presenter name
|
|
18
|
+
# @param options [Hash] Generator options
|
|
19
|
+
def initialize(name, options = {})
|
|
20
|
+
super(name, options)
|
|
21
|
+
@template_version = options[:template_version] || TEMPLATE_VERSION
|
|
22
|
+
@with_spec = options.fetch(:with_spec, true)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Generate presenter files
|
|
26
|
+
# @return [String] Success message
|
|
27
|
+
def generate
|
|
28
|
+
return "Not in a Rails application directory" unless @base_path
|
|
29
|
+
|
|
30
|
+
validate_name!(@name)
|
|
31
|
+
|
|
32
|
+
results = []
|
|
33
|
+
results << generate_presenter
|
|
34
|
+
|
|
35
|
+
if @with_spec
|
|
36
|
+
results << generate_spec
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
"Presenter '#{@name}' generated successfully!\n" + results.join("\n")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Class method for CLI
|
|
43
|
+
def self.generate(presenter_name, with_spec: true, template_version: "v1")
|
|
44
|
+
new(presenter_name, with_spec: with_spec, template_version: template_version).generate
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
# Validate presenter name
|
|
50
|
+
def validate_name!(name)
|
|
51
|
+
raise InvalidPresenterNameError, "Presenter name cannot be empty" if name.nil? || name.strip.empty?
|
|
52
|
+
raise InvalidPresenterNameError, "Name must match pattern: /\\A[A-Z][a-zA-Z0-9]*\\z/" unless name =~ /\A[A-Z][a-zA-Z0-9]*\z/
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Generate presenter file
|
|
56
|
+
def generate_presenter
|
|
57
|
+
presenter_dir = File.join(@base_path, "app", "presenters")
|
|
58
|
+
FileUtils.mkdir_p(presenter_dir)
|
|
59
|
+
|
|
60
|
+
file_name = "#{underscore}_presenter.rb"
|
|
61
|
+
file_path = File.join(presenter_dir, file_name)
|
|
62
|
+
|
|
63
|
+
return " Skipping presenter (already exists)" if File.exist?(file_path)
|
|
64
|
+
|
|
65
|
+
content = load_template
|
|
66
|
+
content = apply_template(content)
|
|
67
|
+
|
|
68
|
+
File.write(file_path, content)
|
|
69
|
+
" Created app/presenters/#{file_name}"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Generate spec file
|
|
73
|
+
def generate_spec
|
|
74
|
+
spec_dir = File.join(@base_path, "spec", "presenters")
|
|
75
|
+
FileUtils.mkdir_p(spec_dir)
|
|
76
|
+
|
|
77
|
+
file_name = "#{underscore}_presenter_spec.rb"
|
|
78
|
+
file_path = File.join(spec_dir, file_name)
|
|
79
|
+
|
|
80
|
+
return " Skipping spec (already exists)" if File.exist?(file_path)
|
|
81
|
+
|
|
82
|
+
content = load_spec_template
|
|
83
|
+
content = apply_template(content)
|
|
84
|
+
|
|
85
|
+
File.write(file_path, content)
|
|
86
|
+
" Created spec/presenters/#{file_name}"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Load template content
|
|
90
|
+
def load_template
|
|
91
|
+
template_path = File.join(
|
|
92
|
+
File.dirname(__FILE__),
|
|
93
|
+
"..",
|
|
94
|
+
"templates",
|
|
95
|
+
@template_version,
|
|
96
|
+
"presenter",
|
|
97
|
+
"template.rb"
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
if File.exist?(template_path)
|
|
101
|
+
File.read(template_path)
|
|
102
|
+
else
|
|
103
|
+
default_template
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Load spec template
|
|
108
|
+
def load_spec_template
|
|
109
|
+
spec_path = File.join(
|
|
110
|
+
File.dirname(__FILE__),
|
|
111
|
+
"..",
|
|
112
|
+
"templates",
|
|
113
|
+
@template_version,
|
|
114
|
+
"presenter",
|
|
115
|
+
"spec_template.rb"
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
if File.exist?(spec_path)
|
|
119
|
+
File.read(spec_path)
|
|
120
|
+
else
|
|
121
|
+
default_spec_template
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Default template
|
|
126
|
+
def default_template
|
|
127
|
+
<<~RUBY
|
|
128
|
+
# Presenter class for #{underscore}
|
|
129
|
+
# Encapsulates view logic
|
|
130
|
+
class #{camelize}Presenter
|
|
131
|
+
def initialize(object)
|
|
132
|
+
@object = object
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def title
|
|
136
|
+
@object.name.titleize
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def details
|
|
140
|
+
# TODO: Add presenter logic
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
RUBY
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Default spec template
|
|
147
|
+
def default_spec_template
|
|
148
|
+
<<~RUBY
|
|
149
|
+
require 'rails_helper'
|
|
150
|
+
|
|
151
|
+
RSpec.describe #{camelize}Presenter do
|
|
152
|
+
let(:object) { double(name: 'Test Object') }
|
|
153
|
+
subject { described_class.new(object) }
|
|
154
|
+
|
|
155
|
+
describe '#title' do
|
|
156
|
+
it 'returns titleized name' do
|
|
157
|
+
expect(subject.title).to eq('Test Object')
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
RUBY
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Apply template variables
|
|
165
|
+
def apply_template(content)
|
|
166
|
+
content
|
|
167
|
+
.gsub("<%= name %>", @name)
|
|
168
|
+
.gsub("<%= name.camelize %>", camelize)
|
|
169
|
+
.gsub("<%= name.underscore %>", underscore)
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Query generator for RailsForge
|
|
2
|
+
# Generates query object files
|
|
3
|
+
|
|
4
|
+
require_relative 'base_generator'
|
|
5
|
+
|
|
6
|
+
module RailsForge
|
|
7
|
+
module Generators
|
|
8
|
+
# QueryGenerator creates query files
|
|
9
|
+
class QueryGenerator < BaseGenerator
|
|
10
|
+
# Error class for invalid query names
|
|
11
|
+
class InvalidQueryNameError < StandardError; end
|
|
12
|
+
|
|
13
|
+
# Template version
|
|
14
|
+
TEMPLATE_VERSION = "v1"
|
|
15
|
+
|
|
16
|
+
# Initialize the generator
|
|
17
|
+
# @param name [String] Query name
|
|
18
|
+
# @param options [Hash] Generator options
|
|
19
|
+
def initialize(name, options = {})
|
|
20
|
+
super(name, options)
|
|
21
|
+
@template_version = options[:template_version] || TEMPLATE_VERSION
|
|
22
|
+
@with_spec = options.fetch(:with_spec, true)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Generate query files
|
|
26
|
+
# @return [String] Success message
|
|
27
|
+
def generate
|
|
28
|
+
return "Not in a Rails application directory" unless @base_path
|
|
29
|
+
|
|
30
|
+
validate_name!(@name)
|
|
31
|
+
|
|
32
|
+
results = []
|
|
33
|
+
results << generate_query
|
|
34
|
+
|
|
35
|
+
if @with_spec
|
|
36
|
+
results << generate_spec
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
"Query '#{@name}' generated successfully!\n" + results.join("\n")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Class method for CLI
|
|
43
|
+
def self.generate(query_name, with_spec: true, template_version: "v1")
|
|
44
|
+
new(query_name, with_spec: with_spec, template_version: template_version).generate
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
# Validate query name
|
|
50
|
+
def validate_name!(name)
|
|
51
|
+
raise InvalidQueryNameError, "Query name cannot be empty" if name.nil? || name.strip.empty?
|
|
52
|
+
raise InvalidQueryNameError, "Name must match pattern: /\\A[A-Z][a-zA-Z0-9]*\\z/" unless name =~ /\A[A-Z][a-zA-Z0-9]*\z/
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Generate query file
|
|
56
|
+
def generate_query
|
|
57
|
+
query_dir = File.join(@base_path, "app", "queries")
|
|
58
|
+
FileUtils.mkdir_p(query_dir)
|
|
59
|
+
|
|
60
|
+
file_name = "#{underscore}.rb"
|
|
61
|
+
file_path = File.join(query_dir, file_name)
|
|
62
|
+
|
|
63
|
+
return " Skipping query (already exists)" if File.exist?(file_path)
|
|
64
|
+
|
|
65
|
+
content = load_template
|
|
66
|
+
content = apply_template(content)
|
|
67
|
+
|
|
68
|
+
File.write(file_path, content)
|
|
69
|
+
" Created app/queries/#{file_name}"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Generate spec file
|
|
73
|
+
def generate_spec
|
|
74
|
+
spec_dir = File.join(@base_path, "spec", "queries")
|
|
75
|
+
FileUtils.mkdir_p(spec_dir)
|
|
76
|
+
|
|
77
|
+
file_name = "#{underscore}_spec.rb"
|
|
78
|
+
file_path = File.join(spec_dir, file_name)
|
|
79
|
+
|
|
80
|
+
return " Skipping spec (already exists)" if File.exist?(file_path)
|
|
81
|
+
|
|
82
|
+
content = load_spec_template
|
|
83
|
+
content = apply_template(content)
|
|
84
|
+
|
|
85
|
+
File.write(file_path, content)
|
|
86
|
+
" Created spec/queries/#{file_name}"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Load template content
|
|
90
|
+
def load_template
|
|
91
|
+
template_path = File.join(
|
|
92
|
+
File.dirname(__FILE__),
|
|
93
|
+
"..",
|
|
94
|
+
"templates",
|
|
95
|
+
@template_version,
|
|
96
|
+
"query",
|
|
97
|
+
"template.rb"
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
if File.exist?(template_path)
|
|
101
|
+
File.read(template_path)
|
|
102
|
+
else
|
|
103
|
+
default_template
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Load spec template
|
|
108
|
+
def load_spec_template
|
|
109
|
+
spec_path = File.join(
|
|
110
|
+
File.dirname(__FILE__),
|
|
111
|
+
"..",
|
|
112
|
+
"templates",
|
|
113
|
+
@template_version,
|
|
114
|
+
"query",
|
|
115
|
+
"spec_template.rb"
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
if File.exist?(spec_path)
|
|
119
|
+
File.read(spec_path)
|
|
120
|
+
else
|
|
121
|
+
default_spec_template
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Default template
|
|
126
|
+
def default_template
|
|
127
|
+
<<~RUBY
|
|
128
|
+
# Query class for #{underscore}
|
|
129
|
+
# Encapsulates database queries
|
|
130
|
+
class #{camelize}
|
|
131
|
+
def initialize(scope: nil)
|
|
132
|
+
@scope = scope || default_scope
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def call
|
|
136
|
+
@scope
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
private
|
|
140
|
+
|
|
141
|
+
def default_scope
|
|
142
|
+
# TODO: Replace with actual model scope
|
|
143
|
+
Model.all
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
RUBY
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Default spec template
|
|
150
|
+
def default_spec_template
|
|
151
|
+
<<~RUBY
|
|
152
|
+
require 'rails_helper'
|
|
153
|
+
|
|
154
|
+
RSpec.describe #{camelize} do
|
|
155
|
+
describe '#call' do
|
|
156
|
+
it 'returns scope' do
|
|
157
|
+
result = described_class.call
|
|
158
|
+
expect(result).to be_a(ActiveRecord::Relation)
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
RUBY
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Apply template variables
|
|
166
|
+
def apply_template(content)
|
|
167
|
+
content
|
|
168
|
+
.gsub("<%= name %>", @name)
|
|
169
|
+
.gsub("<%= name.camelize %>", camelize)
|
|
170
|
+
.gsub("<%= name.underscore %>", underscore)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Serializer generator for RailsForge
|
|
2
|
+
# Generates serializer object files
|
|
3
|
+
|
|
4
|
+
require_relative 'base_generator'
|
|
5
|
+
|
|
6
|
+
module RailsForge
|
|
7
|
+
module Generators
|
|
8
|
+
# SerializerGenerator creates serializer files
|
|
9
|
+
class SerializerGenerator < BaseGenerator
|
|
10
|
+
# Error class for invalid serializer names
|
|
11
|
+
class InvalidSerializerNameError < StandardError; end
|
|
12
|
+
|
|
13
|
+
# Template version
|
|
14
|
+
TEMPLATE_VERSION = "v1"
|
|
15
|
+
|
|
16
|
+
# Initialize the generator
|
|
17
|
+
# @param name [String] Serializer name
|
|
18
|
+
# @param options [Hash] Generator options
|
|
19
|
+
def initialize(name, options = {})
|
|
20
|
+
super(name, options)
|
|
21
|
+
@template_version = options[:template_version] || TEMPLATE_VERSION
|
|
22
|
+
@with_spec = options.fetch(:with_spec, true)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Generate serializer files
|
|
26
|
+
# @return [String] Success message
|
|
27
|
+
def generate
|
|
28
|
+
return "Not in a Rails application directory" unless @base_path
|
|
29
|
+
|
|
30
|
+
validate_name!(@name)
|
|
31
|
+
|
|
32
|
+
results = []
|
|
33
|
+
results << generate_serializer
|
|
34
|
+
|
|
35
|
+
if @with_spec
|
|
36
|
+
results << generate_spec
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
"Serializer '#{@name}' generated successfully!\n" + results.join("\n")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Class method for CLI
|
|
43
|
+
def self.generate(serializer_name, with_spec: true, template_version: "v1")
|
|
44
|
+
new(serializer_name, with_spec: with_spec, template_version: template_version).generate
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
# Validate serializer name
|
|
50
|
+
def validate_name!(name)
|
|
51
|
+
raise InvalidSerializerNameError, "Serializer name cannot be empty" if name.nil? || name.strip.empty?
|
|
52
|
+
raise InvalidSerializerNameError, "Name must match pattern: /\\A[A-Z][a-zA-Z0-9]*\\z/" unless name =~ /\A[A-Z][a-zA-Z0-9]*\z/
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Generate serializer file
|
|
56
|
+
def generate_serializer
|
|
57
|
+
serializer_dir = File.join(@base_path, "app", "serializers")
|
|
58
|
+
FileUtils.mkdir_p(serializer_dir)
|
|
59
|
+
|
|
60
|
+
file_name = "#{underscore}_serializer.rb"
|
|
61
|
+
file_path = File.join(serializer_dir, file_name)
|
|
62
|
+
|
|
63
|
+
return " Skipping serializer (already exists)" if File.exist?(file_path)
|
|
64
|
+
|
|
65
|
+
content = load_template
|
|
66
|
+
content = apply_template(content)
|
|
67
|
+
|
|
68
|
+
File.write(file_path, content)
|
|
69
|
+
" Created app/serializers/#{file_name}"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Generate spec file
|
|
73
|
+
def generate_spec
|
|
74
|
+
spec_dir = File.join(@base_path, "spec", "serializers")
|
|
75
|
+
FileUtils.mkdir_p(spec_dir)
|
|
76
|
+
|
|
77
|
+
file_name = "#{underscore}_serializer_spec.rb"
|
|
78
|
+
file_path = File.join(spec_dir, file_name)
|
|
79
|
+
|
|
80
|
+
return " Skipping spec (already exists)" if File.exist?(file_path)
|
|
81
|
+
|
|
82
|
+
content = load_spec_template
|
|
83
|
+
content = apply_template(content)
|
|
84
|
+
|
|
85
|
+
File.write(file_path, content)
|
|
86
|
+
" Created spec/serializers/#{file_name}"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Load template content
|
|
90
|
+
def load_template
|
|
91
|
+
template_path = File.join(
|
|
92
|
+
File.dirname(__FILE__),
|
|
93
|
+
"..",
|
|
94
|
+
"templates",
|
|
95
|
+
@template_version,
|
|
96
|
+
"serializer",
|
|
97
|
+
"template.rb"
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
if File.exist?(template_path)
|
|
101
|
+
File.read(template_path)
|
|
102
|
+
else
|
|
103
|
+
default_template
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Load spec template
|
|
108
|
+
def load_spec_template
|
|
109
|
+
spec_path = File.join(
|
|
110
|
+
File.dirname(__FILE__),
|
|
111
|
+
"..",
|
|
112
|
+
"templates",
|
|
113
|
+
@template_version,
|
|
114
|
+
"serializer",
|
|
115
|
+
"spec_template.rb"
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
if File.exist?(spec_path)
|
|
119
|
+
File.read(spec_path)
|
|
120
|
+
else
|
|
121
|
+
default_spec_template
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Default template
|
|
126
|
+
def default_template
|
|
127
|
+
<<~RUBY
|
|
128
|
+
# Serializer class for #{underscore}
|
|
129
|
+
# Defines JSON serialization
|
|
130
|
+
class #{camelize}Serializer < ApplicationSerializer
|
|
131
|
+
attributes :id, :name, :created_at, :updated_at
|
|
132
|
+
|
|
133
|
+
# TODO and: Add associations methods
|
|
134
|
+
# belongs_to :user
|
|
135
|
+
# has_many :items
|
|
136
|
+
end
|
|
137
|
+
RUBY
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Default spec template
|
|
141
|
+
def default_spec_template
|
|
142
|
+
<<~RUBY
|
|
143
|
+
require 'rails_helper'
|
|
144
|
+
|
|
145
|
+
RSpec.describe #{camelize}Serializer do
|
|
146
|
+
let(:resource) { #{camelize}.create!(name: 'Test') }
|
|
147
|
+
let(:serializer) { described_class.new(resource) }
|
|
148
|
+
let(:serialization) { ActiveModel::SerializableResource.new(resource).as_json }
|
|
149
|
+
|
|
150
|
+
it 'includes expected attributes' do
|
|
151
|
+
expect(serialization[:#{camelize.underscore}] [:name]).to eq('Test')
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
RUBY
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Apply template variables
|
|
158
|
+
def apply_template(content)
|
|
159
|
+
content
|
|
160
|
+
.gsub("<%= name %>", @name)
|
|
161
|
+
.gsub("<%= name.camelize %>", camelize)
|
|
162
|
+
.gsub("<%= name.underscore %>", underscore)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
data/lib/railsforge/loader.rb
CHANGED
|
@@ -1,56 +1,87 @@
|
|
|
1
1
|
# RailsForge modular loader
|
|
2
|
-
# This file centralizes all require statements
|
|
2
|
+
# This file centralizes all require statements with lazy loading
|
|
3
3
|
|
|
4
4
|
require "fileutils"
|
|
5
5
|
|
|
6
6
|
# Get the lib directory path
|
|
7
7
|
LIB_DIR = File.dirname(__FILE__)
|
|
8
8
|
|
|
9
|
-
# Core modules
|
|
9
|
+
# Core modules - always needed
|
|
10
10
|
require_relative "version"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
require_relative "generators
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
require_relative "
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
require_relative
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
require_relative "
|
|
36
|
-
require_relative "
|
|
37
|
-
|
|
38
|
-
#
|
|
39
|
-
require_relative "
|
|
40
|
-
|
|
41
|
-
#
|
|
42
|
-
require_relative "
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
require_relative "
|
|
46
|
-
require_relative "
|
|
47
|
-
require_relative "
|
|
48
|
-
require_relative "
|
|
49
|
-
require_relative "
|
|
50
|
-
require_relative "
|
|
51
|
-
require_relative "
|
|
52
|
-
require_relative "
|
|
53
|
-
require_relative "
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
11
|
+
|
|
12
|
+
# Minimal CLI loader for --help and --version (fast)
|
|
13
|
+
require_relative "cli_minimal"
|
|
14
|
+
|
|
15
|
+
# Lazy-load everything else
|
|
16
|
+
module RailsForge
|
|
17
|
+
class << self
|
|
18
|
+
# Lazy-load generators
|
|
19
|
+
def require_generator(name)
|
|
20
|
+
require_relative "generators/#{name}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Lazy-load analyzers
|
|
24
|
+
def require_analyzer(name)
|
|
25
|
+
require_relative "analyzers/#{name}"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Lazy-load other modules
|
|
29
|
+
def require_module(name)
|
|
30
|
+
require_relative name
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Preload all (for commands that need everything)
|
|
34
|
+
def preload_all!
|
|
35
|
+
require_relative "profiles"
|
|
36
|
+
require_relative "template_loader"
|
|
37
|
+
|
|
38
|
+
# Define Generators module first to ensure proper namespace
|
|
39
|
+
require_relative "generators/base_generator"
|
|
40
|
+
|
|
41
|
+
# Generators
|
|
42
|
+
require_relative "generators/service_generator"
|
|
43
|
+
require_relative "generators/job_generator"
|
|
44
|
+
require_relative "generators/query_generator"
|
|
45
|
+
require_relative "generators/form_generator"
|
|
46
|
+
require_relative "generators/presenter_generator"
|
|
47
|
+
require_relative "generators/policy_generator"
|
|
48
|
+
require_relative "generators/serializer_generator"
|
|
49
|
+
require_relative "generators/api_generator"
|
|
50
|
+
require_relative "generators/view_component_generator"
|
|
51
|
+
require_relative "generators/stimulus_controller_generator"
|
|
52
|
+
require_relative "generators/demo_generator"
|
|
53
|
+
require_relative "generators/devops_generator"
|
|
54
|
+
require_relative "generators/monitoring_generator"
|
|
55
|
+
require_relative "generators/test_generator"
|
|
56
|
+
|
|
57
|
+
# Analyzers
|
|
58
|
+
require_relative "analyzers/base_analyzer"
|
|
59
|
+
require_relative "analyzers/controller_analyzer"
|
|
60
|
+
require_relative "analyzers/model_analyzer"
|
|
61
|
+
require_relative "analyzers/spec_analyzer"
|
|
62
|
+
require_relative "analyzers/database_analyzer"
|
|
63
|
+
require_relative "analyzers/metrics_analyzer"
|
|
64
|
+
require_relative "analyzers/refactor_analyzer"
|
|
65
|
+
require_relative "analyzers/security_analyzer"
|
|
66
|
+
require_relative "analyzers/performance_analyzer"
|
|
67
|
+
|
|
68
|
+
# Refactors & plugins
|
|
69
|
+
require_relative "refactors/refactor_controller"
|
|
70
|
+
require_relative "plugins"
|
|
71
|
+
|
|
72
|
+
# Legacy (modules with class methods)
|
|
73
|
+
require_relative "mailer_generator"
|
|
74
|
+
require_relative "feature_generator"
|
|
75
|
+
require_relative "audit"
|
|
76
|
+
require_relative "doctor"
|
|
77
|
+
require_relative "graph"
|
|
78
|
+
require_relative "wizard"
|
|
79
|
+
require_relative "wizard_tui"
|
|
80
|
+
require_relative "config"
|
|
81
|
+
require_relative "generator"
|
|
82
|
+
|
|
83
|
+
# CLI
|
|
84
|
+
require_relative "cli"
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -23,7 +23,7 @@ class <%= class_name %>Job < ApplicationJob
|
|
|
23
23
|
# TODO: Implement job logic
|
|
24
24
|
# Example:
|
|
25
25
|
# user = User.find(args[:user_id])
|
|
26
|
-
# user.
|
|
26
|
+
# UserMailer.welcome(user).deliver_now
|
|
27
27
|
Rails.logger.info("Executing #{self.class.name}")
|
|
28
28
|
end
|
|
29
29
|
|
|
@@ -46,16 +46,25 @@ class <%= class_name %>
|
|
|
46
46
|
private
|
|
47
47
|
|
|
48
48
|
# Validate inputs - returns Result
|
|
49
|
+
# Override this method to add custom validation
|
|
50
|
+
# @example
|
|
51
|
+
# def validate!
|
|
52
|
+
# return Failure(errors: ['Name required']) if @params[:name].blank?
|
|
53
|
+
# Success(true)
|
|
54
|
+
# end
|
|
49
55
|
def validate!
|
|
50
|
-
# TODO: Add validation logic
|
|
51
|
-
# Example:
|
|
52
|
-
# return Failure(errors: ['Name required']) if @params[:name].blank?
|
|
53
56
|
Success(true)
|
|
54
57
|
end
|
|
55
58
|
|
|
56
59
|
# Process the main logic - returns Result
|
|
60
|
+
# Override this method to implement your service logic
|
|
61
|
+
# @example
|
|
62
|
+
# def process!
|
|
63
|
+
# user = User.create!(@params)
|
|
64
|
+
# @result = { user: user }
|
|
65
|
+
# Success(true)
|
|
66
|
+
# end
|
|
57
67
|
def process!
|
|
58
|
-
# TODO: Implement service logic
|
|
59
68
|
@result = {}
|
|
60
69
|
Success(true)
|
|
61
70
|
end
|
data/lib/railsforge/version.rb
CHANGED