propel_api 0.1.1

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 (30) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +59 -0
  3. data/LICENSE +21 -0
  4. data/README.md +320 -0
  5. data/Rakefile +36 -0
  6. data/lib/generators/propel_api/USAGE +8 -0
  7. data/lib/generators/propel_api/controller/controller_generator.rb +208 -0
  8. data/lib/generators/propel_api/core/base.rb +19 -0
  9. data/lib/generators/propel_api/core/configuration_methods.rb +187 -0
  10. data/lib/generators/propel_api/core/named_base.rb +457 -0
  11. data/lib/generators/propel_api/core/path_generation_methods.rb +45 -0
  12. data/lib/generators/propel_api/core/relationship_inferrer.rb +117 -0
  13. data/lib/generators/propel_api/install/install_generator.rb +343 -0
  14. data/lib/generators/propel_api/resource/resource_generator.rb +433 -0
  15. data/lib/generators/propel_api/templates/config/propel_api.rb.tt +149 -0
  16. data/lib/generators/propel_api/templates/controllers/api_controller_graphiti.rb +79 -0
  17. data/lib/generators/propel_api/templates/controllers/api_controller_propel_facets.rb +76 -0
  18. data/lib/generators/propel_api/templates/controllers/example_controller.rb.tt +96 -0
  19. data/lib/generators/propel_api/templates/scaffold/facet_controller_template.rb.tt +80 -0
  20. data/lib/generators/propel_api/templates/scaffold/facet_model_template.rb.tt +141 -0
  21. data/lib/generators/propel_api/templates/scaffold/graphiti_controller_template.rb.tt +82 -0
  22. data/lib/generators/propel_api/templates/scaffold/graphiti_model_template.rb.tt +32 -0
  23. data/lib/generators/propel_api/templates/seeds/seeds_template.rb.tt +493 -0
  24. data/lib/generators/propel_api/templates/tests/controller_test_template.rb.tt +485 -0
  25. data/lib/generators/propel_api/templates/tests/fixtures_template.yml.tt +250 -0
  26. data/lib/generators/propel_api/templates/tests/integration_test_template.rb.tt +487 -0
  27. data/lib/generators/propel_api/templates/tests/model_test_template.rb.tt +252 -0
  28. data/lib/generators/propel_api/unpack/unpack_generator.rb +304 -0
  29. data/lib/propel_api.rb +3 -0
  30. metadata +95 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 39e7f4915254a37e32cd3ceacaac8402a3c0f32768d0169345cf69fdb742d52d
4
+ data.tar.gz: 302f7022de04cd30f8c0efac85267a4e636c175169478600094a7f9c9100c465
5
+ SHA512:
6
+ metadata.gz: f74c378babcf34e7077117ae21720335903589c58e4aeb68800b3abbfe8c621c323c1f0b69d12557e80e27b3c715c9aa5047a8b9c7389c834db884435e6e4cec
7
+ data.tar.gz: 6e93710aad4c65df5822e046239b1ea1a661dd44d7efdef050fd4fcfd734a216e4451150513df75d71f7d21748cabf83d9eb70eced4651270ff8bfa27f230e35
data/CHANGELOG.md ADDED
@@ -0,0 +1,59 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Planned Features
11
+ - GraphQL adapter support
12
+ - API versioning migration tools
13
+ - Advanced relationship inference patterns
14
+ - Custom serialization adapter framework
15
+ - Performance optimization tools
16
+
17
+ ## [0.1.0] - 2025-01-XX
18
+
19
+ ### Added
20
+ - **Self-extracting generator gem architecture** - Install temporarily, extract code, remove dependency
21
+ - **Rails generator system** with install and unpack commands
22
+ - **Dual serialization adapter support** - PropelFacets and Graphiti
23
+ - **Complete API resource generation** including:
24
+ - Models with smart association inference
25
+ - Controllers with full CRUD operations
26
+ - Migrations with proper constraints
27
+ - Routes with configurable namespacing/versioning
28
+ - Comprehensive test suite (model, controller, integration)
29
+ - Realistic seed data using Faker
30
+ - Test fixtures with sample data
31
+
32
+ ### Features
33
+ - **Intelligent relationship inference** - Automatically detects and creates associations
34
+ - **Polymorphic association support** - Handles `commentable:references` and `resource_parent:references` patterns
35
+ - **Configurable API structure** - Customizable namespace and version patterns
36
+ - **PropelFacets integration** - JSON facet system with inheritance and field selection
37
+ - **Graphiti integration** - JSON:API compliant resources with automatic generation
38
+ - **Production-ready features** - Pagination, filtering, authentication integration
39
+ - **Comprehensive testing** - Full test coverage with realistic data
40
+ - **Flexible unpack system** - Extract and customize any component
41
+
42
+ ### Configuration
43
+ - PropelApi configuration system with adapter/namespace/version defaults
44
+ - Command-line option support with priority hierarchy
45
+ - Integration with Propel orchestration system
46
+
47
+ ### Dependencies
48
+ - Rails 7.0+ support
49
+ - Faker integration for realistic seed data
50
+ - Pagy pagination for PropelFacets adapter
51
+ - HasScope filtering for PropelFacets adapter
52
+ - Graphiti ecosystem support for JSON:API adapter
53
+
54
+ ### Documentation
55
+ - Complete installation and usage guide
56
+ - Self-extracting architecture explanation
57
+ - Adapter comparison and selection guide
58
+ - Advanced relationship pattern examples
59
+ - Production deployment considerations
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Propel API Generator
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,320 @@
1
+ # PropelApi
2
+
3
+ A comprehensive Rails generator that creates complete API resources with models, controllers, tests, and realistic seed data. Supports both PropelFacets (JSON Facet) and Graphiti serialization engines with **fixed route insertion** and proper indentation.
4
+
5
+ ## Installation
6
+
7
+ PropelApi is designed as a **self-extracting generator gem**. You install it temporarily, run the generators to extract the code into your application, then remove the gem dependency.
8
+
9
+ ### Step 1: Add to Gemfile as a Path Gem
10
+
11
+ ```ruby
12
+ # In your Gemfile
13
+ gem 'propel_api', path: 'propel_api'
14
+ ```
15
+
16
+ ### Step 2: Bundle Install
17
+
18
+ ```bash
19
+ bundle install
20
+ ```
21
+
22
+ ### Step 3: Unpack the Generator (Optional)
23
+
24
+ If you want to customize the generator templates:
25
+
26
+ ```bash
27
+ rails generate propel_api:unpack
28
+ ```
29
+
30
+ This extracts the generator into `lib/generators/propel_api/` for customization.
31
+
32
+ ### Step 4: Install PropelApi
33
+
34
+ ```bash
35
+ rails generate propel_api:install --adapter=propel_facets
36
+ # or
37
+ rails generate propel_api:install --adapter=graphiti
38
+ ```
39
+
40
+ This installs the API controller base class with your chosen serialization adapter.
41
+
42
+ ### Step 5: Remove Gem Dependency (Optional)
43
+
44
+ After installation, you can remove the gem from your Gemfile. All functionality remains in your application.
45
+
46
+ ## Usage
47
+
48
+ ### Generate Complete API Resources
49
+
50
+ ```bash
51
+ # Basic resource with PropelFacets
52
+ rails generate propel_api User name:string email:string role:string
53
+
54
+ # Resource with associations
55
+ rails generate propel_api Article title:string content:text user:references category:references
56
+
57
+ # Polymorphic associations
58
+ rails generate propel_api Comment content:text commentable:references
59
+
60
+ # With Graphiti adapter
61
+ rails generate propel_api Product name:string price:decimal --adapter=graphiti
62
+ ```
63
+
64
+ This generates:
65
+ - **Model** with associations and facets/resources
66
+ - **Migration** with proper constraints
67
+ - **Controller** with full CRUD operations
68
+ - **Routes** with proper namespacing and **correct indentation**
69
+ - **Tests** (model, controller, integration)
70
+ - **Fixtures** with realistic test data
71
+ - **Seeds** with Faker-generated sample data
72
+
73
+ ### Generate Controllers for Existing Models
74
+
75
+ ```bash
76
+ # Auto-detect model attributes (with warning)
77
+ rails generate propel_api:controller User
78
+
79
+ # Explicitly auto-detect all attributes
80
+ rails generate propel_api:controller User --all-attributes
81
+
82
+ # Specify specific attributes
83
+ rails generate propel_api:controller User name:string email:string
84
+
85
+ # Custom namespace and version
86
+ rails generate propel_api:controller User --namespace=admin_api --version=v2
87
+ ```
88
+
89
+ ### API Controller Usage
90
+
91
+ #### PropelFacets Adapter
92
+ ```ruby
93
+ class Api::V1::UsersController < Api::V1::ApiController
94
+ permitted_params :name, :email, :role
95
+
96
+ connect_facet :short, actions: [:index]
97
+ connect_facet :details, actions: [:show, :create, :update]
98
+ end
99
+ ```
100
+
101
+ #### Graphiti Adapter
102
+ ```ruby
103
+ class Api::V1::UsersController < Api::V1::ApiController
104
+ self.resource = UserResource
105
+ end
106
+ ```
107
+
108
+ ### Configuration Options
109
+
110
+ Configure PropelApi defaults in `config/initializers/propel_api.rb`:
111
+
112
+ ```ruby
113
+ PropelApi.configure do |config|
114
+ # Default serialization adapter: 'propel_facets' or 'graphiti'
115
+ config.adapter = 'propel_facets'
116
+
117
+ # Default API namespace: 'api', 'admin_api', etc.
118
+ config.namespace = 'api'
119
+
120
+ # Default API version: 'v1', 'v2', etc.
121
+ config.version = 'v1'
122
+ end
123
+ ```
124
+
125
+ ## Features
126
+
127
+ ### โœ… Fixed Route Insertion
128
+ - **Proper indentation** - Routes are inserted with correct spacing
129
+ - **Namespace support** - Works with nested namespaces (api/v1)
130
+ - **No duplicates** - Prevents duplicate route insertion
131
+ - **Correct positioning** - Routes inserted in the right location
132
+
133
+ ### Automatic Resource Generation
134
+ - **Smart associations** - Automatically infers relationships from field types
135
+ - **Polymorphic support** - Handles `commentable:references` patterns
136
+ - **Proper constraints** - Makes organization required, others optional
137
+ - **Realistic test data** - Uses Faker for meaningful sample data
138
+
139
+ ### Dual Serialization Support
140
+ - **PropelFacets** - Flexible JSON views with inheritance and facet system
141
+ - **Graphiti** - JSON:API compliant with automatic resource generation
142
+ - **Adapter switching** - Change serialization strategy per project needs
143
+
144
+ ### Complete Test Coverage
145
+ - **Model tests** - Validations, associations, business logic
146
+ - **Controller tests** - CRUD operations, parameter handling
147
+ - **Integration tests** - End-to-end API workflows
148
+ - **Fixtures** - Realistic test data for reliable testing
149
+
150
+ ### Production-Ready Features
151
+ - **Pagination** - Built-in with Pagy (PropelFacets) or Graphiti
152
+ - **Filtering** - HasScope integration for PropelFacets
153
+ - **Authentication** - Ready for PropelAuth integration
154
+ - **Error handling** - Proper JSON error responses
155
+
156
+ ## Self-Extracting Architecture
157
+
158
+ PropelApi follows a self-extracting pattern that provides:
159
+
160
+ - **No runtime dependencies** - all code lives in your application
161
+ - **Full control** - modify any component after installation
162
+ - **No black boxes** - transparent, readable Rails code
163
+ - **Easy maintenance** - standard Rails patterns throughout
164
+
165
+ After installation, you can:
166
+ - Remove the gem from your Gemfile
167
+ - Customize all generated code
168
+ - Maintain and extend functionality independently
169
+ - Switch between PropelFacets and Graphiti adapters
170
+
171
+ ## Advanced Usage
172
+
173
+ ### Custom Namespaces and Versions
174
+ ```bash
175
+ # Admin API with different namespace
176
+ rails generate propel_api:install --namespace=admin_api --version=v2
177
+
178
+ # No namespace/version
179
+ rails generate propel_api:install --namespace=none --version=none
180
+ ```
181
+
182
+ ### Model Attribute Detection
183
+ PropelApi provides intelligent attribute detection with security filtering:
184
+
185
+ ```bash
186
+ # Manual attributes (no filtering)
187
+ rails generate propel_api:controller User name:string email:string
188
+
189
+ # Auto-detect with explicit flag
190
+ rails generate propel_api:controller User --all-attributes
191
+
192
+ # Auto-detect with warning (when no attributes specified)
193
+ rails generate propel_api:controller User
194
+ ```
195
+
196
+ **Security Filtering**: Sensitive attributes are automatically filtered:
197
+ - Passwords, tokens, keys, secrets
198
+ - Timestamps and Rails internals
199
+ - Large content fields
200
+ - Binary data
201
+
202
+ Customize filtering in `config/initializers/propel_api.rb`:
203
+ ```ruby
204
+ PropelApi.attribute_filter.add_sensitive_pattern(/private_.*/)
205
+ PropelApi.attribute_filter.add_excluded_pattern(/legacy_.*/)
206
+ ```
207
+
208
+ ### Relationship Patterns
209
+ ```bash
210
+ # Standard belongs_to/has_many
211
+ rails generate propel_api Article title:string user:references
212
+
213
+ # Polymorphic associations (commentable -> Comment belongs_to :commentable, polymorphic: true)
214
+ rails generate propel_api Comment content:text commentable:references
215
+
216
+ # Resource parent pattern (resource_parent -> Attachment belongs_to :resource, polymorphic: true)
217
+ rails generate propel_api Attachment name:string resource_parent:references
218
+ ```
219
+
220
+ ### Route Generation Examples
221
+
222
+ #### Nested Namespace (api/v1)
223
+ ```ruby
224
+ # Input routes.rb:
225
+ Rails.application.routes.draw do
226
+ namespace :api do
227
+ namespace :v1 do
228
+ # Add your API routes here
229
+ end
230
+ end
231
+ end
232
+
233
+ # After: rails generate propel_api:controller User
234
+ Rails.application.routes.draw do
235
+ namespace :api do
236
+ namespace :v1 do
237
+ resources :users # โ† Correctly indented with 4 spaces
238
+ end
239
+ end
240
+ end
241
+ ```
242
+
243
+ #### Single Namespace
244
+ ```ruby
245
+ # After: rails generate propel_api:controller User --namespace=api --version=none
246
+ Rails.application.routes.draw do
247
+ namespace :api do
248
+ resources :users # โ† Correctly indented with 2 spaces
249
+ end
250
+ end
251
+ ```
252
+
253
+ ### Seed Data Generation
254
+ ```ruby
255
+ # Generated seeds use Faker for realistic data
256
+ User.create!([
257
+ { name: Faker::Name.name, email: Faker::Internet.email, role: 'admin' },
258
+ { name: Faker::Name.name, email: Faker::Internet.email, role: 'user' }
259
+ ])
260
+ ```
261
+
262
+ ## Dependencies
263
+
264
+ ### PropelFacets Adapter
265
+ - `propel_facets` - JSON facet system (install separately)
266
+ - `pagy` - Pagination
267
+ - `has_scope` - Filtering
268
+ - `ransack` - Advanced search
269
+
270
+ ### Graphiti Adapter
271
+ - `graphiti` - JSON:API resource framework
272
+ - `graphiti-rails` - Rails integration
273
+ - `vandal_ui` - Interactive API documentation
274
+
275
+ ## Route Insertion Technical Details
276
+
277
+ PropelApi includes **completely fixed route insertion** that handles:
278
+
279
+ ### Indentation Rules
280
+ - **Nested namespaces** (api/v1): 4 spaces for resources
281
+ - **Single namespaces** (api): 2 spaces for resources
282
+ - **Rails route method**: Automatically adds 2 spaces to each line
283
+
284
+ ### Insertion Logic
285
+ - Detects existing namespace structures
286
+ - Inserts at correct position (after namespace opening)
287
+ - Prevents duplicate routes
288
+ - Maintains proper Rails formatting
289
+
290
+ ### Error Prevention
291
+ - Validates route placement before insertion
292
+ - Shows warnings for duplicate routes
293
+ - Maintains file structure integrity
294
+
295
+ ## Documentation
296
+
297
+ After installation:
298
+ - API examples: `doc/api_controller_example.rb`
299
+ - Configuration: `config/initializers/propel_api.rb`
300
+ - Generated tests show usage patterns
301
+ - Seed files demonstrate data creation
302
+
303
+ ## Development
304
+
305
+ ```bash
306
+ # Run generator tests
307
+ cd propel_api
308
+ bundle exec rake test
309
+
310
+ # Test route insertion specifically
311
+ bundle exec ruby -Ilib:test test/generators/propel_api/route_insertion_test.rb
312
+ ```
313
+
314
+ ## Contributing
315
+
316
+ Bug reports and pull requests are welcome on GitHub.
317
+
318
+ ## License
319
+
320
+ The gem is available as open source under the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "test"
8
+ t.libs << "lib"
9
+ t.test_files = FileList["test/**/*_test.rb"]
10
+ t.verbose = true
11
+ end
12
+
13
+ # Individual test tasks for better organization
14
+ namespace :test do
15
+ Rake::TestTask.new(:generators) do |t|
16
+ t.libs << "test"
17
+ t.libs << "lib"
18
+ t.test_files = FileList["test/generators/**/*_test.rb"]
19
+ t.description = "Run generator tests"
20
+ end
21
+
22
+ Rake::TestTask.new(:integration) do |t|
23
+ t.libs << "test"
24
+ t.libs << "lib"
25
+ t.test_files = FileList["test/integration/**/*_test.rb"]
26
+ t.description = "Run integration tests"
27
+ end
28
+ end
29
+
30
+ task default: :test
31
+
32
+ desc "Run all tests with verbose output"
33
+ task :test_verbose do
34
+ ENV['VERBOSE'] = 'true'
35
+ Rake::Task[:test].invoke
36
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Explain the generator
3
+
4
+ Example:
5
+ bin/rails generate propel_api Thing
6
+
7
+ This will create:
8
+ what/will/it/create
@@ -0,0 +1,208 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../core/named_base'
4
+ require 'ostruct'
5
+
6
+ ##
7
+ # PropelApi controller generator that creates API controllers, routes, and tests for existing models
8
+ #
9
+ # Usage:
10
+ # rails generate propel_api:controller User # Auto-introspect (with warning)
11
+ # rails generate propel_api:controller User --all-attributes # Auto-introspect (explicit)
12
+ # rails generate propel_api:controller User name:string # Use specified attributes
13
+ # rails generate propel_api:controller User --namespace=admin_api --version=v2
14
+ #
15
+ # Attribute Detection Priority:
16
+ # 1. --all-attributes flag โ†’ Always introspect model attributes (with configurable filtering)
17
+ # 2. Manual attributes โ†’ Use specified attributes (no filtering applied)
18
+ # 3. No attributes + model exists โ†’ Auto-introspect with educational warning (with configurable filtering)
19
+ # 4. No attributes + no model โ†’ Error (model must exist)
20
+ #
21
+ # Configurable Security Filtering:
22
+ # Filtering is controlled by PropelApi.attribute_filter in config/initializers/propel_api.rb
23
+ # - Sensitive patterns: passwords, tokens, keys, SSNs, etc.
24
+ # - Excluded patterns: timestamps, Rails internals, binary data
25
+ # - Large content patterns: descriptions, content, body text, etc.
26
+ #
27
+ # Customize for your project's naming conventions:
28
+ # PropelApi.attribute_filter.add_sensitive_pattern(/private_.*/)
29
+ # PropelApi.attribute_filter.add_excluded_pattern(/legacy_.*/)
30
+ #
31
+ # View current patterns: PropelApi.attribute_filter.filtering_summary
32
+ #
33
+ # This generator assumes the model already exists and creates:
34
+ # - API controller with full CRUD operations
35
+ # - Routes with proper namespacing
36
+ # - Controller tests
37
+ # - Integration tests
38
+ #
39
+ module PropelApi
40
+ class ControllerGenerator < PropelApi::NamedBase
41
+ source_root File.expand_path("../templates", __dir__)
42
+
43
+ desc "Generate PropelApi controller, routes and tests for existing model"
44
+
45
+ argument :attributes, type: :array, default: [], banner: "field:type field:type"
46
+
47
+ def validate_model_exists
48
+ # Ensure attributes are parsed before validation
49
+ parse_attributes_from_args
50
+
51
+ # Only require model when auto-introspection is needed
52
+ model_file_exists = File.exist?(File.join(destination_root, "app/models/#{file_name}.rb"))
53
+
54
+ if should_auto_introspect? && !model_file_exists
55
+ raise Thor::Error, "Model #{class_name} does not exist. Please create the model first or use 'rails generate propel_api #{class_name}' to create the complete resource."
56
+ end
57
+
58
+ # Show educational warning when no explicit choice is made
59
+ if !options[:all_attributes] && (@attributes.nil? || @attributes.empty?) && model_file_exists
60
+ show_auto_introspection_warning
61
+ end
62
+ # Validate attributes if not using introspection
63
+ validate_attributes_exist unless should_auto_introspect?
64
+ end
65
+
66
+ def create_controller
67
+ # Use shared method from Base class
68
+ create_propel_controller
69
+ end
70
+
71
+ def create_routes
72
+ # Use shared method from Base class
73
+ create_propel_routes
74
+ end
75
+
76
+ def create_tests
77
+ # Use shared method from Base class with controller and integration tests only
78
+ create_propel_tests(test_types: [:controller, :integration])
79
+ end
80
+
81
+ def show_completion_message
82
+ # Use shared completion message framework from Base class
83
+ generated_files = [
84
+ "๐ŸŽฎ Controller: app/controllers/#{controller_path}/#{controller_file_name}.rb",
85
+ "๐Ÿงช Controller Tests: test/controllers/#{controller_path}/#{controller_file_name}_test.rb",
86
+ "๐Ÿงช Integration Tests: test/integration/#{file_name}_api_test.rb"
87
+ ]
88
+
89
+ next_steps = [
90
+ "Test your API: GET #{api_route_path}",
91
+ "Run tests: rails test test/controllers/#{controller_path}/#{controller_file_name}_test.rb",
92
+ "Run integration tests: rails test test/integration/#{file_name}_api_test.rb"
93
+ ]
94
+
95
+ if @adapter == 'propel_facets'
96
+ next_steps << "Customize facets in: app/models/#{file_name}.rb"
97
+ end
98
+
99
+ show_propel_completion_message(
100
+ resource_type: "Controller",
101
+ generated_files: generated_files,
102
+ next_steps: next_steps
103
+ )
104
+ end
105
+
106
+ private
107
+
108
+ def route_name
109
+ file_name.pluralize
110
+ end
111
+
112
+ # Controller generator helper methods
113
+ def attributes
114
+ if should_auto_introspect?
115
+ # Auto-introspection: either --all-attributes or no attributes specified
116
+ # Return introspected attributes as attribute-like objects for template compatibility
117
+ introspect_model_attributes.map do |attr|
118
+ OpenStruct.new(name: attr[:name], type: attr[:type])
119
+ end
120
+ else
121
+ # Manual attributes specified: use those
122
+ # Return cached parsed attributes, or parse them if not done yet
123
+ @parsed_attributes || parse_attributes_from_args
124
+ end
125
+ end
126
+
127
+ def permitted_param_names
128
+ if should_auto_introspect?
129
+ # Auto-introspection: either --all-attributes or no attributes specified
130
+ introspected_permitted_params
131
+ else
132
+ # Manual attributes specified: use those
133
+ attributes.map do |attr|
134
+ # Convert references to foreign key names for permitted params
135
+ if attr.type == :references
136
+ "#{attr.name}_id"
137
+ else
138
+ attr.name
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+ def parse_attributes_from_args
145
+ return [] unless @attributes
146
+
147
+ @parsed_attributes ||= @attributes.map do |attr_string|
148
+ # Parse "field:type" strings into attribute objects
149
+ if attr_string.include?(':')
150
+ name, type = attr_string.split(':', 2)
151
+ OpenStruct.new(name: name, type: type.to_sym)
152
+ else
153
+ # Default to string type if no type specified
154
+ OpenStruct.new(name: attr_string, type: :string)
155
+ end
156
+ end
157
+ end
158
+
159
+ def show_auto_introspection_warning
160
+ say "\n" + "="*70, :yellow
161
+ say "โš ๏ธ No attributes specified - auto-detecting from #{class_name} model", :yellow
162
+ say "="*70, :yellow
163
+
164
+ introspected_attrs = introspected_permitted_params
165
+ say "๐Ÿ” Detected attributes: #{introspected_attrs.join(', ')}", :cyan
166
+
167
+ # Show filtering information
168
+ show_filtering_info
169
+
170
+ say "\n๐Ÿ’ก Best practice: Be explicit about your intent:", :green
171
+ say " Auto-detect all: rails g propel_api:controller #{class_name} --all-attributes", :green
172
+ say " Specify some: rails g propel_api:controller #{class_name} name:string email:string", :green
173
+ say "="*70, :yellow
174
+ say ""
175
+ end
176
+
177
+ def show_filtering_info
178
+ say "\nโš ๏ธ SECURITY NOTE:", :red
179
+ say " Sensitive attributes are automatically filtered using configurable patterns.", :red
180
+
181
+ # Try to show current filter configuration
182
+ begin
183
+ if defined?(PropelApi) && PropelApi.respond_to?(:attribute_filter)
184
+ filter = PropelApi.attribute_filter
185
+ total_patterns = filter.sensitive_patterns.size + filter.excluded_patterns.size + filter.large_content_patterns.size
186
+ say " Active filtering patterns: #{total_patterns} (#{filter.sensitive_patterns.size} sensitive, #{filter.excluded_patterns.size} excluded, #{filter.large_content_patterns.size} large content)", :red
187
+ say " ๐Ÿ“‹ View patterns: PropelApi.attribute_filter.filtering_summary", :cyan
188
+ say " ๐Ÿ”ง Customize in: config/initializers/propel_api.rb", :cyan
189
+ else
190
+ say " Using fallback patterns (configure in config/initializers/propel_api.rb)", :red
191
+ end
192
+ rescue => e
193
+ say " Using fallback patterns (PropelApi configuration not available)", :red
194
+ end
195
+
196
+ say " ๐Ÿšจ Review filtering to ensure it matches your naming conventions!", :red
197
+ end
198
+
199
+ def should_auto_introspect?
200
+ # Auto-introspect when:
201
+ # 1. --all-attributes is explicitly passed (takes precedence over manual attributes)
202
+ # 2. No attributes specified AND model exists (auto-fallback with warning)
203
+ options[:all_attributes] || ((@attributes.nil? || @attributes.empty?) && model_exists?)
204
+ end
205
+
206
+ public
207
+ end
208
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'configuration_methods'
4
+ require_relative 'path_generation_methods'
5
+
6
+ ##
7
+ # Base class for all PropelApi generators
8
+ # Provides shared configuration detection, validation, and path generation logic
9
+ #
10
+ module PropelApi
11
+ class Base < Rails::Generators::Base
12
+ include PropelApi::ConfigurationMethods
13
+ include PropelApi::PathGenerationMethods
14
+
15
+
16
+
17
+ private
18
+ end
19
+ end