inline_forms_installer 8.1.9 → 8.1.10
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/lib/inline_forms_installer/installer_core.rb +24 -6
- data/lib/inline_forms_installer/version.rb +1 -1
- data/lib/installer_templates/example_app_tests/test/integration/example_app_showcase_numeric_fields_test.rb +79 -4
- data/lib/installer_templates/example_app_tests/test/integration/example_app_showcase_page_render_test.rb +4 -0
- data/lib/installer_templates/example_app_tests/test/models/example_app_form_element_showcase_test.rb +61 -0
- 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: 6e8a8a9d34cdcedea81beaadb7a2db76e36a53754e6edf224e65066249cd4b94
|
|
4
|
+
data.tar.gz: 3c98242f205d111da4e51d7fe6caae53fcad4ae9da9ddd8482a167845d5a7895
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b61043ca27f2902b5cd1c3c3518ecd7bd267f3ad43179ceac4e0cd2af592d07978c86c004d4f569d2eeed8432d506a57906a8644346333a753a1ba0fe8608f3b
|
|
7
|
+
data.tar.gz: 003bea7e68f32bf009f7e681f4221e30788909856d045e2d16c94172200ddc699287b2bf6be878726166a350a78bf8e327087509faaea38242c9a585f9edf282
|
|
@@ -46,10 +46,17 @@ def install_prerelease_gems_from_roots!
|
|
|
46
46
|
return if roots.empty?
|
|
47
47
|
|
|
48
48
|
%w[validation_hints inline_forms inline_forms_installer].each do |name|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
# Pick the *highest version*, not the highest filename. String sort
|
|
50
|
+
# placed `inline_forms-8.1.7.gem` above `inline_forms-8.1.10.gem`
|
|
51
|
+
# because "7" > "1" lexicographically — silently picking up a stale
|
|
52
|
+
# gem build on every release once minor versions cross a digit
|
|
53
|
+
# boundary. Parse the version out of the filename with Gem::Version
|
|
54
|
+
# so the comparison is numeric.
|
|
55
|
+
candidates = roots.flat_map { |root| Dir[File.join(root, "#{name}-*.gem")] }
|
|
56
|
+
gem_file = candidates.max_by do |path|
|
|
57
|
+
ver_str = File.basename(path, ".gem").sub(/\A#{Regexp.escape(name)}-/, "")
|
|
58
|
+
Gem::Version.new(ver_str) rescue Gem::Version.new("0")
|
|
59
|
+
end
|
|
53
60
|
next unless gem_file && File.file?(gem_file)
|
|
54
61
|
|
|
55
62
|
say "- Installing #{File.basename(gem_file)} into app gemset..."
|
|
@@ -1065,7 +1072,7 @@ if ENV['install_example'] == 'true'
|
|
|
1065
1072
|
# ---------------------------------------------------------------------
|
|
1066
1073
|
say "- Generating FormElementShowcase (one resource per kept Tier 1 form_element)..."
|
|
1067
1074
|
sleep 1
|
|
1068
|
-
run %q{bundle exec rails g inline_forms FormElementShowcase title:string body_plain_area:plain_text_area count:integer_field price:decimal_field amount:money_field meeting_date:date_select meeting_time:time_select birth_month:month_select start_month:month_year_picker is_active:check_box gender:radio_button rating_int:dropdown_with_integers priority:dropdown_with_values priority2:dropdown_with_values stars:dropdown_with_values_with_stars scale_int:scale_with_integers scale_val:scale_with_values attachment:file_field jingle:audio_field cover:image_field description:rich_text locales:has_and_belongs_to_many _enabled:yes _list_order:title _list_search:title _presentation:'#{title}'}
|
|
1075
|
+
run %q{bundle exec rails g inline_forms FormElementShowcase title:string body_plain_area:plain_text_area count:integer_field price:decimal_field amount:money_field latitude:decimal_field{9,6} longitude:decimal_field{10,6} meeting_date:date_select meeting_time:time_select birth_month:month_select start_month:month_year_picker is_active:check_box gender:radio_button rating_int:dropdown_with_integers priority:dropdown_with_values priority2:dropdown_with_values stars:dropdown_with_values_with_stars scale_int:scale_with_integers scale_val:scale_with_values attachment:file_field jingle:audio_field cover:image_field description:rich_text locales:has_and_belongs_to_many _enabled:yes _list_order:title _list_search:title _presentation:'#{title}'}
|
|
1069
1076
|
|
|
1070
1077
|
say "- Generating Attachment + Jingle uploaders (Cover reuses ImageUploader)..."
|
|
1071
1078
|
run "bundle exec rails generate uploader Attachment"
|
|
@@ -1127,7 +1134,11 @@ if ENV['install_example'] == 'true'
|
|
|
1127
1134
|
# A `def` body is parsed but only resolved at call time, side-stepping
|
|
1128
1135
|
# the ordering hazard.
|
|
1129
1136
|
inject_into_file "app/models/form_element_showcase.rb",
|
|
1130
|
-
"\n validates :count, numericality: { only_integer: true }, allow_blank: true\n
|
|
1137
|
+
"\n validates :count, numericality: { only_integer: true }, allow_blank: true\n" \
|
|
1138
|
+
" validates :price, numericality: true, allow_blank: true\n" \
|
|
1139
|
+
" validates :latitude, numericality: { greater_than_or_equal_to: -90, less_than_or_equal_to: 90 }, allow_blank: true\n" \
|
|
1140
|
+
" validates :longitude, numericality: { greater_than_or_equal_to: -180, less_than_or_equal_to: 180 }, allow_blank: true\n" \
|
|
1141
|
+
" mount_uploader :attachment, AttachmentUploader\n monetize :amount_cents\n\n def locales_display\n locales\n end\n",
|
|
1131
1142
|
after: "class FormElementShowcase < ApplicationRecord\n"
|
|
1132
1143
|
|
|
1133
1144
|
# Value-bearing rows for every form_element that needs a values hash
|
|
@@ -1199,6 +1210,8 @@ if ENV['install_example'] == 'true'
|
|
|
1199
1210
|
amount: Amount
|
|
1200
1211
|
meeting_date: Meeting date
|
|
1201
1212
|
meeting_time: Meeting time
|
|
1213
|
+
latitude: Latitude
|
|
1214
|
+
longitude: Longitude
|
|
1202
1215
|
birth_month: Birth month
|
|
1203
1216
|
start_month: Start month and year
|
|
1204
1217
|
is_active: Is active
|
|
@@ -1280,6 +1293,11 @@ if ENV['install_example'] == 'true'
|
|
|
1280
1293
|
s.count = 7
|
|
1281
1294
|
s.price = "12.34"
|
|
1282
1295
|
s.amount = Money.from_amount(99.95, "USD") if s.respond_to?(:amount=)
|
|
1296
|
+
# Curaçao (Willemstad). Exactly representable in decimal(9,6)
|
|
1297
|
+
# and decimal(10,6) — useful for the precision-survival test
|
|
1298
|
+
# that asserts the round-trip is bit-identical, not float-fuzzy.
|
|
1299
|
+
s.latitude = BigDecimal("12.123456")
|
|
1300
|
+
s.longitude = BigDecimal("-68.987654")
|
|
1283
1301
|
s.meeting_date = Date.new(2026, 6, 1)
|
|
1284
1302
|
s.meeting_time = Time.utc(2000, 1, 1, 14, 30)
|
|
1285
1303
|
s.birth_month = 7
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
require_relative "../example_app/example_integration_test_case"
|
|
4
4
|
|
|
5
5
|
# Numeric Tier 1 helpers on FormElementShowcase:
|
|
6
|
-
# integer_field (count)
|
|
7
|
-
# decimal_field (price)
|
|
6
|
+
# integer_field (count) + numericality validation regression
|
|
7
|
+
# decimal_field (price) default precision: 10, scale: 2
|
|
8
|
+
# decimal_field (latitude, longitude) explicit `{p,s}` CLI suffix:
|
|
9
|
+
# decimal(9,6) / decimal(10,6)
|
|
8
10
|
# money_field (amount, money-rails `monetize :amount_cents`)
|
|
9
11
|
class ExampleAppShowcaseNumericFieldsTest < ExampleAppIntegrationTestCase
|
|
10
12
|
setup do
|
|
@@ -30,7 +32,11 @@ class ExampleAppShowcaseNumericFieldsTest < ExampleAppIntegrationTestCase
|
|
|
30
32
|
assert_equal 42, @showcase.reload.count
|
|
31
33
|
end
|
|
32
34
|
|
|
33
|
-
test "decimal_field price round-trips" do
|
|
35
|
+
test "decimal_field price round-trips as BigDecimal with default precision/scale" do
|
|
36
|
+
# Since 8.1.10 the registry maps :decimal_field to a real :decimal
|
|
37
|
+
# column. Bare `price:decimal_field` (no `{p,s}` suffix) defaults to
|
|
38
|
+
# precision: 10, scale: 2 — so 99.95 round-trips losslessly *and*
|
|
39
|
+
# ActiveRecord returns a BigDecimal, not a String.
|
|
34
40
|
frame = "form_element_showcase_#{@showcase.id}_price"
|
|
35
41
|
headers = { "Turbo-Frame" => frame, "Accept" => "text/html" }
|
|
36
42
|
|
|
@@ -44,7 +50,76 @@ class ExampleAppShowcaseNumericFieldsTest < ExampleAppIntegrationTestCase
|
|
|
44
50
|
assert_response :success
|
|
45
51
|
assert_includes @response.body, %(<turbo-frame id="#{frame}">)
|
|
46
52
|
assert_includes @response.body, "99.95"
|
|
47
|
-
|
|
53
|
+
reloaded_price = @showcase.reload.price
|
|
54
|
+
assert_kind_of BigDecimal, reloaded_price,
|
|
55
|
+
"expected :decimal column to return BigDecimal, got #{reloaded_price.class}"
|
|
56
|
+
assert_equal BigDecimal("99.95"), reloaded_price
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
test "decimal_field{9,6} latitude round-trips at full scale (6 fractional digits)" do
|
|
60
|
+
# The `latitude:decimal_field{9,6}` CLI suffix should give us
|
|
61
|
+
# exactly 6 fractional digits of precision — enough for ~11cm
|
|
62
|
+
# accuracy in GPS terms. Pick a value that fully populates the
|
|
63
|
+
# scale so we'd catch off-by-one truncation.
|
|
64
|
+
frame = "form_element_showcase_#{@showcase.id}_latitude"
|
|
65
|
+
headers = { "Turbo-Frame" => frame, "Accept" => "text/html" }
|
|
66
|
+
|
|
67
|
+
put form_element_showcase_path(
|
|
68
|
+
@showcase,
|
|
69
|
+
attribute: "latitude",
|
|
70
|
+
form_element: "decimal_field",
|
|
71
|
+
update: frame
|
|
72
|
+
), params: { latitude: "12.123456" }, headers: headers
|
|
73
|
+
|
|
74
|
+
assert_response :success
|
|
75
|
+
reloaded = @showcase.reload.latitude
|
|
76
|
+
assert_kind_of BigDecimal, reloaded
|
|
77
|
+
assert_equal BigDecimal("12.123456"), reloaded
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
test "decimal_field{10,6} longitude accepts the full ±180 range" do
|
|
81
|
+
frame = "form_element_showcase_#{@showcase.id}_longitude"
|
|
82
|
+
headers = { "Turbo-Frame" => frame, "Accept" => "text/html" }
|
|
83
|
+
|
|
84
|
+
put form_element_showcase_path(
|
|
85
|
+
@showcase,
|
|
86
|
+
attribute: "longitude",
|
|
87
|
+
form_element: "decimal_field",
|
|
88
|
+
update: frame
|
|
89
|
+
), params: { longitude: "-179.999999" }, headers: headers
|
|
90
|
+
|
|
91
|
+
assert_response :success
|
|
92
|
+
assert_equal BigDecimal("-179.999999"), @showcase.reload.longitude
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
test "decimal_field price rejects non-numeric via top-level create" do
|
|
96
|
+
# Counterpart to the integer_field rejection test below. Without
|
|
97
|
+
# the `validates :price, numericality: true` line in the showcase
|
|
98
|
+
# model, ActiveRecord would silently cast "ace" to BigDecimal("0")
|
|
99
|
+
# and the create would succeed. The validation keeps the
|
|
100
|
+
# round-trip honest.
|
|
101
|
+
assert_no_difference "FormElementShowcase.count" do
|
|
102
|
+
post form_element_showcases_path(update: @list_frame),
|
|
103
|
+
params: {
|
|
104
|
+
title: "Bad Price",
|
|
105
|
+
price: "ace",
|
|
106
|
+
count: 1,
|
|
107
|
+
amount: "0.00",
|
|
108
|
+
start_month: "September 2026",
|
|
109
|
+
_form_element_showcase: {
|
|
110
|
+
rating_int: 1,
|
|
111
|
+
priority: 1,
|
|
112
|
+
priority2: 1,
|
|
113
|
+
stars: 1,
|
|
114
|
+
scale_int: 1,
|
|
115
|
+
scale_val: 1,
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
headers: @list_headers
|
|
119
|
+
end
|
|
120
|
+
assert_response :success
|
|
121
|
+
assert_match(/is not a number|price[^<]*is not a number/i, @response.body,
|
|
122
|
+
"expected numericality error to render after invalid price")
|
|
48
123
|
end
|
|
49
124
|
|
|
50
125
|
test "money_field amount round-trips through monetize :amount_cents" do
|
|
@@ -14,6 +14,8 @@ class ExampleAppShowcasePageRenderTest < ExampleAppIntegrationTestCase
|
|
|
14
14
|
count
|
|
15
15
|
price
|
|
16
16
|
amount
|
|
17
|
+
latitude
|
|
18
|
+
longitude
|
|
17
19
|
meeting_date
|
|
18
20
|
meeting_time
|
|
19
21
|
birth_month
|
|
@@ -66,6 +68,8 @@ class ExampleAppShowcasePageRenderTest < ExampleAppIntegrationTestCase
|
|
|
66
68
|
s.scale_int = 3
|
|
67
69
|
s.scale_val = 2
|
|
68
70
|
s.amount = Money.from_amount(99.95, "USD") if s.respond_to?(:amount=) && defined?(Money)
|
|
71
|
+
s.latitude = BigDecimal("12.123456")
|
|
72
|
+
s.longitude = BigDecimal("-68.987654")
|
|
69
73
|
s.description = "<p>A rich-text body.</p>"
|
|
70
74
|
end
|
|
71
75
|
@full.locales << @locale unless @full.locales.where(id: @locale.id).exists?
|
data/lib/installer_templates/example_app_tests/test/models/example_app_form_element_showcase_test.rb
CHANGED
|
@@ -16,6 +16,8 @@ class ExampleAppFormElementShowcaseTest < ActiveSupport::TestCase
|
|
|
16
16
|
count
|
|
17
17
|
price
|
|
18
18
|
amount
|
|
19
|
+
latitude
|
|
20
|
+
longitude
|
|
19
21
|
header_dates
|
|
20
22
|
meeting_date
|
|
21
23
|
meeting_time
|
|
@@ -82,4 +84,63 @@ class ExampleAppFormElementShowcaseTest < ActiveSupport::TestCase
|
|
|
82
84
|
showcase = FormElementShowcase.new(title: "X", count: nil)
|
|
83
85
|
assert showcase.valid?, "expected showcase to be valid with count=nil (allow_blank), got #{showcase.errors.full_messages.inspect}"
|
|
84
86
|
end
|
|
87
|
+
|
|
88
|
+
# ---------------------------------------------------------------------
|
|
89
|
+
# 8.1.10: :decimal_field now maps to a real :decimal column with
|
|
90
|
+
# precision/scale instead of the legacy varchar. The migration emitter
|
|
91
|
+
# applies (10, 2) by default and reads `{p,s}` overrides from the CLI
|
|
92
|
+
# type suffix (e.g. `latitude:decimal_field{9,6}` -> decimal(9,6)).
|
|
93
|
+
# ---------------------------------------------------------------------
|
|
94
|
+
|
|
95
|
+
test "decimal_field maps to a real :decimal column with default precision/scale" do
|
|
96
|
+
price_col = FormElementShowcase.columns_hash["price"]
|
|
97
|
+
assert_not_nil price_col, "expected a :price column"
|
|
98
|
+
assert_equal :decimal, price_col.type,
|
|
99
|
+
"expected :price to be a :decimal column, got #{price_col.type.inspect} (#{price_col.sql_type.inspect})"
|
|
100
|
+
assert_equal 10, price_col.precision, "expected default precision: 10"
|
|
101
|
+
assert_equal 2, price_col.scale, "expected default scale: 2"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
test "decimal_field{p,s} CLI suffix sets precision and scale" do
|
|
105
|
+
lat = FormElementShowcase.columns_hash["latitude"]
|
|
106
|
+
lon = FormElementShowcase.columns_hash["longitude"]
|
|
107
|
+
assert_equal :decimal, lat.type
|
|
108
|
+
assert_equal :decimal, lon.type
|
|
109
|
+
assert_equal [9, 6], [lat.precision, lat.scale],
|
|
110
|
+
"expected latitude:decimal_field{9,6} -> decimal(9,6), got decimal(#{lat.precision},#{lat.scale})"
|
|
111
|
+
assert_equal [10, 6], [lon.precision, lon.scale],
|
|
112
|
+
"expected longitude:decimal_field{10,6} -> decimal(10,6), got decimal(#{lon.precision},#{lon.scale})"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
test "decimal column round-trips BigDecimal losslessly at full scale" do
|
|
116
|
+
showcase = FormElementShowcase.create!(
|
|
117
|
+
title: "decimal-roundtrip",
|
|
118
|
+
latitude: BigDecimal("12.123456"),
|
|
119
|
+
longitude: BigDecimal("-68.987654"),
|
|
120
|
+
)
|
|
121
|
+
showcase.reload
|
|
122
|
+
assert_kind_of BigDecimal, showcase.latitude
|
|
123
|
+
assert_equal BigDecimal("12.123456"), showcase.latitude
|
|
124
|
+
assert_equal BigDecimal("-68.987654"), showcase.longitude
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
test "price rejects non-numeric input with a numericality error" do
|
|
128
|
+
showcase = FormElementShowcase.new(title: "X", price: "ace")
|
|
129
|
+
assert_not showcase.valid?
|
|
130
|
+
assert_includes showcase.errors.attribute_names, :price
|
|
131
|
+
assert showcase.errors[:price].any? { |m| m.match?(/not a number/i) },
|
|
132
|
+
"expected `not a number` error on :price, got #{showcase.errors[:price].inspect}"
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
test "latitude rejects out-of-range values via numericality range" do
|
|
136
|
+
showcase = FormElementShowcase.new(title: "X", latitude: 91)
|
|
137
|
+
assert_not showcase.valid?
|
|
138
|
+
assert_includes showcase.errors.attribute_names, :latitude
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
test "longitude rejects out-of-range values via numericality range" do
|
|
142
|
+
showcase = FormElementShowcase.new(title: "X", longitude: 181)
|
|
143
|
+
assert_not showcase.valid?
|
|
144
|
+
assert_includes showcase.errors.attribute_names, :longitude
|
|
145
|
+
end
|
|
85
146
|
end
|