railsforge 1.0.1 → 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/lib/railsforge/cli.rb +19 -5
- 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 +14 -3
- data/lib/railsforge/version.rb +1 -1
- metadata +11 -4
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Job generator for RailsForge
|
|
2
|
+
# Generates background job files
|
|
3
|
+
|
|
4
|
+
require_relative 'base_generator'
|
|
5
|
+
|
|
6
|
+
module RailsForge
|
|
7
|
+
module Generators
|
|
8
|
+
# JobGenerator creates job files
|
|
9
|
+
class JobGenerator < BaseGenerator
|
|
10
|
+
# Error class for invalid job names
|
|
11
|
+
class InvalidJobNameError < StandardError; end
|
|
12
|
+
|
|
13
|
+
# Template version
|
|
14
|
+
TEMPLATE_VERSION = "v1"
|
|
15
|
+
|
|
16
|
+
# Initialize the generator
|
|
17
|
+
# @param name [String] Job 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 job 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_job
|
|
34
|
+
|
|
35
|
+
if @with_spec
|
|
36
|
+
results << generate_spec
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
"Job '#{@name}' generated successfully!\n" + results.join("\n")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Class method for CLI
|
|
43
|
+
def self.generate(job_name, with_spec: true, template_version: "v1")
|
|
44
|
+
new(job_name, with_spec: with_spec, template_version: template_version).generate
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
# Validate job name
|
|
50
|
+
def validate_name!(name)
|
|
51
|
+
raise InvalidJobNameError, "Job name cannot be empty" if name.nil? || name.strip.empty?
|
|
52
|
+
raise InvalidJobNameError, "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 job file
|
|
56
|
+
def generate_job
|
|
57
|
+
job_dir = File.join(@base_path, "app", "jobs")
|
|
58
|
+
FileUtils.mkdir_p(job_dir)
|
|
59
|
+
|
|
60
|
+
file_name = "#{underscore}_job.rb"
|
|
61
|
+
file_path = File.join(job_dir, file_name)
|
|
62
|
+
|
|
63
|
+
return " Skipping job (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/jobs/#{file_name}"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Generate spec file
|
|
73
|
+
def generate_spec
|
|
74
|
+
spec_dir = File.join(@base_path, "spec", "jobs")
|
|
75
|
+
FileUtils.mkdir_p(spec_dir)
|
|
76
|
+
|
|
77
|
+
file_name = "#{underscore}_job_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/jobs/#{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
|
+
"job",
|
|
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
|
+
"job",
|
|
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
|
+
# Background job for #{underscore}
|
|
129
|
+
# Handles async processing
|
|
130
|
+
#
|
|
131
|
+
# Usage:
|
|
132
|
+
# #{camelize}Job.perform_later(record)
|
|
133
|
+
# #{camelize}Job.perform_now(record)
|
|
134
|
+
class #{camelize}Job < ApplicationJob
|
|
135
|
+
queue_as :default
|
|
136
|
+
|
|
137
|
+
def perform(*args)
|
|
138
|
+
# TODO: Implement job logic
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
RUBY
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Default spec template
|
|
145
|
+
def default_spec_template
|
|
146
|
+
<<~RUBY
|
|
147
|
+
require 'rails_helper'
|
|
148
|
+
|
|
149
|
+
RSpec.describe #{camelize}Job do
|
|
150
|
+
let(:args) { [] }
|
|
151
|
+
|
|
152
|
+
it 'enqueues the job' do
|
|
153
|
+
expect {
|
|
154
|
+
described_class.perform_later(*args)
|
|
155
|
+
}.to have_enqueued_job(described_class)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
describe '#perform' do
|
|
159
|
+
it 'performs the job' do
|
|
160
|
+
expect { subject.perform(*args) }.not_to raise_error
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
RUBY
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Apply template variables
|
|
168
|
+
def apply_template(content)
|
|
169
|
+
content
|
|
170
|
+
.gsub("<%= name %>", @name)
|
|
171
|
+
.gsub("<%= name.camelize %>", camelize)
|
|
172
|
+
.gsub("<%= name.underscore %>", underscore)
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# Policy generator for RailsForge
|
|
2
|
+
# Generates policy object files (for Pundit)
|
|
3
|
+
|
|
4
|
+
require_relative 'base_generator'
|
|
5
|
+
|
|
6
|
+
module RailsForge
|
|
7
|
+
module Generators
|
|
8
|
+
# PolicyGenerator creates policy files
|
|
9
|
+
class PolicyGenerator < BaseGenerator
|
|
10
|
+
# Error class for invalid policy names
|
|
11
|
+
class InvalidPolicyNameError < StandardError; end
|
|
12
|
+
|
|
13
|
+
# Template version
|
|
14
|
+
TEMPLATE_VERSION = "v1"
|
|
15
|
+
|
|
16
|
+
# Initialize the generator
|
|
17
|
+
# @param name [String] Policy 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 policy 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_policy
|
|
34
|
+
|
|
35
|
+
if @with_spec
|
|
36
|
+
results << generate_spec
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
"Policy '#{@name}' generated successfully!\n" + results.join("\n")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Class method for CLI
|
|
43
|
+
def self.generate(policy_name, with_spec: true, template_version: "v1")
|
|
44
|
+
new(policy_name, with_spec: with_spec, template_version: template_version).generate
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
# Validate policy name
|
|
50
|
+
def validate_name!(name)
|
|
51
|
+
raise InvalidPolicyNameError, "Policy name cannot be empty" if name.nil? || name.strip.empty?
|
|
52
|
+
raise InvalidPolicyNameError, "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 policy file
|
|
56
|
+
def generate_policy
|
|
57
|
+
policy_dir = File.join(@base_path, "app", "policies")
|
|
58
|
+
FileUtils.mkdir_p(policy_dir)
|
|
59
|
+
|
|
60
|
+
file_name = "#{underscore}_policy.rb"
|
|
61
|
+
file_path = File.join(policy_dir, file_name)
|
|
62
|
+
|
|
63
|
+
return " Skipping policy (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/policies/#{file_name}"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Generate spec file
|
|
73
|
+
def generate_spec
|
|
74
|
+
spec_dir = File.join(@base_path, "spec", "policies")
|
|
75
|
+
FileUtils.mkdir_p(spec_dir)
|
|
76
|
+
|
|
77
|
+
file_name = "#{underscore}_policy_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/policies/#{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
|
+
"policy",
|
|
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
|
+
"policy",
|
|
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
|
+
# Policy class for #{underscore}
|
|
129
|
+
# Defines authorization rules using Pundit
|
|
130
|
+
class #{camelize}Policy
|
|
131
|
+
attr_reader :user, :record
|
|
132
|
+
|
|
133
|
+
def initialize(user, record)
|
|
134
|
+
@user = user
|
|
135
|
+
@record = record
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def index?
|
|
139
|
+
true
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def show?
|
|
143
|
+
true
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def create?
|
|
147
|
+
user.present?
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def new?
|
|
151
|
+
create?
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def update?
|
|
155
|
+
user.present? && record.user == user
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def edit?
|
|
159
|
+
update?
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def destroy?
|
|
163
|
+
user.present? && record.user == user
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
class Scope
|
|
167
|
+
def initialize(user, scope)
|
|
168
|
+
@user = user
|
|
169
|
+
@scope = scope
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def resolve
|
|
173
|
+
scope.all
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
RUBY
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Default spec template
|
|
181
|
+
def default_spec_template
|
|
182
|
+
<<~RUBY
|
|
183
|
+
require 'rails_helper'
|
|
184
|
+
|
|
185
|
+
RSpec.describe #{camelize}Policy do
|
|
186
|
+
let(:user) { User.new }
|
|
187
|
+
let(:record) { #{camelize}.new }
|
|
188
|
+
|
|
189
|
+
subject { described_class.new(user, record) }
|
|
190
|
+
|
|
191
|
+
it { should permit(:index) }
|
|
192
|
+
it { should permit(:show) }
|
|
193
|
+
it { should permit(:new) }
|
|
194
|
+
it { should permit(:create) }
|
|
195
|
+
|
|
196
|
+
context 'when user is the owner' do
|
|
197
|
+
let(:user) { record.user }
|
|
198
|
+
|
|
199
|
+
it { should permit(:update) }
|
|
200
|
+
it { should permit(:destroy) }
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
context 'when user is not the owner' do
|
|
204
|
+
it { should_not permit(:update) }
|
|
205
|
+
it { should_not permit(:destroy) }
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
RUBY
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
# Apply template variables
|
|
212
|
+
def apply_template(content)
|
|
213
|
+
content
|
|
214
|
+
.gsub("<%= name %>", @name)
|
|
215
|
+
.gsub("<%= name.camelize %>", camelize)
|
|
216
|
+
.gsub("<%= name.underscore %>", underscore)
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
@@ -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
|