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,180 @@
|
|
|
1
|
+
# Form generator for RailsForge
|
|
2
|
+
# Generates form object files
|
|
3
|
+
|
|
4
|
+
require_relative 'base_generator'
|
|
5
|
+
|
|
6
|
+
module RailsForge
|
|
7
|
+
module Generators
|
|
8
|
+
# FormGenerator creates form files
|
|
9
|
+
class FormGenerator < BaseGenerator
|
|
10
|
+
# Error class for invalid form names
|
|
11
|
+
class InvalidFormNameError < StandardError; end
|
|
12
|
+
|
|
13
|
+
# Template version
|
|
14
|
+
TEMPLATE_VERSION = "v1"
|
|
15
|
+
|
|
16
|
+
# Initialize the generator
|
|
17
|
+
# @param name [String] Form 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 form 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_form
|
|
34
|
+
|
|
35
|
+
if @with_spec
|
|
36
|
+
results << generate_spec
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
"Form '#{@name}' generated successfully!\n" + results.join("\n")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Class method for CLI
|
|
43
|
+
def self.generate(form_name, with_spec: true, template_version: "v1")
|
|
44
|
+
new(form_name, with_spec: with_spec, template_version: template_version).generate
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
# Validate form name
|
|
50
|
+
def validate_name!(name)
|
|
51
|
+
raise InvalidFormNameError, "Form name cannot be empty" if name.nil? || name.strip.empty?
|
|
52
|
+
raise InvalidFormNameError, "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 form file
|
|
56
|
+
def generate_form
|
|
57
|
+
form_dir = File.join(@base_path, "app", "forms")
|
|
58
|
+
FileUtils.mkdir_p(form_dir)
|
|
59
|
+
|
|
60
|
+
file_name = "#{underscore}_form.rb"
|
|
61
|
+
file_path = File.join(form_dir, file_name)
|
|
62
|
+
|
|
63
|
+
return " Skipping form (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/forms/#{file_name}"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Generate spec file
|
|
73
|
+
def generate_spec
|
|
74
|
+
spec_dir = File.join(@base_path, "spec", "forms")
|
|
75
|
+
FileUtils.mkdir_p(spec_dir)
|
|
76
|
+
|
|
77
|
+
file_name = "#{underscore}_form_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/forms/#{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
|
+
"form",
|
|
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
|
+
"form",
|
|
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
|
+
# Form class for #{underscore}
|
|
129
|
+
# Encapsulates form validation and processing
|
|
130
|
+
class #{camelize}Form
|
|
131
|
+
include ActiveModel::Model
|
|
132
|
+
|
|
133
|
+
attr_accessor :name, :email
|
|
134
|
+
|
|
135
|
+
validates :name, presence: true
|
|
136
|
+
validates :email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }
|
|
137
|
+
|
|
138
|
+
def save
|
|
139
|
+
return false unless valid?
|
|
140
|
+
|
|
141
|
+
# TODO: Implement save logic
|
|
142
|
+
true
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
RUBY
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Default spec template
|
|
149
|
+
def default_spec_template
|
|
150
|
+
<<~RUBY
|
|
151
|
+
require 'rails_helper'
|
|
152
|
+
|
|
153
|
+
RSpec.describe #{camelize}Form do
|
|
154
|
+
describe 'validations' do
|
|
155
|
+
it 'validates presence of name' do
|
|
156
|
+
form = described_class.new(name: nil, email: 'test@example.com')
|
|
157
|
+
expect(form).not_to be_valid
|
|
158
|
+
expect(form.errors[:name]).to be_present
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it 'validates email format' do
|
|
162
|
+
form = described_class.new(name: 'Test', email: 'invalid')
|
|
163
|
+
expect(form).not_to be_valid
|
|
164
|
+
expect(form.errors[:email]).to be_present
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
RUBY
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Apply template variables
|
|
172
|
+
def apply_template(content)
|
|
173
|
+
content
|
|
174
|
+
.gsub("<%= name %>", @name)
|
|
175
|
+
.gsub("<%= name.camelize %>", camelize)
|
|
176
|
+
.gsub("<%= name.underscore %>", underscore)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
@@ -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
|