elaine_crud 0.1.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 (55) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/LICENSE +21 -0
  4. data/README.md +225 -0
  5. data/Rakefile +9 -0
  6. data/TODO.md +496 -0
  7. data/app/controllers/elaine_crud/base_controller.rb +228 -0
  8. data/app/helpers/elaine_crud/base_helper.rb +787 -0
  9. data/app/helpers/elaine_crud/search_helper.rb +132 -0
  10. data/app/javascript/controllers/dropdown_controller.js +18 -0
  11. data/app/views/elaine_crud/base/_edit_row.html.erb +60 -0
  12. data/app/views/elaine_crud/base/_export_button.html.erb +88 -0
  13. data/app/views/elaine_crud/base/_foreign_key_select_refresh.html.erb +52 -0
  14. data/app/views/elaine_crud/base/_form.html.erb +45 -0
  15. data/app/views/elaine_crud/base/_form_fields.html.erb +45 -0
  16. data/app/views/elaine_crud/base/_index_table.html.erb +58 -0
  17. data/app/views/elaine_crud/base/_modal.html.erb +71 -0
  18. data/app/views/elaine_crud/base/_pagination.html.erb +110 -0
  19. data/app/views/elaine_crud/base/_per_page_selector.html.erb +30 -0
  20. data/app/views/elaine_crud/base/_search_bar.html.erb +75 -0
  21. data/app/views/elaine_crud/base/_show_details.html.erb +29 -0
  22. data/app/views/elaine_crud/base/_view_row.html.erb +96 -0
  23. data/app/views/elaine_crud/base/edit.html.erb +51 -0
  24. data/app/views/elaine_crud/base/index.html.erb +74 -0
  25. data/app/views/elaine_crud/base/new.html.erb +12 -0
  26. data/app/views/elaine_crud/base/new_modal.html.erb +37 -0
  27. data/app/views/elaine_crud/base/not_found.html.erb +49 -0
  28. data/app/views/elaine_crud/base/show.html.erb +32 -0
  29. data/docs/ARCHITECTURE.md +410 -0
  30. data/docs/CSS_GRID_LAYOUT.md +126 -0
  31. data/docs/DEMO.md +693 -0
  32. data/docs/DSL_EXAMPLES.md +313 -0
  33. data/docs/FOREIGN_KEY_EXAMPLE.rb +100 -0
  34. data/docs/FOREIGN_KEY_SUPPORT.md +197 -0
  35. data/docs/HAS_MANY_IMPLEMENTATION.md +154 -0
  36. data/docs/LAYOUT_EXAMPLES.md +301 -0
  37. data/docs/TROUBLESHOOTING.md +170 -0
  38. data/elaine_crud.gemspec +46 -0
  39. data/lib/elaine_crud/dsl_methods.rb +348 -0
  40. data/lib/elaine_crud/engine.rb +37 -0
  41. data/lib/elaine_crud/export_handling.rb +164 -0
  42. data/lib/elaine_crud/field_configuration.rb +422 -0
  43. data/lib/elaine_crud/field_configuration_methods.rb +152 -0
  44. data/lib/elaine_crud/layout_calculation.rb +55 -0
  45. data/lib/elaine_crud/parameter_handling.rb +48 -0
  46. data/lib/elaine_crud/record_fetching.rb +150 -0
  47. data/lib/elaine_crud/relationship_handling.rb +220 -0
  48. data/lib/elaine_crud/routing.rb +33 -0
  49. data/lib/elaine_crud/search_and_filtering.rb +285 -0
  50. data/lib/elaine_crud/sorting_concern.rb +65 -0
  51. data/lib/elaine_crud/version.rb +5 -0
  52. data/lib/elaine_crud.rb +25 -0
  53. data/lib/tasks/demo.rake +111 -0
  54. data/lib/tasks/spec.rake +26 -0
  55. metadata +264 -0
@@ -0,0 +1,154 @@
1
+ # has_many Relationship Implementation
2
+
3
+ This document describes the implementation of `has_many` relationship support in ElaineCrud using filtered flat resources (URLs like `/meetings?meeting_room_id=4`).
4
+
5
+ ## Implementation Summary
6
+
7
+ The has_many implementation adds the following features:
8
+
9
+ ### 1. Automatic Detection
10
+ - ElaineCrud automatically detects all `has_many` relationships in your ActiveRecord models
11
+ - Auto-configures display fields for related records
12
+ - Includes automatic query optimization with `includes()` to prevent N+1 queries
13
+
14
+ ### 2. Parent Filtering
15
+ - Supports URLs like `/meetings?meeting_room_id=4` to show filtered views
16
+ - Automatically filters records based on parent relationship parameters
17
+ - Maintains parent context in forms and redirects
18
+
19
+ ### 3. Smart Display
20
+ - **Index Views**: Shows relationship summaries with counts and previews
21
+ - **Links**: Automatically generates links to filtered views (e.g., "5 meetings: Daily Standup, Team Review...")
22
+ - **Forms**: Pre-populates parent relationships when creating from filtered context
23
+
24
+ ### 4. UI Enhancements
25
+ - Context-aware breadcrumbs showing the parent record
26
+ - "View All" links to remove filters
27
+ - Parent information display in forms
28
+
29
+ ## Usage Examples
30
+
31
+ ### Automatic Configuration (No Code Required)
32
+
33
+ ```ruby
34
+ class MeetingRoomsController < ElaineCrud::BaseController
35
+ model MeetingRoom
36
+ permit_params :name, :capacity, :building
37
+ # has_many :meetings relationship automatically detected and configured
38
+ end
39
+
40
+ class MeetingsController < ElaineCrud::BaseController
41
+ model Meeting
42
+ permit_params :title, :start_time, :end_time, :meeting_room_id
43
+ # Automatic parent filtering support - no additional configuration needed
44
+ end
45
+ ```
46
+
47
+ ### Manual Configuration (Optional)
48
+
49
+ ```ruby
50
+ class MeetingRoomsController < ElaineCrud::BaseController
51
+ model MeetingRoom
52
+ permit_params :name, :capacity, :building
53
+
54
+ # Optional: Customize has_many relationship display
55
+ has_many_relation :meetings do
56
+ title "Room Meetings"
57
+ display :title
58
+ show_count true
59
+ max_preview_items 3
60
+ scope -> { where('start_time > ?', Time.current) }
61
+ end
62
+ end
63
+ ```
64
+
65
+ ## Generated URLs and Behavior
66
+
67
+ ```ruby
68
+ # MeetingRoom index page shows:
69
+ # Name | Capacity | Meetings
70
+ # Room A | 20 | 5 meetings: Daily Standup, Team Review, All Hands
71
+ # Room B | 10 | 2 meetings: 1:1 Meeting, Code Review
72
+ ```
73
+
74
+ Clicking "5 meetings: Daily Standup, Team Review..." generates:
75
+ - URL: `/meetings?meeting_room_id=4`
76
+ - Shows filtered view with context banner
77
+ - "New Meeting" button pre-populates `meeting_room_id=4`
78
+ - After creating, redirects back to filtered view
79
+
80
+ ## Technical Implementation
81
+
82
+ ### Controller Changes
83
+ - **BaseController**: Added parent filtering logic in `fetch_records`
84
+ - **Auto-detection**: `auto_configure_has_many_relationships` method
85
+ - **Context management**: `@parent_context` instance variable for UI
86
+ - **Query optimization**: Enhanced `get_all_relationship_includes`
87
+
88
+ ### Field Configuration
89
+ - **FieldConfiguration**: Added `has_many_config` attribute and methods
90
+ - **Display logic**: `render_has_many_display` method for relationship summaries
91
+ - **DSL support**: Block-style configuration with `has_many_relation`
92
+
93
+ ### Helper Methods
94
+ - **BaseHelper**: Enhanced `display_field_value` to handle has_many
95
+ - **Link generation**: Automatic URL generation for filtered views
96
+ - **Relationship detection**: `is_has_many_relationship?` helper
97
+
98
+ ### View Templates
99
+ - **Index**: Parent context banner with breadcrumbs
100
+ - **Forms**: Hidden fields and context information for parent relationships
101
+ - **Styling**: TailwindCSS classes for consistent UI
102
+
103
+ ## Configuration Options
104
+
105
+ | Option | Type | Description | Default |
106
+ |--------|------|-------------|---------|
107
+ | `display` | Symbol/Proc | Field or method to display | Auto-detected (name, title, etc.) |
108
+ | `show_count` | Boolean | Show count in relationship display | `true` |
109
+ | `max_preview_items` | Integer | Number of items to preview | `3` |
110
+ | `scope` | Proc | Limits displayed relationships | `-> { all }` |
111
+ | `foreign_key` | Symbol | The foreign key field name | Auto-detected |
112
+
113
+ ## Supported URL Patterns
114
+
115
+ ```ruby
116
+ # All supported URL patterns:
117
+ /meeting_rooms # All meeting rooms
118
+ /meeting_rooms/4 # Show specific meeting room
119
+ /meetings # All meetings
120
+ /meetings?meeting_room_id=4 # Meetings filtered by room
121
+ /meetings/new # Create new meeting
122
+ /meetings/new?meeting_room_id=4 # Create meeting for specific room
123
+ /meetings/123?meeting_room_id=4 # Show meeting in room context
124
+ ```
125
+
126
+ ## Migration from Manual Configuration
127
+
128
+ If you previously configured has_many relationships manually, ElaineCrud respects existing configurations:
129
+
130
+ ```ruby
131
+ # Your existing configuration takes precedence
132
+ has_many_relation :meetings do
133
+ display :custom_title
134
+ show_count false
135
+ end
136
+ # Auto-detection skips this field since it's already configured
137
+ ```
138
+
139
+ ## Performance Considerations
140
+
141
+ - **Automatic Includes**: Related models are automatically included in queries
142
+ - **Lazy Loading**: Relationship counts and previews are loaded only when displayed
143
+ - **Query Optimization**: Uses single queries with joins rather than N+1 patterns
144
+ - **Caching**: Consider adding Rails caching for frequently accessed relationship displays
145
+
146
+ ## Error Handling
147
+
148
+ ElaineCrud handles various error scenarios gracefully:
149
+ - **Missing Parent Record**: Shows error message with record ID
150
+ - **Configuration Errors**: Falls back to basic display in production
151
+ - **Missing Display Fields**: Uses fallback display methods
152
+ - **Database Errors**: Logs errors and shows user-friendly messages
153
+
154
+ This implementation provides a powerful, automatic has_many relationship system that works out-of-the-box while still allowing for extensive customization when needed.
@@ -0,0 +1,301 @@
1
+ # ElaineCrud Layout System
2
+
3
+ ElaineCrud now supports a flexible layout system that allows you to customize how ActiveRecord items are displayed in a grid format.
4
+
5
+ ## Overview
6
+
7
+ The layout system introduces two main concepts:
8
+
9
+ 1. **Layout Structure**: A nested array where the first dimension represents rows and the second dimension represents columns within each row
10
+ 2. **Layout Header**: An array of configuration objects defining column widths, titles, and sorting behavior
11
+
12
+ ## Default Behavior
13
+
14
+ By default, ElaineCrud displays all fields in a single row with equal column distribution:
15
+
16
+ ```ruby
17
+ class PeopleController < ElaineCrud::BaseController
18
+ model Person
19
+ permit_params :name, :email, :bio, :status
20
+
21
+ field :name, title: "Full Name"
22
+ field :email, title: "Email Address"
23
+ field :bio, title: "Biography"
24
+ field :status, title: "Status"
25
+ end
26
+ ```
27
+
28
+ This will create a layout like:
29
+ ```
30
+ | Name (25%) | Email (25%) | Bio (25%) | Status (25%) |
31
+ ```
32
+
33
+ ## Custom Layouts
34
+
35
+ You can override the `calculate_layout` and `calculate_layout_header` methods to create custom layouts:
36
+
37
+ ### Example 1: Two-Row Layout
38
+
39
+ ```ruby
40
+ class PeopleController < ElaineCrud::BaseController
41
+ model Person
42
+ permit_params :name, :email, :bio, :status, :created_at
43
+
44
+ field :name, title: "Full Name"
45
+ field :email, title: "Email Address"
46
+ field :bio, title: "Biography"
47
+ field :status, title: "Status"
48
+ field :created_at, title: "Joined", visible: true
49
+
50
+ private
51
+
52
+ # Custom layout: Name and Email on first row, Bio and metadata on second row
53
+ def calculate_layout(content, fields)
54
+ [
55
+ [
56
+ { field_name: :name, colspan: 1 },
57
+ { field_name: :email, colspan: 1 },
58
+ { field_name: :status, colspan: 1 }
59
+ ],
60
+ [
61
+ { field_name: :bio, colspan: 2 },
62
+ { field_name: :created_at, colspan: 1 }
63
+ ]
64
+ ]
65
+ end
66
+
67
+ # Custom header: Define column sizes
68
+ def calculate_layout_header(fields)
69
+ ["25%", "35%", "25%", "15%"] # 4 columns total
70
+ end
71
+ end
72
+ ```
73
+
74
+ ### Example 2: Conditional Layout Based on Content
75
+
76
+ ```ruby
77
+ class ProductController < ElaineCrud::BaseController
78
+ model Product
79
+ permit_params :name, :price, :description, :category, :image_url, :featured
80
+
81
+ private
82
+
83
+ # Different layouts for featured vs regular products
84
+ def calculate_layout(content, fields)
85
+ if content.featured?
86
+ # Featured products get a prominent layout
87
+ [
88
+ [
89
+ { field_name: :name, colspan: 2 },
90
+ { field_name: :price, colspan: 1 }
91
+ ],
92
+ [
93
+ { field_name: :description, colspan: 3 }
94
+ ],
95
+ [
96
+ { field_name: :category, colspan: 1 },
97
+ { field_name: :image_url, colspan: 2 }
98
+ ]
99
+ ]
100
+ else
101
+ # Regular products use compact layout
102
+ [
103
+ [
104
+ { field_name: :name, colspan: 1 },
105
+ { field_name: :price, colspan: 1 },
106
+ { field_name: :category, colspan: 1 }
107
+ ]
108
+ ]
109
+ end
110
+ end
111
+
112
+ def calculate_layout_header(fields)
113
+ ["40%", "20%", "40%"] # Flexible 3-column grid
114
+ end
115
+ end
116
+ ```
117
+
118
+ ### Example 3: Complex Multi-Row Layout with Spans
119
+
120
+ ```ruby
121
+ class OrderController < ElaineCrud::BaseController
122
+ model Order
123
+ permit_params :order_number, :customer_name, :total, :status, :notes, :created_at
124
+
125
+ private
126
+
127
+ def calculate_layout(content, fields)
128
+ [
129
+ [
130
+ { field_name: :order_number, colspan: 1 },
131
+ { field_name: :customer_name, colspan: 2 },
132
+ { field_name: :total, colspan: 1 }
133
+ ],
134
+ [
135
+ { field_name: :status, colspan: 1 },
136
+ { field_name: :created_at, colspan: 1 },
137
+ { field_name: :notes, colspan: 2 } # Notes span 2 columns
138
+ ]
139
+ ]
140
+ end
141
+
142
+ def calculate_layout_header(fields)
143
+ ["15%", "35%", "25%", "25%"]
144
+ end
145
+ end
146
+ ```
147
+
148
+ ## Layout Configuration Properties
149
+
150
+ Each column configuration object in the layout can have the following properties:
151
+
152
+ - `field_name`: **Required** - The name of the field to display
153
+ - `colspan`: **Optional** - Number of columns this field should span (default: 1)
154
+ - `rowspan`: **Optional** - Number of rows this field should span (default: 1)
155
+ - Future properties can be added as needed
156
+
157
+ ## Method Signatures
158
+
159
+ ### calculate_layout(content, fields)
160
+
161
+ - **content**: The ActiveRecord object for the current row
162
+ - **fields**: Array of field names that should be included in the layout
163
+ - **Returns**: Array of arrays, where each sub-array represents a row of column configurations
164
+
165
+ ### calculate_layout_header(fields)
166
+
167
+ - **fields**: Array of field names that should be included in the layout
168
+ - **Returns**: Array of header configuration objects with width, field_name, and/or title properties
169
+
170
+ ## CSS Grid Integration
171
+
172
+ The layout system generates CSS Grid structures that automatically handle:
173
+
174
+ - Column sizing based on `calculate_layout_header`
175
+ - Column and row spanning based on layout configuration
176
+ - Responsive behavior using CSS Grid's built-in capabilities
177
+ - Proper alignment and spacing
178
+
179
+ ## Migration from Existing Configurations
180
+
181
+ **Breaking Change**: The `grid_column_span` and `grid_row_span` field configuration options have been removed in favor of the more powerful layout system.
182
+
183
+ **Before (deprecated)**:
184
+ ```ruby
185
+ field :bio, grid_column_span: 2
186
+ field :comments, grid_column_span: 3
187
+ ```
188
+
189
+ **After (new layout system)**:
190
+ ```ruby
191
+ private
192
+
193
+ def calculate_layout(content, fields)
194
+ [
195
+ [
196
+ { field_name: :name, colspan: 1 },
197
+ { field_name: :email, colspan: 1 },
198
+ { field_name: :status, colspan: 1 }
199
+ ],
200
+ [
201
+ { field_name: :bio, colspan: 2 },
202
+ { field_name: :comments, colspan: 1 }
203
+ ]
204
+ ]
205
+ end
206
+
207
+ def calculate_layout_header(fields)
208
+ [
209
+ { width: "25%", field_name: :name }, # Sortable column
210
+ { width: "25%", field_name: :email }, # Sortable column
211
+ { width: "25%", title: "Personal Info" }, # Custom title, not sortable
212
+ { width: "25%" } # Empty column
213
+ ]
214
+ end
215
+ ```
216
+
217
+ This provides much more flexibility and control over your layouts.
218
+
219
+ ## Header Configuration
220
+
221
+ Each header configuration object can contain:
222
+
223
+ - `width`: **Required** - CSS width value (e.g., "25%", "200px", "1fr")
224
+ - `field_name`: **Optional** - Field name to display and enable sorting
225
+ - `title`: **Optional** - Custom column title (overrides field title)
226
+
227
+ ### Header Examples
228
+
229
+ ```ruby
230
+ # Field-based sortable column
231
+ { width: "30%", field_name: :name }
232
+
233
+ # Custom title with field sorting
234
+ { width: "25%", field_name: :created_at, title: "Created" }
235
+
236
+ # Custom title without field (not sortable)
237
+ { width: "20%", title: "Category Info" }
238
+
239
+ # Empty header column
240
+ { width: "10%" }
241
+ ```
242
+
243
+ ### Sorting Behavior
244
+
245
+ - **Sortable**: Columns with `field_name` get sorting links and indicators
246
+ - **Non-sortable**: Columns without `field_name` display plain text
247
+ - **Custom titles**: Use `title` to override the field's configured title
248
+
249
+ ## Best Practices
250
+
251
+ 1. **Keep it Simple**: Start with the default layout and only customize when you have specific layout requirements
252
+ 2. **Consistent Headers**: Make sure your `calculate_layout_header` returns the right number of columns for your layout
253
+ 3. **Responsive Design**: Use percentage or `fr` units in your header layout for responsive behavior
254
+ 4. **Test Edge Cases**: Consider how your layout handles missing data or varying content lengths
255
+ 5. **Performance**: The layout methods are called for every record, so keep them efficient
256
+
257
+ ## Example Controller with Layout
258
+
259
+ Here's a complete example showing the layout system in action:
260
+
261
+ ```ruby
262
+ class EventController < ElaineCrud::BaseController
263
+ layout 'application'
264
+
265
+ model Event
266
+ permit_params :title, :description, :date, :location, :organizer, :capacity
267
+
268
+ field :title, title: "Event Title"
269
+ field :date, title: "Event Date"
270
+ field :location, title: "Venue"
271
+ field :organizer, title: "Organized By"
272
+ field :capacity, title: "Max Attendees"
273
+ field :description, title: "Description"
274
+
275
+ private
276
+
277
+ # Custom layout: Title and key info on top, description below
278
+ def calculate_layout(content, fields)
279
+ [
280
+ [
281
+ { field_name: :title, colspan: 2 },
282
+ { field_name: :date, colspan: 1 },
283
+ { field_name: :capacity, colspan: 1 }
284
+ ],
285
+ [
286
+ { field_name: :organizer, colspan: 2 },
287
+ { field_name: :location, colspan: 2 }
288
+ ],
289
+ [
290
+ { field_name: :description, colspan: 4 }
291
+ ]
292
+ ]
293
+ end
294
+
295
+ def calculate_layout_header(fields)
296
+ ["25%", "25%", "25%", "25%"] # Equal 4-column grid
297
+ end
298
+ end
299
+ ```
300
+
301
+ This creates a structured layout that displays events in a clear, hierarchical format while maintaining the flexibility to customize for different types of content.
@@ -0,0 +1,170 @@
1
+ # ElaineCrud Troubleshooting Guide
2
+
3
+ ## Form Changes Not Being Saved
4
+
5
+ If you're experiencing issues where form changes are not being saved when you click "Save Changes", here's how to diagnose and fix the problem:
6
+
7
+ ### Step 1: Enable Debug Logging
8
+
9
+ The latest version of ElaineCrud includes detailed debug logging. Check your Rails development log after attempting to save changes. Look for lines starting with "ElaineCrud:".
10
+
11
+ ### Step 2: Check Your Controller Configuration
12
+
13
+ Add this line to your controller's action (temporarily) to see the configuration:
14
+
15
+ ```ruby
16
+ class MeetingsController < ElaineCrud::BaseController
17
+ model Meeting
18
+ permit_params :title, :start_time, :end_time
19
+
20
+ def index
21
+ debug_configuration # Add this temporarily
22
+ super
23
+ end
24
+ end
25
+ ```
26
+
27
+ This will output configuration details to your console.
28
+
29
+ ### Step 3: Common Issues and Solutions
30
+
31
+ #### Issue 1: `permit_params` called before `model`
32
+ **Problem**: If you call `permit_params` before setting the model, foreign keys won't be auto-included.
33
+
34
+ **Wrong**:
35
+ ```ruby
36
+ permit_params :title, :start_time
37
+ model Meeting # Model set after permit_params
38
+ ```
39
+
40
+ **Correct**:
41
+ ```ruby
42
+ model Meeting
43
+ permit_params :title, :start_time # Foreign keys auto-included
44
+ ```
45
+
46
+ **Note**: Recent versions automatically handle this, but it's still best practice to call `model` first.
47
+
48
+ #### Issue 2: Missing permitted parameters
49
+ **Problem**: The field you're trying to update isn't in the permitted parameters list.
50
+
51
+ **Solution**: Add the field to `permit_params`:
52
+ ```ruby
53
+ permit_params :title, :start_time, :end_time, :description
54
+ # Foreign keys like :meeting_room_id are automatically included
55
+ ```
56
+
57
+ #### Issue 3: Validation errors
58
+ **Problem**: The model has validation errors that prevent saving.
59
+
60
+ **Check**: Look in your Rails log for lines like:
61
+ ```
62
+ ElaineCrud: Record update failed with errors: ["Title can't be blank"]
63
+ ```
64
+
65
+ **Solution**: Fix the validation errors or adjust your model validations.
66
+
67
+ #### Issue 4: Parameter namespace issues
68
+ **Problem**: Form parameters aren't being submitted under the correct model name.
69
+
70
+ **Check**: Look for log lines like:
71
+ ```
72
+ ElaineCrud: Looking for params under key 'meeting'
73
+ ElaineCrud: Available param keys: ["utf8", "authenticity_token", "commit"]
74
+ ElaineCrud: No parameters found for model 'meeting'
75
+ ```
76
+
77
+ **Solution**: This usually indicates a form submission issue. Check that your model name matches expectations.
78
+
79
+ ### Step 4: Manual Debugging
80
+
81
+ If the automatic debugging isn't sufficient, you can add this to your controller:
82
+
83
+ ```ruby
84
+ def update
85
+ Rails.logger.info "Raw params: #{params.inspect}"
86
+ Rails.logger.info "Record params: #{record_params.inspect}"
87
+ Rails.logger.info "Permitted attributes: #{permitted_attributes.inspect}"
88
+ super
89
+ end
90
+ ```
91
+
92
+ ### Step 5: Common Log Patterns and Their Meanings
93
+
94
+ #### Successful Update
95
+ ```
96
+ ElaineCrud: Attempting to update with params: {:title=>"New Title", :meeting_room_id=>2}
97
+ ElaineCrud: Record updated successfully: {"id"=>1, "title"=>"New Title", "meeting_room_id"=>2}
98
+ ```
99
+
100
+ #### Missing Parameters
101
+ ```
102
+ ElaineCrud: Looking for params under key 'meeting'
103
+ ElaineCrud: No parameters found for model 'meeting'
104
+ ElaineCrud: Attempting to update with params: {}
105
+ ```
106
+ **Fix**: Check form submission and parameter names.
107
+
108
+ #### Validation Errors
109
+ ```
110
+ ElaineCrud: Record update failed with errors: ["Title can't be blank", "Meeting room must exist"]
111
+ ```
112
+ **Fix**: Ensure required fields are filled and foreign key references are valid.
113
+
114
+ #### Permission Issues
115
+ ```
116
+ ElaineCrud: Permitted attributes: [:title]
117
+ ElaineCrud: Attempting to update with params: {:title=>"New Title"}
118
+ ```
119
+ **Fix**: Add missing fields to `permit_params` (foreign keys should be auto-included).
120
+
121
+ ### Step 6: Browser Developer Tools
122
+
123
+ 1. Open your browser's developer tools (F12)
124
+ 2. Go to the Network tab
125
+ 3. Attempt to save changes
126
+ 4. Look for the POST request to your update action
127
+ 5. Check the request payload to see what parameters are being sent
128
+
129
+ ### Step 7: Test with Rails Console
130
+
131
+ You can test parameter handling directly:
132
+
133
+ ```ruby
134
+ # In rails console
135
+ controller = YourController.new
136
+ controller.params = ActionController::Parameters.new({
137
+ your_model_name: { title: "Test", meeting_room_id: 1 }
138
+ })
139
+ puts controller.send(:record_params).inspect
140
+ ```
141
+
142
+ ### Step 8: Minimal Test Case
143
+
144
+ Create a minimal controller to isolate the issue:
145
+
146
+ ```ruby
147
+ class TestController < ElaineCrud::BaseController
148
+ model YourModel # Replace with your actual model
149
+ permit_params :title # Add your basic fields
150
+
151
+ def index
152
+ debug_configuration
153
+ super
154
+ end
155
+ end
156
+ ```
157
+
158
+ Add a route and test with this minimal setup.
159
+
160
+ ## Getting Help
161
+
162
+ If you're still experiencing issues:
163
+
164
+ 1. **Check the logs**: Include relevant log output in your issue report
165
+ 2. **Share your controller**: Include your controller code
166
+ 3. **Share your model**: Include relevant model code (relationships, validations)
167
+ 4. **Share the form**: Include the HTML form being submitted
168
+ 5. **Browser network info**: Include details from browser developer tools
169
+
170
+ The debug logging should give you enough information to identify the root cause of the issue.
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/elaine_crud/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'elaine_crud'
7
+ spec.version = ElaineCrud::VERSION
8
+ spec.authors = ['Garo']
9
+ spec.email = ['juho.makinen@gmail.com']
10
+
11
+ spec.summary = 'A Rails engine for generating CRUD UIs for ActiveRecord models'
12
+ spec.description = 'ElaineCrud provides a reusable BaseController and views to quickly generate CRUD interfaces for any ActiveRecord model with minimal configuration.'
13
+ spec.homepage = 'https://github.com/garo/elaine_crud'
14
+ spec.license = 'MIT'
15
+
16
+ spec.metadata['homepage_uri'] = spec.homepage
17
+ spec.metadata['source_code_uri'] = 'https://github.com/garo/elaine_crud'
18
+
19
+ spec.files = Dir.chdir(__dir__) do
20
+ `git ls-files -z 2>/dev/null`.split("\x0").reject do |f|
21
+ (File.expand_path(f) == __FILE__) ||
22
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor Gemfile])
23
+ end
24
+ end
25
+
26
+ spec.require_paths = ['lib']
27
+
28
+ # Runtime dependencies
29
+ spec.add_dependency 'rails', '>= 6.0'
30
+ spec.add_dependency 'kaminari', '~> 1.2'
31
+ spec.add_dependency 'caxlsx', '~> 4.0'
32
+ spec.add_dependency 'csv', '~> 3.0'
33
+ spec.add_dependency 'turbo-rails', '~> 2.0'
34
+
35
+ # Development dependencies
36
+ spec.add_development_dependency 'rspec', '~> 3.0'
37
+ spec.add_development_dependency 'rspec-rails', '~> 6.0'
38
+ spec.add_development_dependency 'capybara', '~> 3.0'
39
+ spec.add_development_dependency 'selenium-webdriver', '~> 4.0'
40
+ spec.add_development_dependency 'sqlite3', '~> 2.1'
41
+ spec.add_development_dependency 'puma', '~> 6.0'
42
+ spec.add_development_dependency 'roo', '~> 2.10'
43
+
44
+ # For more information and examples about making a new gem, check out our
45
+ # guide at: https://bundler.io/guides/creating_gem.html
46
+ end