railsforge 1.0.2 → 2.0.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.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +105 -444
  3. data/lib/railsforge/analyzers/controller_analyzer.rb +29 -55
  4. data/lib/railsforge/analyzers/database_analyzer.rb +16 -30
  5. data/lib/railsforge/analyzers/metrics_analyzer.rb +8 -22
  6. data/lib/railsforge/analyzers/model_analyzer.rb +29 -46
  7. data/lib/railsforge/analyzers/performance_analyzer.rb +34 -94
  8. data/lib/railsforge/analyzers/refactor_analyzer.rb +77 -57
  9. data/lib/railsforge/analyzers/security_analyzer.rb +34 -91
  10. data/lib/railsforge/analyzers/spec_analyzer.rb +17 -31
  11. data/lib/railsforge/cli.rb +14 -650
  12. data/lib/railsforge/cli_minimal.rb +8 -55
  13. data/lib/railsforge/doctor.rb +52 -225
  14. data/lib/railsforge/formatter.rb +102 -0
  15. data/lib/railsforge/issue.rb +23 -0
  16. data/lib/railsforge/loader.rb +4 -64
  17. data/lib/railsforge/version.rb +1 -1
  18. metadata +14 -82
  19. data/lib/railsforge/api_generator.rb +0 -397
  20. data/lib/railsforge/audit.rb +0 -289
  21. data/lib/railsforge/config.rb +0 -181
  22. data/lib/railsforge/database_analyzer.rb +0 -300
  23. data/lib/railsforge/feature_generator.rb +0 -560
  24. data/lib/railsforge/generator.rb +0 -313
  25. data/lib/railsforge/generators/api_generator.rb +0 -392
  26. data/lib/railsforge/generators/base_generator.rb +0 -75
  27. data/lib/railsforge/generators/demo_generator.rb +0 -307
  28. data/lib/railsforge/generators/devops_generator.rb +0 -287
  29. data/lib/railsforge/generators/form_generator.rb +0 -180
  30. data/lib/railsforge/generators/job_generator.rb +0 -176
  31. data/lib/railsforge/generators/monitoring_generator.rb +0 -134
  32. data/lib/railsforge/generators/policy_generator.rb +0 -220
  33. data/lib/railsforge/generators/presenter_generator.rb +0 -173
  34. data/lib/railsforge/generators/query_generator.rb +0 -174
  35. data/lib/railsforge/generators/serializer_generator.rb +0 -166
  36. data/lib/railsforge/generators/service_generator.rb +0 -122
  37. data/lib/railsforge/generators/stimulus_controller_generator.rb +0 -129
  38. data/lib/railsforge/generators/test_generator.rb +0 -289
  39. data/lib/railsforge/generators/view_component_generator.rb +0 -169
  40. data/lib/railsforge/graph.rb +0 -270
  41. data/lib/railsforge/mailer_generator.rb +0 -191
  42. data/lib/railsforge/plugins/plugin_loader.rb +0 -60
  43. data/lib/railsforge/plugins.rb +0 -30
  44. data/lib/railsforge/profiles.rb +0 -99
  45. data/lib/railsforge/refactor_analyzer.rb +0 -401
  46. data/lib/railsforge/refactor_controller.rb +0 -277
  47. data/lib/railsforge/refactors/refactor_controller.rb +0 -117
  48. data/lib/railsforge/template_loader.rb +0 -105
  49. data/lib/railsforge/templates/v1/form/spec_template.rb +0 -18
  50. data/lib/railsforge/templates/v1/form/template.rb +0 -28
  51. data/lib/railsforge/templates/v1/job/spec_template.rb +0 -17
  52. data/lib/railsforge/templates/v1/job/template.rb +0 -13
  53. data/lib/railsforge/templates/v1/policy/spec_template.rb +0 -41
  54. data/lib/railsforge/templates/v1/policy/template.rb +0 -57
  55. data/lib/railsforge/templates/v1/presenter/spec_template.rb +0 -12
  56. data/lib/railsforge/templates/v1/presenter/template.rb +0 -13
  57. data/lib/railsforge/templates/v1/query/spec_template.rb +0 -12
  58. data/lib/railsforge/templates/v1/query/template.rb +0 -16
  59. data/lib/railsforge/templates/v1/serializer/spec_template.rb +0 -13
  60. data/lib/railsforge/templates/v1/serializer/template.rb +0 -11
  61. data/lib/railsforge/templates/v1/service/spec_template.rb +0 -12
  62. data/lib/railsforge/templates/v1/service/template.rb +0 -25
  63. data/lib/railsforge/templates/v1/stimulus_controller/template.rb +0 -35
  64. data/lib/railsforge/templates/v1/view_component/template.rb +0 -24
  65. data/lib/railsforge/templates/v2/job/template.rb +0 -49
  66. data/lib/railsforge/templates/v2/query/template.rb +0 -66
  67. data/lib/railsforge/templates/v2/service/spec_template.rb +0 -33
  68. data/lib/railsforge/templates/v2/service/template.rb +0 -71
  69. data/lib/railsforge/templates/v3/job/template.rb +0 -72
  70. data/lib/railsforge/templates/v3/query/spec_template.rb +0 -54
  71. data/lib/railsforge/templates/v3/query/template.rb +0 -115
  72. data/lib/railsforge/templates/v3/service/spec_template.rb +0 -51
  73. data/lib/railsforge/templates/v3/service/template.rb +0 -93
  74. data/lib/railsforge/wizard.rb +0 -265
  75. data/lib/railsforge/wizard_tui.rb +0 -286
@@ -1,180 +0,0 @@
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
@@ -1,176 +0,0 @@
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
@@ -1,134 +0,0 @@
1
- # Monitoring generator for RailsForge
2
- # Generates Sentry and Lograge configurations
3
-
4
- require 'fileutils'
5
-
6
- module RailsForge
7
- module Generators
8
- # Monitoring generator
9
- class MonitoringGenerator < BaseGenerator
10
- # Initialize the generator
11
- def initialize(name = "monitoring", options = {})
12
- super(name, options)
13
- @sentry_dsn = options[:sentry_dsn] || ""
14
- @environment = options[:environment] || (defined?(Rails) && Rails.env) || 'development'
15
- end
16
-
17
- # Generate monitoring configs
18
- def generate
19
- return "Not in a Rails application directory" unless @base_path
20
-
21
- results = []
22
- results << create_sentry_initializer
23
- results << create_lograge_config
24
- results << create_log_formatter
25
- results << create_environments_config
26
-
27
- results.join("\n")
28
- end
29
-
30
- private
31
-
32
- # Create Sentry initializer
33
- def create_sentry_initializer
34
- init_dir = File.join(@base_path, "config", "initializers")
35
- FileUtils.mkdir_p(init_dir)
36
-
37
- sentry_path = File.join(init_dir, "sentry.rb")
38
- return "Skipping Sentry initializer (already exists)" if File.exist?(sentry_path)
39
-
40
- content = <<~RUBY
41
- # Sentry error tracking configuration
42
- # Install sentry-ruby and add to Gemfile: gem 'sentry-ruby', '~> 4.0'
43
- Sentry.init do |config|
44
- config.dsn = ENV.fetch('SENTRY_DSN', '#{@sentry_dsn}')
45
- config.breadcrumb_logger = :active_support
46
- config.environments = %w[staging production]
47
- config.traces_sample_rate = 0.1
48
- config.before_send = lambda do |event, hint|
49
- # Filter out specific errors
50
- if hint[:exception]
51
- # Add custom filtering logic here
52
- end
53
- event
54
- end
55
- end
56
- RUBY
57
-
58
- File.write(sentry_path, content)
59
- "Created config/initializers/sentry.rb"
60
- end
61
-
62
- # Create Lograge configuration
63
- def create_lograge_config
64
- init_dir = File.join(@base_path, "config", "initializers")
65
- FileUtils.mkdir_p(init_dir)
66
-
67
- lograge_path = File.join(init_dir, "lograge.rb")
68
- return "Skipping Lograge initializer (already exists)" if File.exist?(lograge_path)
69
-
70
- content = <<~RUBY
71
- # Lograge configuration for structured logging
72
- # Add to Gemfile: gem 'lograge'
73
- Rails.application.configure do
74
- config.lograge.enabled = true
75
- config.lograge.base_controller_class = 'ActionController::API'
76
- config.lograge.custom_options = lambda do |event|
77
- {
78
- # Add custom data to logs
79
- host: Socket.gethostname,
80
- pid: Process.pid,
81
- # Add timing data
82
- request_id: event.payload[:request_id],
83
- user_id: event.payload[:user_id]
84
- }
85
- end
86
- config.lograge.formatter = Lograge::Formatters::Json.new
87
- end
88
- RUBY
89
-
90
- File.write(lograge_path, content)
91
- "Created config/initializers/lograge.rb"
92
- end
93
-
94
- # Create log formatter
95
- def create_log_formatter
96
- config_path = File.join(@base_path, "config")
97
-
98
- # Check if application.rb exists
99
- app_rb = File.join(config_path, "application.rb")
100
- return "Not a Rails app" unless File.exist?(app_rb)
101
-
102
- content = File.read(app_rb)
103
-
104
- unless content.include?("config.log_formatter")
105
- # Add log formatter to application.rb
106
- File.write(app_rb, content.gsub(/class Application < Rails::Application/,
107
- "class Application < Rails::Application\n config.log_formatter = proc { |severity, datetime, progname, msg| \"#{datetime.utc_iso8601} #{severity}: #{msg}\\n\" }"))
108
- end
109
-
110
- "Updated application.rb with custom log formatter"
111
- end
112
-
113
- # Create environment-specific configs
114
- def create_environments_config
115
- env_dir = File.join(@base_path, "config", "environments")
116
- return "Not a Rails app" unless Dir.exist?(env_dir)
117
-
118
- results = []
119
-
120
- # Production config
121
- prod_path = File.join(env_dir, "production.rb")
122
- if File.exist?(prod_path)
123
- content = File.read(prod_path)
124
- unless content.include?("Lograge") || content.include?("Sentry")
125
- File.write(prod_path, content + "\n\n# Monitoring\nconfig.lograge.enabled = true\n")
126
- results << "Updated production.rb"
127
- end
128
- end
129
-
130
- results.any? ? results.join("\n") : "No environment updates needed"
131
- end
132
- end
133
- end
134
- end
@@ -1,220 +0,0 @@
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