propel_api 0.2.0 โ 0.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +66 -37
- data/README.md +239 -4
- data/lib/generators/propel_api/core/named_base.rb +92 -1
- data/lib/generators/propel_api/core/relationship_inferrer.rb +4 -11
- data/lib/generators/propel_api/install/install_generator.rb +2 -2
- data/lib/generators/propel_api/resource/resource_generator.rb +205 -63
- data/lib/generators/propel_api/templates/config/propel_api.rb.tt +26 -1
- data/lib/generators/propel_api/templates/controllers/api_controller_graphiti.rb +2 -2
- data/lib/generators/propel_api/templates/controllers/api_controller_propel_facets.rb +20 -10
- data/lib/generators/propel_api/templates/controllers/example_controller.rb.tt +2 -2
- data/lib/generators/propel_api/templates/scaffold/facet_controller_template.rb.tt +34 -9
- data/lib/generators/propel_api/templates/scaffold/facet_model_template.rb.tt +17 -8
- data/lib/generators/propel_api/templates/scaffold/graphiti_controller_template.rb.tt +1 -1
- data/lib/generators/propel_api/templates/scaffold/graphiti_resource_template.rb.tt +2 -2
- data/lib/generators/propel_api/templates/seeds/seeds_template.rb.tt +62 -14
- data/lib/generators/propel_api/templates/tests/controller_test_template.rb.tt +34 -6
- data/lib/generators/propel_api/templates/tests/fixtures_template.yml.tt +58 -15
- data/lib/generators/propel_api/templates/tests/integration_test_template.rb.tt +108 -36
- data/lib/generators/propel_api/templates/tests/model_test_template.rb.tt +20 -0
- data/lib/propel_api.rb +1 -1
- metadata +22 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 224fb8718c35e1b5d828201c8256a39eeedc0cc6f9ad096ac874f34c9a726c25
|
4
|
+
data.tar.gz: 6902529de75450cd89415ea357891100f2c2a2d4cc6c57ba6679257e693aaab3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dcd7b7a650de42cf4d0f19e51e777535e399c7f01dd0947e6ecb97854504a2e1a79abfa0341f7bb2dae4dc128cc9261b0c42060c5218aa6129c465920eeb6546
|
7
|
+
data.tar.gz: 5ee7eace1077821dbb23b93f719d3544447e8a72d5ba0541df8712d55b6294054d2f335aaa4d8bad43e60ea4b69d7737733e4e63bc722bde3ad5fbd2b85a1418
|
data/CHANGELOG.md
CHANGED
@@ -10,19 +10,72 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
10
10
|
### Planned Features
|
11
11
|
- GraphQL adapter support
|
12
12
|
|
13
|
-
## [0.
|
13
|
+
## [0.3.0] - 2025-01-15
|
14
|
+
|
15
|
+
### ๐ Major Features Added
|
16
|
+
- **Full Polymorphic Association Support**: Complete implementation of polymorphic relationships in API resources
|
17
|
+
- New `--parents` command-line option for specifying valid parent models
|
18
|
+
- Automatic generation of correct fixtures, tests, and API parameters
|
19
|
+
- Support for quote-free polymorphic syntax: `field_name:polymorphic`
|
20
|
+
- Enhanced fixture generation using Rails' `fixture_name (ModelName)` syntax
|
21
|
+
|
22
|
+
### โ ๏ธ Breaking Changes
|
23
|
+
- **Generator Syntax Change**: Tenancy associations are not automatically created you must pass organization:references and/or agency:references and configure the tenancy in the PropelApi configurations, any automated workflows or CI/CD that generate resources assuming the organization and/or agency references will be auto-injected will break with generator calls.
|
24
|
+
- **Required --parents Option**: Polymorphic resources now require `--parents field_name:Parent1,Parent2` for proper test generation
|
25
|
+
- **Fixture Format Change**: Polymorphic fixtures now use `field_name: fixture_name (ParentClass)` instead of hardcoded IDs
|
26
|
+
- **Test Template Updates**: All test templates now include polymorphic-aware parameter generation
|
27
|
+
|
28
|
+
### ๐ง Generator Improvements
|
29
|
+
- **Enhanced Resource Generator**:
|
30
|
+
- Added polymorphic syntax conversion (`field_name:polymorphic` โ `field_name:references{polymorphic}`)
|
31
|
+
- Improved argument processing to handle polymorphic parent specifications
|
32
|
+
- Fixed migration generation to use processed attributes instead of raw ARGV
|
33
|
+
- **Smart Fixture References**:
|
34
|
+
- Automatic fixture name resolution (e.g., uses `marketing_agency` instead of `one` for Agency models)
|
35
|
+
- Dynamic parent type selection for varied test data
|
36
|
+
- Proper Rails fixture syntax for polymorphic associations
|
37
|
+
|
38
|
+
### ๐งช Test Generation Enhancements
|
39
|
+
- **Model Tests**:
|
40
|
+
- Polymorphic association validation with proper parent type checking
|
41
|
+
- Automatic setup of polymorphic parent variables (`@field_name`)
|
42
|
+
- Correct assertions for polymorphic relationships
|
43
|
+
- **Controller Tests**:
|
44
|
+
- Automatic inclusion of both `field_name_id` and `field_name_type` in test parameters
|
45
|
+
- Proper polymorphic parent setup in test fixtures
|
46
|
+
- **Integration Tests**:
|
47
|
+
- Enhanced error handling tests with polymorphic parameter support
|
48
|
+
- Multi-tenancy isolation tests work correctly with polymorphic associations
|
49
|
+
- Comprehensive API workflow testing
|
50
|
+
|
51
|
+
### ๐๏ธ Architecture Improvements
|
52
|
+
- **Named Base Enhancements**:
|
53
|
+
- New `polymorphic_associations` helper method
|
54
|
+
- Enhanced `polymorphic_parent_for_fixture` with fixture name resolution
|
55
|
+
- Improved parent type parsing and validation
|
56
|
+
- **Template System**:
|
57
|
+
- All ERB templates now polymorphic-aware
|
58
|
+
- Consistent handling of polymorphic vs. regular references
|
59
|
+
- Better error handling and edge case management
|
60
|
+
|
61
|
+
### ๐ Bug Fixes
|
62
|
+
- **Migration Constraints**: Fixed polymorphic migrations to use `polymorphic: true` instead of incorrect `foreign_key: true`
|
63
|
+
- **Fixture Loading**: Resolved issues with hardcoded IDs causing fixture loading failures
|
64
|
+
- **Test Isolation**: Fixed multi-tenancy tests failing due to missing polymorphic associations
|
65
|
+
- **API Parameter Generation**: Corrected missing `_type` parameters in generated API calls
|
66
|
+
|
67
|
+
## [0.2.1] - 2025-01-14
|
68
|
+
|
69
|
+
### Fixed
|
70
|
+
- **Critical Pagy pagination bug**: Fixed `NoMethodError: undefined method 'items' for Pagy`
|
71
|
+
- API controller templates now use correct `pagy.limit` instead of non-existent `pagy.items`
|
72
|
+
- Fixes pagination metadata generation in API responses
|
73
|
+
- Affects all generated API controllers with pagination
|
74
|
+
- **Dependency update**: Improved compatibility with PropelFacets 0.2.1
|
75
|
+
- API controllers now work correctly with fixed `for_organization` scope installation
|
76
|
+
- Resolves `NoMethodError` when using generated controllers in fresh Rails installations
|
14
77
|
|
15
|
-
|
16
|
-
- **Security-first API architecture**: Complete redesign of tenancy validation flow
|
17
|
-
- Invalid tenancy context (organization_id, agency_id) now returns 403 Forbidden instead of 422 Unprocessable Entity
|
18
|
-
- Security validation occurs before business validation (prevents information disclosure)
|
19
|
-
- Error response structure changed from `{"errors": {...}}` to `{"error": "...", "message": "...", "code": "..."}`
|
20
|
-
- **Controller generation format**: Generated controllers now use foreign key format in permitted_params
|
21
|
-
- `permitted_params :organization` โ `permitted_params :organization_id`
|
22
|
-
- Ensures proper strong parameter filtering for security validation
|
23
|
-
- **Configuration dependency**: `agency_tenancy` configuration moved to PropelAuthentication
|
24
|
-
- Remove `PropelApi.configuration.agency_tenancy` from config files
|
25
|
-
- Agency tenancy now controlled entirely by PropelAuthentication
|
78
|
+
## [0.2.0] - 2025-09-02
|
26
79
|
|
27
80
|
### Added
|
28
81
|
- **Organization-level multi-tenancy security** - Complete data isolation between organizations
|
@@ -31,19 +84,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
31
84
|
- `for_organization(org_id)` scope added to ApplicationRecord base class
|
32
85
|
- Cross-organization data access completely blocked (show, update, delete return 404)
|
33
86
|
- New records automatically assigned to authenticated user's organization
|
34
|
-
- Comprehensive security test suite covering all attack vectors
|
87
|
+
- Comprehensive security test suite with 12 tests covering all attack vectors
|
35
88
|
- Zero impact on existing single-tenant applications
|
36
|
-
- **Configurable auto-assignment**: Integration with PropelAuthentication tenancy configuration
|
37
|
-
- Respects `require_organization_id` and `require_user_id` settings from PropelAuthentication
|
38
|
-
- Helper methods: `require_organization_id?`, `require_user_id?` for configuration access
|
39
|
-
- **Enhanced security validation**: Comprehensive unauthorized access protection
|
40
|
-
- Organization access validation with detailed error codes
|
41
|
-
- User assignment validation for admin delegation scenarios
|
42
|
-
- Agency access validation with proper user permission checking
|
43
|
-
- **Conditional test generation**: Tests now adapt behavior based on PropelAuthentication configuration
|
44
|
-
- Auto-assignment mode: Tests expect 201 Created with proper context assignment
|
45
|
-
- Strict mode: Tests expect 422 Unprocessable Entity when required fields missing
|
46
|
-
- Security tests: Tests expect 403 Forbidden for unauthorized access attempts
|
47
89
|
|
48
90
|
### Fixed
|
49
91
|
- **Authentication namespace conflict resolved** - Renamed authentication concern to prevent module name collision
|
@@ -53,14 +95,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
53
95
|
- Updated PropelFacets and Graphiti API controller templates
|
54
96
|
- Improved method visibility: `authenticate_user`, `current_user`, and `extract_jwt_token` are now public methods
|
55
97
|
- Enhanced flexibility for custom authentication scenarios (email notifications, audit logging, token refresh)
|
56
|
-
- **Attribute introspection**: Fixed foreign key detection for User and other models with associations
|
57
|
-
- Database column introspection now properly generates foreign key format for permitted_params
|
58
|
-
- Association detection preserved for model relationship generation
|
59
|
-
- JSON field handling improved with proper `field: {}` syntax for nested objects
|
60
|
-
- **Test data generation**: Enhanced User model test data generation
|
61
|
-
- Unique email and username generation to prevent fixture conflicts
|
62
|
-
- Proper field names for User model tests (email_address, username, password vs generic title)
|
63
|
-
- Model-specific test data patterns for comprehensive validation coverage
|
64
98
|
|
65
99
|
### Security
|
66
100
|
- **Multi-tenant data isolation** - Zero-trust organization scoping prevents data leaks
|
@@ -71,17 +105,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
71
105
|
- Database-level enforcement via ActiveRecord scopes
|
72
106
|
|
73
107
|
### Improved
|
74
|
-
- **Multi-step security validation**: Three-phase validation for robust security
|
75
|
-
1. Security validation (403 for unauthorized access)
|
76
|
-
2. Auto-assignment (based on configuration)
|
77
|
-
3. Final validation (422 for missing required fields)
|
78
108
|
- **Authentication concern API design** - Better method organization and access patterns
|
79
109
|
- `authenticate_user` - Public method for `before_action` callbacks
|
80
110
|
- `current_user` - Public method for accessing authenticated user
|
81
111
|
- `current_organization_id` - Public method for accessing organization context
|
82
112
|
- `extract_jwt_token` - Public method for custom authentication scenarios
|
83
113
|
- Clean separation between public API and internal implementation
|
84
|
-
- **Template reliability**: Attribute detection using generator attributes instead of database queries during generation
|
85
114
|
|
86
115
|
## [0.1.4] - 2025-08-15
|
87
116
|
|
data/README.md
CHANGED
@@ -49,13 +49,16 @@ After installation, you can remove the gem from your Gemfile. All functionality
|
|
49
49
|
|
50
50
|
```bash
|
51
51
|
# Basic resource with PropelFacets
|
52
|
-
rails generate propel_api User name:string email:string role:string
|
52
|
+
rails generate propel_api:resource User name:string email:string role:string
|
53
53
|
|
54
54
|
# Resource with associations
|
55
|
-
rails generate propel_api Article title:string content:text user:references category:references
|
55
|
+
rails generate propel_api:resource Article title:string content:text user:references category:references
|
56
56
|
|
57
|
-
# Polymorphic associations
|
58
|
-
rails generate propel_api Comment content:text commentable:references
|
57
|
+
# ๐ NEW: Polymorphic associations (v0.3.0)
|
58
|
+
rails generate propel_api:resource Comment content:text commentable:references{polymorphic} --parents commentable:Post,Video,Product
|
59
|
+
|
60
|
+
# Polymorphic with tenancy
|
61
|
+
rails generate propel_api:resource Review rating:integer comment:text review_parent:polymorphic --parents review_parent:Product,Agency
|
59
62
|
|
60
63
|
# With Graphiti adapter
|
61
64
|
rails generate propel_api Product name:string price:decimal --adapter=graphiti
|
@@ -70,6 +73,238 @@ This generates:
|
|
70
73
|
- **Fixtures** with realistic test data
|
71
74
|
- **Seeds** with Faker-generated sample data
|
72
75
|
|
76
|
+
## ๐ Polymorphic Association Support (v0.3.0)
|
77
|
+
|
78
|
+
PropelApi now provides comprehensive support for polymorphic associations with automatic test generation and intelligent fixture management.
|
79
|
+
|
80
|
+
### Quick Start with Polymorphic Resources
|
81
|
+
|
82
|
+
```bash
|
83
|
+
# Generate a Comment that can belong to Posts, Videos, or Products
|
84
|
+
rails generate propel_api:resource Comment body:text commentable:references{polymorphic} --parents commentable:Post,Video,Product
|
85
|
+
|
86
|
+
# Generate a Review with full tenancy support
|
87
|
+
rails generate propel_api:resource Review rating:integer comment:text review_parent:references{polymorphic} --parents reviewable:Product,Agency
|
88
|
+
```
|
89
|
+
|
90
|
+
### Key Features
|
91
|
+
|
92
|
+
#### โจ Simple, Intuitive Syntax
|
93
|
+
- Additional support `field_name:polymorphic` instead of Rails' verbose `field_name:references{polymorphic}`
|
94
|
+
- No need for complex quote escaping or nested syntax
|
95
|
+
|
96
|
+
#### ๐ฏ Smart Parent Specification
|
97
|
+
- `--parents field_name:Parent1,Parent2,Parent3` defines valid parent models
|
98
|
+
- Automatically generates varied test data using different parent types
|
99
|
+
- Validates parent models exist in your application
|
100
|
+
|
101
|
+
#### ๐งช Complete Test Coverage
|
102
|
+
- **Model Tests**: Proper polymorphic association validation and parent type checking
|
103
|
+
- **Controller Tests**: Automatic inclusion of both `_id` and `_type` parameters
|
104
|
+
- **Integration Tests**: Full API workflow testing with polymorphic data
|
105
|
+
- **Fixtures**: Uses Rails' clean `fixture_name (ModelName)` syntax
|
106
|
+
|
107
|
+
#### ๐ง Generated Code Quality
|
108
|
+
```ruby
|
109
|
+
# Generated Model
|
110
|
+
class Comment < ApplicationRecord
|
111
|
+
belongs_to :commentable, polymorphic: true
|
112
|
+
# ... other associations and validations
|
113
|
+
end
|
114
|
+
|
115
|
+
# Generated Migration
|
116
|
+
def change
|
117
|
+
create_table :comments do |t|
|
118
|
+
t.text :body
|
119
|
+
t.references :commentable, polymorphic: true, null: false
|
120
|
+
# ... other fields
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Generated Fixtures (clean Rails syntax)
|
125
|
+
one:
|
126
|
+
commentable: one (Post)
|
127
|
+
body: "Great post!"
|
128
|
+
|
129
|
+
two:
|
130
|
+
commentable: featured_video (Video)
|
131
|
+
body: "Amazing video content!"
|
132
|
+
```
|
133
|
+
|
134
|
+
#### ๐ API-Ready Controllers
|
135
|
+
Controllers automatically include proper parameter handling:
|
136
|
+
```ruby
|
137
|
+
class Api::V1::CommentsController < Api::V1::ApiController
|
138
|
+
permitted_params :body, :commentable_id, :commentable_type
|
139
|
+
end
|
140
|
+
```
|
141
|
+
|
142
|
+
### Breaking Changes from v0.2.x
|
143
|
+
|
144
|
+
โ ๏ธ **Migration Required**: The polymorphic syntax and test generation has been completely rewritten for better reliability and Rails compatibility.
|
145
|
+
|
146
|
+
- **Old**: `rails generate propel_api:resource Comment body:text commentable:references{polymorphic}`
|
147
|
+
- **New**: `rails generate propel_api:resource Comment body:text commentable:polymorphic --parents commentable:Post,Video`
|
148
|
+
|
149
|
+
The new approach provides:
|
150
|
+
- More reliable test generation
|
151
|
+
- Better fixture management
|
152
|
+
- Cleaner, more maintainable code
|
153
|
+
- Full Rails compatibility
|
154
|
+
|
155
|
+
## ๐ API Explorer for Development
|
156
|
+
|
157
|
+
PropelApi includes a comprehensive test application with multiple API resources perfect for development and testing. The dummy app provides a fully functional API with authentication, multi-tenancy, and polymorphic associations.
|
158
|
+
|
159
|
+
### Quick Start with the Test API
|
160
|
+
|
161
|
+
```bash
|
162
|
+
# Navigate to the test application
|
163
|
+
cd test/dummy
|
164
|
+
|
165
|
+
# Set up the database
|
166
|
+
rails db:setup
|
167
|
+
|
168
|
+
# Start the development server
|
169
|
+
rails server
|
170
|
+
|
171
|
+
# Your API is now running at http://localhost:3000
|
172
|
+
```
|
173
|
+
|
174
|
+
### Available API Endpoints
|
175
|
+
|
176
|
+
The dummy app provides these fully functional endpoints:
|
177
|
+
|
178
|
+
#### Authentication
|
179
|
+
- `POST /api/v1/signup` - User registration
|
180
|
+
- `POST /api/v1/login` - User authentication
|
181
|
+
- `GET /api/v1/me` - Current user info
|
182
|
+
- `DELETE /api/v1/logout` - Logout
|
183
|
+
- `POST /api/v1/reset` - Password reset request
|
184
|
+
- `PATCH /api/v1/reset` - Password reset update
|
185
|
+
|
186
|
+
#### Core Resources
|
187
|
+
- `GET|POST /api/v1/users` - User management
|
188
|
+
- `GET|POST /api/v1/organizations` - Organization management
|
189
|
+
- `GET|POST|PATCH|DELETE /api/v1/products` - Product CRUD
|
190
|
+
- `GET|POST|PATCH|DELETE /api/v1/comments` - Comment CRUD
|
191
|
+
- `GET|POST|PATCH|DELETE /api/v1/attachments` - File attachments
|
192
|
+
- `GET|POST|PATCH|DELETE /api/v1/reviews` - Reviews (polymorphic!)
|
193
|
+
|
194
|
+
### Setting Up API Explorer Tools
|
195
|
+
|
196
|
+
#### Option 1: Postman Collection
|
197
|
+
|
198
|
+
Create a Postman collection with these base settings:
|
199
|
+
|
200
|
+
```json
|
201
|
+
{
|
202
|
+
"info": {
|
203
|
+
"name": "PropelApi Development",
|
204
|
+
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
|
205
|
+
},
|
206
|
+
"variable": [
|
207
|
+
{
|
208
|
+
"key": "base_url",
|
209
|
+
"value": "http://localhost:3000/api/v1",
|
210
|
+
"type": "string"
|
211
|
+
},
|
212
|
+
{
|
213
|
+
"key": "auth_token",
|
214
|
+
"value": "",
|
215
|
+
"type": "string"
|
216
|
+
}
|
217
|
+
]
|
218
|
+
}
|
219
|
+
```
|
220
|
+
|
221
|
+
#### Option 2: Insomnia Workspace
|
222
|
+
|
223
|
+
1. Create a new workspace in Insomnia
|
224
|
+
2. Set base URL: `http://localhost:3000/api/v1`
|
225
|
+
3. Create environment variables:
|
226
|
+
- `base_url`: `http://localhost:3000/api/v1`
|
227
|
+
- `auth_token`: (will be populated after login)
|
228
|
+
|
229
|
+
#### Option 3: cURL Scripts
|
230
|
+
|
231
|
+
```bash
|
232
|
+
# Login and get token
|
233
|
+
TOKEN=$(curl -s -X POST http://localhost:3000/api/v1/login \
|
234
|
+
-H "Content-Type: application/json" \
|
235
|
+
-d '{"data": {"email_address": "test@example.com", "password": "password123"}}' \
|
236
|
+
| jq -r '.token')
|
237
|
+
|
238
|
+
# Use token for authenticated requests
|
239
|
+
curl -H "Authorization: Bearer $TOKEN" \
|
240
|
+
-H "Content-Type: application/json" \
|
241
|
+
http://localhost:3000/api/v1/me
|
242
|
+
```
|
243
|
+
|
244
|
+
### API Response Format
|
245
|
+
|
246
|
+
All PropelApi endpoints follow consistent JSON:API-inspired formatting:
|
247
|
+
|
248
|
+
```json
|
249
|
+
{
|
250
|
+
"data": {
|
251
|
+
"id": 1,
|
252
|
+
"name": "Example Product",
|
253
|
+
"price": 99.99,
|
254
|
+
"organization": {
|
255
|
+
"id": 1,
|
256
|
+
"name": "Test Organization"
|
257
|
+
}
|
258
|
+
},
|
259
|
+
"meta": {
|
260
|
+
"total": 1,
|
261
|
+
"page": 1,
|
262
|
+
"limit": 25
|
263
|
+
}
|
264
|
+
}
|
265
|
+
```
|
266
|
+
|
267
|
+
### Testing Polymorphic Associations
|
268
|
+
|
269
|
+
The Reviews resource demonstrates polymorphic associations:
|
270
|
+
|
271
|
+
```bash
|
272
|
+
# Create a review for a product
|
273
|
+
curl -X POST http://localhost:3000/api/v1/reviews \
|
274
|
+
-H "Authorization: Bearer $TOKEN" \
|
275
|
+
-H "Content-Type: application/json" \
|
276
|
+
-d '{
|
277
|
+
"data": {
|
278
|
+
"rating": 5,
|
279
|
+
"comment": "Great product!",
|
280
|
+
"reviewable_id": 1,
|
281
|
+
"reviewable_type": "Product"
|
282
|
+
}
|
283
|
+
}'
|
284
|
+
|
285
|
+
# Create a review for an agency
|
286
|
+
curl -X POST http://localhost:3000/api/v1/reviews \
|
287
|
+
-H "Authorization: Bearer $TOKEN" \
|
288
|
+
-H "Content-Type: application/json" \
|
289
|
+
-d '{
|
290
|
+
"data": {
|
291
|
+
"rating": 4,
|
292
|
+
"comment": "Good service!",
|
293
|
+
"reviewable_id": 1,
|
294
|
+
"reviewable_type": "Agency"
|
295
|
+
}
|
296
|
+
}'
|
297
|
+
```
|
298
|
+
|
299
|
+
### Development Tips
|
300
|
+
|
301
|
+
1. **Seed Data**: Run `rails db:seed` to populate with realistic test data
|
302
|
+
2. **Test User**: Default login is `test@example.com` / `password123`
|
303
|
+
3. **Admin User**: Admin login is `admin@example.com` / `password123`
|
304
|
+
4. **Multi-tenancy**: All resources are scoped to organizations automatically
|
305
|
+
5. **Error Handling**: All endpoints return consistent error formats
|
306
|
+
6. **Validation**: Try invalid data to see validation error responses
|
307
|
+
|
73
308
|
### Generate Controllers for Existing Models
|
74
309
|
|
75
310
|
```bash
|
@@ -93,7 +93,7 @@ module PropelApi
|
|
93
93
|
attributes << attr_data
|
94
94
|
end
|
95
95
|
end
|
96
|
-
|
96
|
+
|
97
97
|
# Look for basic validations that might indicate attributes
|
98
98
|
# Exclude association names (they're already handled above as foreign keys)
|
99
99
|
# NOTE: Only add validated attributes if they weren't already detected by schema introspection
|
@@ -514,5 +514,96 @@ module PropelApi
|
|
514
514
|
|
515
515
|
content
|
516
516
|
end
|
517
|
+
|
518
|
+
# Helper methods for templates to detect tenancy attributes
|
519
|
+
# These are shared between ResourceGenerator and ControllerGenerator
|
520
|
+
def has_organization_reference?
|
521
|
+
return false unless defined?(@attributes) && @attributes
|
522
|
+
@attributes.any? { |attr| attr.name == 'organization' && attr.type == :references }
|
523
|
+
end
|
524
|
+
|
525
|
+
def has_agency_reference?
|
526
|
+
return false unless defined?(@attributes) && @attributes
|
527
|
+
@attributes.any? { |attr| attr.name == 'agency' && attr.type == :references }
|
528
|
+
end
|
529
|
+
|
530
|
+
# Polymorphic associations helper methods
|
531
|
+
def polymorphic_parent_types
|
532
|
+
@polymorphic_parent_types ||= parse_polymorphic_parent_types
|
533
|
+
end
|
534
|
+
|
535
|
+
def polymorphic_associations
|
536
|
+
return [] unless defined?(@attributes) && @attributes
|
537
|
+
|
538
|
+
@polymorphic_associations ||= begin
|
539
|
+
polymorphic_attrs = @attributes.select { |attr| attr.type == :references && attr.respond_to?(:polymorphic?) && attr.polymorphic? }
|
540
|
+
|
541
|
+
polymorphic_attrs.map do |attr|
|
542
|
+
parent_types = polymorphic_parent_types[attr.name.to_s] || discover_available_models.first(1)
|
543
|
+
|
544
|
+
# Create one association entry per polymorphic field with all parent types
|
545
|
+
{
|
546
|
+
field_name: attr.name,
|
547
|
+
id_field: "#{attr.name}_id",
|
548
|
+
type_field: "#{attr.name}_type",
|
549
|
+
parent_types: parent_types,
|
550
|
+
# For fixture generation, we'll use the first parent type for fixture "one", second for "two", etc.
|
551
|
+
primary_parent_type: parent_types.first,
|
552
|
+
primary_parent_table: parent_types.first.underscore.pluralize
|
553
|
+
}
|
554
|
+
end
|
555
|
+
end
|
556
|
+
end
|
557
|
+
|
558
|
+
# Helper method for fixture generation to get the appropriate parent type for each fixture
|
559
|
+
def polymorphic_parent_for_fixture(field_name, fixture_index)
|
560
|
+
poly_assoc = polymorphic_associations.find { |assoc| assoc[:field_name].to_s == field_name.to_s }
|
561
|
+
return nil unless poly_assoc
|
562
|
+
|
563
|
+
parent_types = poly_assoc[:parent_types]
|
564
|
+
parent_type = parent_types[fixture_index % parent_types.length] || parent_types.first
|
565
|
+
|
566
|
+
# Determine the fixture name based on parent type and fixture index
|
567
|
+
fixture_name = case parent_type.underscore
|
568
|
+
when 'agency'
|
569
|
+
['marketing_agency', 'tech_agency', 'sales_agency'][fixture_index] || 'marketing_agency'
|
570
|
+
else
|
571
|
+
['one', 'two', 'three'][fixture_index] || 'one'
|
572
|
+
end
|
573
|
+
|
574
|
+
{
|
575
|
+
id_field: poly_assoc[:id_field],
|
576
|
+
type_field: poly_assoc[:type_field],
|
577
|
+
parent_type: parent_type,
|
578
|
+
parent_table: parent_type.underscore.pluralize,
|
579
|
+
fixture_name: fixture_name
|
580
|
+
}
|
581
|
+
end
|
582
|
+
|
583
|
+
private
|
584
|
+
|
585
|
+
def parse_polymorphic_parent_types
|
586
|
+
return {} unless defined?(options) && options[:parents]
|
587
|
+
|
588
|
+
parsed_types = {}
|
589
|
+
options[:parents].each do |field_name, parent_list|
|
590
|
+
parsed_types[field_name] = parent_list.split(',').map(&:strip).map(&:camelize)
|
591
|
+
end
|
592
|
+
parsed_types
|
593
|
+
end
|
594
|
+
|
595
|
+
def discover_available_models
|
596
|
+
# Auto-discover available models from app/models directory
|
597
|
+
models_dir = File.join(destination_root, 'app/models')
|
598
|
+
return ['Post'] unless File.directory?(models_dir) # Fallback
|
599
|
+
|
600
|
+
model_files = Dir[File.join(models_dir, '*.rb')]
|
601
|
+
model_files.map do |file|
|
602
|
+
File.basename(file, '.rb').camelize
|
603
|
+
end.reject do |model|
|
604
|
+
# Skip common non-domain models
|
605
|
+
%w[ApplicationRecord Concerns].include?(model)
|
606
|
+
end.sort
|
607
|
+
end
|
517
608
|
end
|
518
609
|
end
|
@@ -106,20 +106,13 @@ class RelationshipInferrer
|
|
106
106
|
end
|
107
107
|
|
108
108
|
def polymorphic_belongs_to(attribute)
|
109
|
-
#
|
110
|
-
|
111
|
-
|
112
|
-
base_name = attribute.name.to_s.gsub(/_parent$/, '')
|
113
|
-
elsif attribute.name.to_s.end_with?('able')
|
114
|
-
# commentable -> commentable
|
115
|
-
base_name = attribute.name.to_s
|
116
|
-
else
|
117
|
-
base_name = attribute.name.to_s
|
118
|
-
end
|
109
|
+
# Keep the full attribute name for polymorphic associations
|
110
|
+
# Don't strip the '_parent' suffix - it's needed to match the schema columns
|
111
|
+
association_name = attribute.name.to_s
|
119
112
|
|
120
113
|
# Polymorphic associations default to required (Rails convention)
|
121
114
|
# Add 'optional: true' manually if optional behavior is needed
|
122
|
-
"belongs_to :#{
|
115
|
+
"belongs_to :#{association_name}, polymorphic: true"
|
123
116
|
end
|
124
117
|
|
125
118
|
|
@@ -140,8 +140,8 @@ module PropelApi
|
|
140
140
|
|
141
141
|
def add_propel_facets_gems
|
142
142
|
add_gem_if_missing 'faker', '~> 3.5', 'Realistic seed data generation'
|
143
|
-
add_gem_if_missing 'pagy', '~> 9.
|
144
|
-
add_gem_if_missing 'has_scope', '~> 0.8.
|
143
|
+
add_gem_if_missing 'pagy', '~> 9.4', 'Pagination for Propel Facets API'
|
144
|
+
add_gem_if_missing 'has_scope', '~> 0.8.2', 'Scope filtering for Propel Facets API'
|
145
145
|
add_gem_if_missing 'ransack', '~> 4.0', 'Advanced search for Propel Facets API'
|
146
146
|
|
147
147
|
say "Don't forget to run: bundle install", :yellow
|