propel_api 0.3.1.4 → 0.3.1.5
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 +15 -0
- data/lib/generators/propel_api/core/configuration_methods.rb +1 -1
- data/lib/generators/propel_api/resource/resource_generator.rb +2 -2
- data/lib/generators/propel_api/templates/config/propel_api.rb.tt +4 -4
- data/lib/generators/propel_api/templates/scaffold/facet_model_template.rb.tt +2 -2
- data/lib/generators/propel_api/templates/tests/integration_test_template.rb.tt +13 -2
- data/lib/generators/propel_api/templates/tests/model_test_template.rb.tt +41 -0
- data/lib/propel_api.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91e74e1fe5e094d98139863beb372f8635300f6dafe41e9993c988c1cf98f089
|
4
|
+
data.tar.gz: df50d1039f6d627fa05ed8c53c1be23af126aecdaa2d6803ade04ba64760b061
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cdb193ecf7a26a2941ca6ea07d5e8f6fc778967169ff6bde3dc0a764e9ef9bcd00ac7324954fe02f7201bea0656b69be2dc55276fada71f52a6171e0fa7dd6fe
|
7
|
+
data.tar.gz: ac9a94e0bfb83c0a5bc945a550e25672c2f471c9b10f14dc20bfb6c6548eca55b60f53f13a08d7e9dc6ec8c65d9a0aad1cb1ff488a260a3864128e1d665103f8
|
data/CHANGELOG.md
CHANGED
@@ -10,6 +10,21 @@ 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.3.1.5] - 2025-09-11
|
14
|
+
|
15
|
+
### 🐛 Bug Fixes
|
16
|
+
- **JSONB Support Consistency**: Ensured all template files consistently support both `:json` and `:jsonb` field types
|
17
|
+
- Fixed any remaining instances of `:json`-only checks in generator templates
|
18
|
+
- Enhanced controller parameter generation for JSONB fields across all templates
|
19
|
+
- Improved test data generation for JSONB fields in all test templates
|
20
|
+
- Consistent JSONB handling in fixtures, integration tests, and model tests
|
21
|
+
|
22
|
+
### 📖 Documentation & Template Improvements
|
23
|
+
- **Enhanced Template Consistency**: Verified all generator templates have proper JSONB support
|
24
|
+
- Updated controller templates to handle both JSON and JSONB consistently
|
25
|
+
- Enhanced test templates for reliable JSONB field testing
|
26
|
+
- Improved fixture generation for JSONB data structures
|
27
|
+
|
13
28
|
## [0.3.1.4] - 2025-09-11
|
14
29
|
|
15
30
|
### 🐛 Critical Bug Fixes
|
@@ -31,7 +31,7 @@ module PropelApi
|
|
31
31
|
base.class_option :json_defaults,
|
32
32
|
type: :boolean,
|
33
33
|
default: nil,
|
34
|
-
desc: "Add default:
|
34
|
+
desc: "Add default: {} to json/jsonb fields in migrations. Defaults to PropelApi configuration."
|
35
35
|
end
|
36
36
|
|
37
37
|
protected
|
@@ -631,10 +631,10 @@ Time.current.utc.strftime("%Y%m%d%H%M%S")
|
|
631
631
|
if should_add_json_defaults?
|
632
632
|
json_attrs = attributes.select { |attr| attr.type == :json || attr.type == :jsonb }
|
633
633
|
json_attrs.each do |attr|
|
634
|
-
# Look for the json/jsonb field declaration and add default:
|
634
|
+
# Look for the json/jsonb field declaration and add default: {}
|
635
635
|
json_field_pattern = /t\.#{attr.type} :#{attr.name}(?!\s*,\s*default:)/
|
636
636
|
if updated_content.match?(json_field_pattern)
|
637
|
-
updated_content = updated_content.gsub(json_field_pattern, "t.#{attr.type} :#{attr.name}, default:
|
637
|
+
updated_content = updated_content.gsub(json_field_pattern, "t.#{attr.type} :#{attr.name}, default: {}")
|
638
638
|
end
|
639
639
|
end
|
640
640
|
end
|
@@ -19,8 +19,8 @@ module PropelApi
|
|
19
19
|
@enforce_tenancy = true # true = enforce tenancy (default), false = no checking
|
20
20
|
@required_tenancy_attributes = [:organization, :agency] # Required when enforce_tenancy is true
|
21
21
|
|
22
|
-
# JSON field defaults - automatically add default:
|
23
|
-
@json_field_defaults = true # true = add default:
|
22
|
+
# JSON field defaults - automatically add default: {} to json/jsonb fields in migrations
|
23
|
+
@json_field_defaults = true # true = add default: {}, false = leave as default nil
|
24
24
|
|
25
25
|
# Initialize the configurable attribute filter
|
26
26
|
@attribute_filter = PropelApi::AttributeFilter.new
|
@@ -147,9 +147,9 @@ PropelApi.configure do |config|
|
|
147
147
|
config.required_tenancy_attributes = [:organization, :agency] # Both required by default
|
148
148
|
|
149
149
|
# JSON field defaults configuration
|
150
|
-
# Automatically adds default:
|
150
|
+
# Automatically adds default: {} to json/jsonb fields in generated migrations
|
151
151
|
# This prevents nil values and makes JSON fields more predictable
|
152
|
-
config.json_field_defaults = true # Default: true (add default:
|
152
|
+
config.json_field_defaults = true # Default: true (add default: {} to JSON fields)
|
153
153
|
|
154
154
|
# To disable JSON defaults globally:
|
155
155
|
# config.json_field_defaults = false
|
@@ -105,7 +105,7 @@ json_facet :short, fields: [:id<%
|
|
105
105
|
excluded_patterns = /\A(description|content|body|notes|comment|bio|about|summary|created_at|updated_at|deleted_at|password|digest|token|secret|key|salt|encrypted|confirmation|unlock|reset|api_key|access_token|refresh_token)\z/i
|
106
106
|
|
107
107
|
# Always exclude if the field contains security-sensitive words
|
108
|
-
security_patterns =
|
108
|
+
security_patterns = /\A(password|password_digest|password_confirmation|digest|token|secret|key|salt|encrypted|confirmation|unlock|reset|api_key|access_token|refresh_token)\z|.*(_digest|_token|_secret|_key|_salt|_encrypted)$/i
|
109
109
|
|
110
110
|
identifying_fields.include?(attr.name.to_s) ||
|
111
111
|
(simple_types.include?(attr.type) &&
|
@@ -126,7 +126,7 @@ json_facet :details, fields: [:id<%
|
|
126
126
|
# Exclude timestamps and internal fields
|
127
127
|
excluded_patterns = /\A(created_at|updated_at|deleted_at|password_digest|reset_password_token|confirmation_token|unlock_token)\z/i
|
128
128
|
# Always exclude security-sensitive fields
|
129
|
-
security_patterns =
|
129
|
+
security_patterns = /\A(password|password_digest|password_confirmation|digest|token|secret|key|salt|encrypted|confirmation|unlock|reset|api_key|access_token|refresh_token)\z|.*(_digest|_token|_secret|_key|_salt|_encrypted)$/i
|
130
130
|
# Exclude binary and large data types
|
131
131
|
excluded_types = [:binary]
|
132
132
|
|
@@ -102,7 +102,13 @@ class <%= class_name %>ApiTest < ActionDispatch::IntegrationTest
|
|
102
102
|
<%= attribute.name %>: true<%= ',' if index < attributes.length - 1 %>
|
103
103
|
<% elsif attribute.type == :decimal || attribute.type == :float -%>
|
104
104
|
<%= attribute.name %>: 100.50<%= ',' if index < attributes.length - 1 %>
|
105
|
+
<% elsif attribute.type == :date -%>
|
106
|
+
<%= attribute.name %>: Date.current<%= ',' if index < attributes.length - 1 %>
|
105
107
|
<% elsif attribute.type == :datetime -%>
|
108
|
+
<%= attribute.name %>: DateTime.current<%= ',' if index < attributes.length - 1 %>
|
109
|
+
<% elsif attribute.type == :time -%>
|
110
|
+
<%= attribute.name %>: Time.current<%= ',' if index < attributes.length - 1 %>
|
111
|
+
<% elsif attribute.type == :timestamp -%>
|
106
112
|
<%= attribute.name %>: Time.current<%= ',' if index < attributes.length - 1 %>
|
107
113
|
<% elsif attribute.type == :json || attribute.type == :jsonb -%>
|
108
114
|
<% if attribute.name == 'metadata' -%>
|
@@ -192,7 +198,12 @@ class <%= class_name %>ApiTest < ActionDispatch::IntegrationTest
|
|
192
198
|
<% elsif attribute.type == :decimal || attribute.type == :float -%>
|
193
199
|
# Rails conventionally serializes decimal/float values as strings in JSON
|
194
200
|
assert_equal "100.5", created_<%= singular_table_name %>['<%= attribute.name %>']
|
195
|
-
<% elsif attribute.type == :
|
201
|
+
<% elsif attribute.type == :date -%>
|
202
|
+
# Date fields should be properly formatted ISO dates
|
203
|
+
if created_<%= singular_table_name %>['<%= attribute.name %>'].present?
|
204
|
+
assert_match(/\d{4}-\d{2}-\d{2}/, created_<%= singular_table_name %>['<%= attribute.name %>'], "<%= attribute.name %> should be ISO date format")
|
205
|
+
end
|
206
|
+
<% elsif attribute.type == :datetime || attribute.type == :timestamp || attribute.type == :time || (attribute.name.to_s.match?(/_at$/) && attribute.type != :json && attribute.type != :jsonb) -%>
|
196
207
|
# Datetime fields should be properly formatted ISO timestamps, not exact values
|
197
208
|
if created_<%= singular_table_name %>['<%= attribute.name %>'].present?
|
198
209
|
assert_match(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/, created_<%= singular_table_name %>['<%= attribute.name %>'], "<%= attribute.name %> should be ISO timestamp format")
|
@@ -239,7 +250,7 @@ class <%= class_name %>ApiTest < ActionDispatch::IntegrationTest
|
|
239
250
|
|
240
251
|
# Verify data types
|
241
252
|
assert_kind_of String, test_data['string_value'], "string_value should be a string"
|
242
|
-
assert_kind_of
|
253
|
+
assert_kind_of String, test_data['numeric_value'], "numeric_value should be a string (HTTP API converts all values to strings)"
|
243
254
|
assert_kind_of Array, test_data['array_value'], "array_value should be an array"
|
244
255
|
assert_kind_of Hash, test_data['nested_object'], "nested_object should be a hash"
|
245
256
|
|
@@ -106,6 +106,14 @@ class <%= class_name %>Test < ActiveSupport::TestCase
|
|
106
106
|
<%= attribute.name %>: true<%= ',' if index < attributes.length - 1 %>
|
107
107
|
<% elsif attribute.type == :decimal || attribute.type == :float -%>
|
108
108
|
<%= attribute.name %>: <%= (index + 1) * 10.5 %><%= ',' if index < attributes.length - 1 %>
|
109
|
+
<% elsif attribute.type == :date -%>
|
110
|
+
<%= attribute.name %>: Date.current<%= ',' if index < attributes.length - 1 %>
|
111
|
+
<% elsif attribute.type == :datetime -%>
|
112
|
+
<%= attribute.name %>: DateTime.current<%= ',' if index < attributes.length - 1 %>
|
113
|
+
<% elsif attribute.type == :time -%>
|
114
|
+
<%= attribute.name %>: Time.current<%= ',' if index < attributes.length - 1 %>
|
115
|
+
<% elsif attribute.type == :timestamp -%>
|
116
|
+
<%= attribute.name %>: Time.current<%= ',' if index < attributes.length - 1 %>
|
109
117
|
<% else -%>
|
110
118
|
<%= attribute.name %>: "Test <%= attribute.name.humanize %>"<%= ',' if index < attributes.length - 1 %>
|
111
119
|
<% end -%>
|
@@ -136,6 +144,14 @@ class <%= class_name %>Test < ActiveSupport::TestCase
|
|
136
144
|
<%= attribute.name %>: false<%= ',' if index < attributes.length - 1 %>
|
137
145
|
<% elsif attribute.type == :decimal || attribute.type == :float -%>
|
138
146
|
<%= attribute.name %>: 99.99<%= ',' if index < attributes.length - 1 %>
|
147
|
+
<% elsif attribute.type == :date -%>
|
148
|
+
<%= attribute.name %>: Date.tomorrow<%= ',' if index < attributes.length - 1 %>
|
149
|
+
<% elsif attribute.type == :datetime -%>
|
150
|
+
<%= attribute.name %>: DateTime.tomorrow<%= ',' if index < attributes.length - 1 %>
|
151
|
+
<% elsif attribute.type == :time -%>
|
152
|
+
<%= attribute.name %>: 1.hour.from_now<%= ',' if index < attributes.length - 1 %>
|
153
|
+
<% elsif attribute.type == :timestamp -%>
|
154
|
+
<%= attribute.name %>: 1.day.from_now<%= ',' if index < attributes.length - 1 %>
|
139
155
|
<% else -%>
|
140
156
|
<%= attribute.name %>: "New Test <%= attribute.name.humanize %>"<%= ',' if index < attributes.length - 1 %>
|
141
157
|
<% end -%>
|
@@ -282,6 +298,14 @@ class <%= class_name %>Test < ActiveSupport::TestCase
|
|
282
298
|
<%= attribute.name %>: 123.45<%= ',' if index < attributes.length - 1 %>
|
283
299
|
<% elsif attribute.type == :json || attribute.type == :jsonb -%>
|
284
300
|
<%= attribute.name %>: { "test_key" => "test_value" }<%= ',' if index < attributes.length - 1 %>
|
301
|
+
<% elsif attribute.type == :date -%>
|
302
|
+
<%= attribute.name %>: Date.current<%= ',' if index < attributes.length - 1 %>
|
303
|
+
<% elsif attribute.type == :datetime -%>
|
304
|
+
<%= attribute.name %>: DateTime.current<%= ',' if index < attributes.length - 1 %>
|
305
|
+
<% elsif attribute.type == :time -%>
|
306
|
+
<%= attribute.name %>: Time.current<%= ',' if index < attributes.length - 1 %>
|
307
|
+
<% elsif attribute.type == :timestamp -%>
|
308
|
+
<%= attribute.name %>: Time.current<%= ',' if index < attributes.length - 1 %>
|
285
309
|
<% else -%>
|
286
310
|
<%= attribute.name %>: "Integrity Test <%= attribute.name.humanize %>"<%= ',' if index < attributes.length - 1 %>
|
287
311
|
<% end -%>
|
@@ -319,6 +343,23 @@ class <%= class_name %>Test < ActiveSupport::TestCase
|
|
319
343
|
assert_equal 123.45, reloaded_<%= singular_table_name %>.<%= attribute.name %>
|
320
344
|
<% elsif attribute.type == :json || attribute.type == :jsonb -%>
|
321
345
|
assert_equal({ "test_key" => "test_value" }, reloaded_<%= singular_table_name %>.<%= attribute.name %>)
|
346
|
+
<% elsif attribute.type == :date -%>
|
347
|
+
# Date fields should be properly stored and retrieved
|
348
|
+
assert_not_nil reloaded_<%= singular_table_name %>.<%= attribute.name %>
|
349
|
+
assert_kind_of Date, reloaded_<%= singular_table_name %>.<%= attribute.name %>
|
350
|
+
<% elsif attribute.type == :datetime -%>
|
351
|
+
# DateTime fields should be properly stored and retrieved
|
352
|
+
assert_not_nil reloaded_<%= singular_table_name %>.<%= attribute.name %>
|
353
|
+
# Rails typically converts DateTime to Time in ActiveRecord
|
354
|
+
assert(reloaded_<%= singular_table_name %>.<%= attribute.name %>.is_a?(DateTime) || reloaded_<%= singular_table_name %>.<%= attribute.name %>.is_a?(Time))
|
355
|
+
<% elsif attribute.type == :time -%>
|
356
|
+
# Time fields should be properly stored and retrieved
|
357
|
+
assert_not_nil reloaded_<%= singular_table_name %>.<%= attribute.name %>
|
358
|
+
assert_kind_of Time, reloaded_<%= singular_table_name %>.<%= attribute.name %>
|
359
|
+
<% elsif attribute.type == :timestamp -%>
|
360
|
+
# Timestamp fields should be properly stored and retrieved
|
361
|
+
assert_not_nil reloaded_<%= singular_table_name %>.<%= attribute.name %>
|
362
|
+
assert_kind_of Time, reloaded_<%= singular_table_name %>.<%= attribute.name %>
|
322
363
|
<% else -%>
|
323
364
|
assert_equal "Integrity Test <%= attribute.name.humanize %>", reloaded_<%= singular_table_name %>.<%= attribute.name %>
|
324
365
|
<% end -%>
|
data/lib/propel_api.rb
CHANGED