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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f4163e5ce8733e5d7f2226ce39f9a475a75860497da6d6d0ddf12575deaa661f
4
- data.tar.gz: 42640181a8f3927a9e70ea3b536dfa3507eb21b0997b1fd5a4a5409668422002
3
+ metadata.gz: 6e8a8a9d34cdcedea81beaadb7a2db76e36a53754e6edf224e65066249cd4b94
4
+ data.tar.gz: 3c98242f205d111da4e51d7fe6caae53fcad4ae9da9ddd8482a167845d5a7895
5
5
  SHA512:
6
- metadata.gz: 7034b106b0c14b639fff1385ef6827f5e3431fe9209e978ea932a65e28a58c97ef8a45e9c66b6cac1bbd8a1c906d8628611127714716f954d75df28ac1c232aa
7
- data.tar.gz: 70ac2e021ba10ffb43fbae4f7608134b1f25ad0583d6f92658166a963aadcc8a9d7deb25b8d3389cbd575224e95f0698ba470f3b7f26f016d0dc8a03e79542f8
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
- gem_file = roots.filter_map { |root|
50
- files = Dir[File.join(root, "#{name}-*.gem")]
51
- files.sort.last if files.any?
52
- }.max
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 mount_uploader :attachment, AttachmentUploader\n monetize :amount_cents\n\n def locales_display\n locales\n end\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
@@ -1,6 +1,6 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  module InlineFormsInstaller
3
- VERSION = "8.1.9"
3
+ VERSION = "8.1.10"
4
4
 
5
5
  # Written into generated apps' `.ruby-version` (must match gemspec `required_ruby_version`).
6
6
  TARGET_RUBY_VERSION = "ruby-4.0.4"
@@ -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) + numericality validation regression
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
- assert_equal "99.95", @showcase.reload.price
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?
@@ -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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inline_forms_installer
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.1.9
4
+ version: 8.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ace Suares