inline_forms_installer 8.1.6 → 8.1.9

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: 8780337213fbfb45e061f0f5309c9cb73826461aacca4dd4cc1662214b8654f4
4
- data.tar.gz: c355bf659cc460fa83ca210a712c91b466dc4d7e30c0c8477906b2d867770674
3
+ metadata.gz: f4163e5ce8733e5d7f2226ce39f9a475a75860497da6d6d0ddf12575deaa661f
4
+ data.tar.gz: 42640181a8f3927a9e70ea3b536dfa3507eb21b0997b1fd5a4a5409668422002
5
5
  SHA512:
6
- metadata.gz: 1e663a9f2bfdf0ad9e8bab1a93cb397a12374d7918a7f08d069c10b84ca3e635c95cd702c87e1164fb78173f6992cd99191930c1814ffdddc7d996273303c5c5
7
- data.tar.gz: 210aef3002d3c58c01f226c5f29e6f0a7e548c8b273cb3eca3f08e524beb407f16b75d4cd3ec46abcac4e4a65b21d05c3d2132e79d347cac5a528b54119ac5a4
6
+ metadata.gz: 7034b106b0c14b639fff1385ef6827f5e3431fe9209e978ea932a65e28a58c97ef8a45e9c66b6cac1bbd8a1c906d8628611127714716f954d75df28ac1c232aa
7
+ data.tar.gz: 70ac2e021ba10ffb43fbae4f7608134b1f25ad0583d6f92658166a963aadcc8a9d7deb25b8d3389cbd575224e95f0698ba470f3b7f26f016d0dc8a03e79542f8
@@ -105,6 +105,13 @@ gem 'jquery-ui-rails', '4.0.3'
105
105
  # Foundation Icons SCSS + fonts are vendored in the inline_forms engine (Dart Sass;
106
106
  # foundation-icons-sass-rails depended on sass-rails).
107
107
  gem 'mini_magick'
108
+ # money-rails powers the `money_field` Tier 1 helper:
109
+ # * adds the `humanized_money_with_symbol` view helper used by
110
+ # money_field_show
111
+ # * exposes `monetize :foo_cents` so an integer `_cents` column is
112
+ # read/written as a Money instance through `obj.foo`
113
+ # Used by FormElementShowcase#amount in the --example app.
114
+ gem 'money-rails', '~> 3.0'
108
115
  gem 'mysql2'
109
116
  gem 'paper_trail', '~> 17.0'
110
117
  gem 'rails-i18n', '~> 8.1'
@@ -424,7 +431,16 @@ END_INITIALIZER
424
431
  # Create Locales
425
432
  say "- Create locales"
426
433
  generate "inline_forms", "Locale name:string title:string #{user_cfg.table_name}:has_many _enabled:yes _list_order:title _presentation:\#{title}"
427
- append_to_file "db/seeds.rb", "Locale.create({ id: 1, name: 'en', title: 'English' })\n"
434
+ # Seed four locales so the FormElementShowcase HABTM :locales demo
435
+ # (added under --example) has something to check on/off. `id: 1` (en) is
436
+ # the default the admin user is bound to in the line below; the other
437
+ # three are inert until selected by the showcase rows.
438
+ append_to_file "db/seeds.rb", <<~LOCALE_SEED
439
+ Locale.create({ id: 1, name: 'en', title: 'English' })
440
+ Locale.create({ id: 2, name: 'nl', title: 'Nederlands' })
441
+ Locale.create({ id: 3, name: 'de', title: 'Deutsch' })
442
+ Locale.create({ id: 4, name: 'fr', title: 'Français' })
443
+ LOCALE_SEED
428
444
 
429
445
  # Create Roles
430
446
  say "- Create roles"
@@ -1049,7 +1065,7 @@ if ENV['install_example'] == 'true'
1049
1065
  # ---------------------------------------------------------------------
1050
1066
  say "- Generating FormElementShowcase (one resource per kept Tier 1 form_element)..."
1051
1067
  sleep 1
1052
- run %q{bundle exec rails g inline_forms FormElementShowcase title:string body_plain_area:plain_text_area count:integer_field price:decimal_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 attachment:file_field jingle:audio_field cover:image_field description:rich_text roles:has_and_belongs_to_many _enabled:yes _list_order:title _list_search:title _presentation:'#{title}'}
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}'}
1053
1069
 
1054
1070
  say "- Generating Attachment + Jingle uploaders (Cover reuses ImageUploader)..."
1055
1071
  run "bundle exec rails generate uploader Attachment"
@@ -1063,12 +1079,55 @@ if ENV['install_example'] == 'true'
1063
1079
  "mount_uploader :cover, CoverUploader",
1064
1080
  "mount_uploader :cover, ImageUploader"
1065
1081
 
1082
+ # money-rails wiring for the `amount:money_field` showcase column.
1083
+ #
1084
+ # * The inline_forms generator emits a plain `t.integer :amount`
1085
+ # (FormElementRegistry maps `:money_field` to `:integer`), but
1086
+ # money-rails' `monetize` reader/writer convention is `_cents`-
1087
+ # suffixed: declare `monetize :amount_cents`, store cents in
1088
+ # `amount_cents`, and money-rails defines `obj.amount`/`obj.amount=`
1089
+ # returning/parsing Money objects. That keeps the inline_forms
1090
+ # attribute list entry `[:amount, :money_field]` semantically
1091
+ # correct (`obj.amount` => Money) without a custom helper.
1092
+ # * Rename the column in the generated create-table migration from
1093
+ # `:amount` to `:amount_cents` *before* `rake db:migrate` runs.
1094
+ # * Add a small initializer pinning the default currency so the
1095
+ # showcase renders predictably under any host locale.
1096
+ showcase_migration = Dir.glob("db/migrate/*_inline_forms_create_form_element_showcases.rb").first
1097
+ if showcase_migration
1098
+ gsub_file showcase_migration, /t\.integer :amount\b/, "t.integer :amount_cents, default: 0, null: false"
1099
+ end
1100
+
1101
+ create_file "config/initializers/money.rb", <<-MONEY_INIT.strip_heredoc
1102
+ # Generated by inline_forms (money-rails defaults for the
1103
+ # FormElementShowcase `amount:money_field` demo column).
1104
+ MoneyRails.configure do |config|
1105
+ config.default_currency = :usd
1106
+ end
1107
+ MONEY_INIT
1108
+
1066
1109
  # First field-level validation in the example app. `allow_blank: true`
1067
1110
  # keeps PaperTrail revert paths (and the seeded second row, which leaves
1068
1111
  # count nil) valid. The integration test covers the explicit error
1069
1112
  # path by POSTing `count: "abc"` to /form_element_showcases.
1113
+ #
1114
+ # `locales_display` is a virtual alias for the HABTM :locales association
1115
+ # so the same association can render twice in the attribute list: once
1116
+ # editable (`[:locales, :check_list]`) and once read-only
1117
+ # (`[:locales_display, :info_list]`). Inline-forms keys turbo frames by
1118
+ # attribute name, so we need a distinct name for the second row — info_list
1119
+ # has no `_update` method, hence the wrapper rather than a separate column.
1120
+ #
1121
+ # NOTE: this has to be `def locales_display; locales; end`, not
1122
+ # `alias_method :locales_display, :locales`. `alias_method` resolves the
1123
+ # source method at class-load time, but the `has_and_belongs_to_many
1124
+ # :locales` declaration that defines `#locales` is injected lower in the
1125
+ # file (line ~12), so an alias_method here raises
1126
+ # `NameError: undefined method 'locales' for class 'FormElementShowcase'`.
1127
+ # A `def` body is parsed but only resolved at call time, side-stepping
1128
+ # the ordering hazard.
1070
1129
  inject_into_file "app/models/form_element_showcase.rb",
1071
- "\n validates :count, numericality: { only_integer: true }, allow_blank: true\n mount_uploader :attachment, AttachmentUploader\n",
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",
1072
1131
  after: "class FormElementShowcase < ApplicationRecord\n"
1073
1132
 
1074
1133
  # Value-bearing rows for every form_element that needs a values hash
@@ -1082,6 +1141,8 @@ if ENV['install_example'] == 'true'
1082
1141
  "[ :priority, :dropdown_with_values ]" => "[ :priority, :dropdown_with_values, { 1 => 'low', 2 => 'mid', 3 => 'high' } ]",
1083
1142
  "[ :priority2, :dropdown_with_values ]" => "[ :priority2, :dropdown_with_values, { 1 => 'low', 2 => 'mid', 3 => 'high' }, [ 2 ] ]",
1084
1143
  "[ :stars, :dropdown_with_values_with_stars ]" => "[ :stars, :dropdown_with_values_with_stars, { 1 => '1stars', 2 => '2stars', 3 => '3stars', 4 => '4stars', 5 => '5stars' } ]",
1144
+ "[ :scale_int, :scale_with_integers ]" => "[ :scale_int, :scale_with_integers, { 1 => 'one', 2 => 'two', 3 => 'three', 4 => 'four', 5 => 'five' } ]",
1145
+ "[ :scale_val, :scale_with_values ]" => "[ :scale_val, :scale_with_values, { 1 => 'red', 2 => 'green', 3 => 'blue' } ]",
1085
1146
  }
1086
1147
  showcase_value_rows.each do |from, to|
1087
1148
  gsub_file "app/models/form_element_showcase.rb", from, to
@@ -1103,13 +1164,18 @@ if ENV['install_example'] == 'true'
1103
1164
  gsub_file "app/models/form_element_showcase.rb", from, to
1104
1165
  end
1105
1166
 
1106
- # Insert :roles (info_list), :header_meta, and the timestamps after
1107
- # the rich_text row. The generator does not emit a row for
1108
- # `roles:has_and_belongs_to_many` (relation? is true), so we add it
1109
- # manually here.
1167
+ # Insert :locales (editable check_list), :locales_display (read-only
1168
+ # info_list mirror of the same association see the alias_method
1169
+ # above), :header_meta, and the timestamps after the rich_text row.
1170
+ # The generator does not emit a row for `locales:has_and_belongs_to_many`
1171
+ # (relation? is true), so we add the rows manually here. Locale (not
1172
+ # Role) was chosen because Role is reserved for the user/Member model
1173
+ # in the inline_forms example app (the join sits under roles_users);
1174
+ # Locale already has a `_presentation` returning `title`, which is
1175
+ # exactly what `info_list_show` renders per row.
1110
1176
  gsub_file "app/models/form_element_showcase.rb",
1111
1177
  "[ :description, :rich_text ], \n",
1112
- "[ :description, :rich_text ], \n [ :roles, :info_list ], \n [ :header_meta, :header ], \n [ :created_at, :info ], \n [ :updated_at, :info ], \n"
1178
+ "[ :description, :rich_text ], \n [ :locales, :check_list ], \n [ :locales_display, :info_list ], \n [ :header_meta, :header ], \n [ :created_at, :info ], \n [ :updated_at, :info ], \n"
1113
1179
 
1114
1180
  # Locale keys for the showcase attributes. Headers + the timestamps
1115
1181
  # need explicit labels so `human_attribute_name` does not fall back to
@@ -1130,21 +1196,25 @@ if ENV['install_example'] == 'true'
1130
1196
  body_plain_area: Plain text area
1131
1197
  count: Count
1132
1198
  price: Price
1199
+ amount: Amount
1133
1200
  meeting_date: Meeting date
1134
1201
  meeting_time: Meeting time
1135
1202
  birth_month: Birth month
1136
- start_month: Start month
1203
+ start_month: Start month and year
1137
1204
  is_active: Is active
1138
1205
  gender: Gender
1139
1206
  rating_int: Rating
1140
1207
  priority: Priority
1141
1208
  priority2: Priority (with disabled option)
1142
1209
  stars: Stars
1210
+ scale_int: Scale (integers)
1211
+ scale_val: Scale (values)
1143
1212
  attachment: Attachment
1144
1213
  jingle: Jingle
1145
1214
  cover: Cover
1146
1215
  description: Description
1147
- roles: Roles
1216
+ locales: Locales (editable)
1217
+ locales_display: Locales (read-only)
1148
1218
  created_at: Created at
1149
1219
  updated_at: Updated at
1150
1220
  END_SHOWCASE_LOCALE
@@ -1160,22 +1230,36 @@ if ENV['install_example'] == 'true'
1160
1230
  copy_file src, File.join("app/assets/images", "#{n}stars.png") if File.exist?(src)
1161
1231
  end
1162
1232
 
1163
- # Join table for has_and_belongs_to_many :roles. Mirrors the
1164
- # roles_users join migration created for the user model above.
1165
- say "- Creating form_element_showcases_roles join migration..."
1233
+ # File/audio/image upload sample assets for the full-demo seed. Copied
1234
+ # under db/seed_uploads so the seed migration can read them at
1235
+ # db:migrate time and store them through CarrierWave. Mirrors the
1236
+ # db/seed_images convention used for the Photo gallery seed above.
1237
+ %w[sample.txt sample.wav sample_cover.png].each do |basename|
1238
+ src = File.join(showcase_assets_root, basename)
1239
+ copy_file src, File.join("db/seed_uploads", basename) if File.exist?(src)
1240
+ end
1241
+
1242
+ # Join table for has_and_belongs_to_many :locales. Mirrors the
1243
+ # roles_users join migration created for the user model above. Locale
1244
+ # (not Role) was chosen because Role is reserved for the Member/User
1245
+ # auth model; using it here would coincidentally share the same join
1246
+ # row pool as roles_users which is confusing for the demo. The four
1247
+ # locales seeded above (en/nl/de/fr) give the editable check_list
1248
+ # something interesting to toggle.
1249
+ say "- Creating form_element_showcases_locales join migration..."
1166
1250
  sleep 1
1167
1251
  habtm_ts = Time.now.utc.strftime("%Y%m%d%H%M%S")
1168
- create_file "db/migrate/#{habtm_ts}_create_join_table_form_element_showcases_roles.rb", <<-HABTM_MIGRATION.strip_heredoc
1169
- class CreateJoinTableFormElementShowcasesRoles < ActiveRecord::Migration[8.1]
1252
+ create_file "db/migrate/#{habtm_ts}_create_join_table_form_element_showcases_locales.rb", <<-HABTM_MIGRATION.strip_heredoc
1253
+ class CreateJoinTableFormElementShowcasesLocales < ActiveRecord::Migration[8.1]
1170
1254
  def self.up
1171
- create_table :form_element_showcases_roles, id: false, force: true do |t|
1255
+ create_table :form_element_showcases_locales, id: false, force: true do |t|
1172
1256
  t.integer :form_element_showcase_id
1173
- t.integer :role_id
1257
+ t.integer :locale_id
1174
1258
  end
1175
1259
  end
1176
1260
 
1177
1261
  def self.down
1178
- drop_table :form_element_showcases_roles
1262
+ drop_table :form_element_showcases_locales
1179
1263
  end
1180
1264
  end
1181
1265
  HABTM_MIGRATION
@@ -1195,6 +1279,7 @@ if ENV['install_example'] == 'true'
1195
1279
  s.body_plain_area = "A short plain-text paragraph."
1196
1280
  s.count = 7
1197
1281
  s.price = "12.34"
1282
+ s.amount = Money.from_amount(99.95, "USD") if s.respond_to?(:amount=)
1198
1283
  s.meeting_date = Date.new(2026, 6, 1)
1199
1284
  s.meeting_time = Time.utc(2000, 1, 1, 14, 30)
1200
1285
  s.birth_month = 7
@@ -1205,11 +1290,34 @@ if ENV['install_example'] == 'true'
1205
1290
  s.priority = 2
1206
1291
  s.priority2 = 3
1207
1292
  s.stars = 4
1293
+ s.scale_int = 3
1294
+ s.scale_val = 2
1208
1295
  s.description = "<p>A rich-text paragraph for the showcase.</p>"
1209
1296
  end
1210
- if defined?(Role) && Role.exists?(1) && full.roles.empty?
1211
- full.roles << Role.find(1)
1297
+ # Attach the default locale (en) so the editable check_list and the
1298
+ # paired read-only info_list both have something to show. The other
1299
+ # seeded locales (nl/de/fr) stay unchecked so the toggle UX is
1300
+ # exercised when the user opens the check_list.
1301
+ if defined?(Locale) && Locale.exists?(1) && full.locales.empty?
1302
+ full.locales << Locale.find(1)
1303
+ end
1304
+
1305
+ # File/audio/image uploads for the full demo. The asset files are
1306
+ # copied into db/seed_uploads/ from lib/installer_templates/example_app_assets/
1307
+ # at install time (see the asset-copy block above), so this
1308
+ # migration can open them at db:migrate time and hand File handles
1309
+ # to CarrierWave for storage in public/uploads/.
1310
+ seed_uploads = Rails.root.join("db", "seed_uploads")
1311
+ {
1312
+ attachment: seed_uploads.join("sample.txt"),
1313
+ jingle: seed_uploads.join("sample.wav"),
1314
+ cover: seed_uploads.join("sample_cover.png"),
1315
+ }.each do |attr, path|
1316
+ next unless path.file?
1317
+ next if full.public_send(attr).present?
1318
+ File.open(path, "rb") { |io| full.public_send("\#{attr}=", io) }
1212
1319
  end
1320
+ full.save! if full.changed?
1213
1321
 
1214
1322
  # "Empty" refers to the role and uploader fields (their empty
1215
1323
  # branches need to render). The other fields keep valid values
@@ -1222,6 +1330,8 @@ if ENV['install_example'] == 'true'
1222
1330
  s.priority = 1
1223
1331
  s.priority2 = 1
1224
1332
  s.stars = 1
1333
+ s.scale_int = 1
1334
+ s.scale_val = 1
1225
1335
  end
1226
1336
  end
1227
1337
 
@@ -1,6 +1,6 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  module InlineFormsInstaller
3
- VERSION = "8.1.6"
3
+ VERSION = "8.1.9"
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"
@@ -0,0 +1 @@
1
+ Sample attachment file generated by inline_forms_installer for the FormElementShowcase demo. You can replace this with any file.
@@ -2,14 +2,14 @@
2
2
 
3
3
  require_relative "../example_app/example_integration_test_case"
4
4
 
5
- # Choice helpers on FormElementShowcase:
5
+ # Choice/scale helpers on FormElementShowcase:
6
6
  # check_box (is_active, 0|1)
7
7
  # radio_button (gender, hash)
8
8
  # dropdown_with_integers (rating_int)
9
9
  # dropdown_with_values (priority normal + priority2 options_disabled)
10
10
  # dropdown_with_values_with_stars (stars)
11
- # (scale_with_integers / scale_with_values are dropped from the showcase
12
- # until their runtime show helpers are repaired; see CHANGELOG 8.1.6.)
11
+ # scale_with_integers (scale_int)
12
+ # scale_with_values (scale_val)
13
13
  class ExampleAppShowcaseChoiceScaleFieldsTest < ExampleAppIntegrationTestCase
14
14
  setup do
15
15
  @showcase = FormElementShowcase.find_or_create_by!(title: "Choice/scale demo")
@@ -123,4 +123,30 @@ class ExampleAppShowcaseChoiceScaleFieldsTest < ExampleAppIntegrationTestCase
123
123
  assert_equal 5, @showcase.reload.stars
124
124
  end
125
125
 
126
+ test "scale_with_integers scale_int round-trips" do
127
+ frame = field_frame(:scale_int)
128
+ put form_element_showcase_path(
129
+ @showcase,
130
+ attribute: "scale_int",
131
+ form_element: "scale_with_integers",
132
+ update: frame
133
+ ), params: { underscored_param_root => { scale_int: 4 } }, headers: field_headers(:scale_int)
134
+
135
+ assert_response :success
136
+ assert_equal 4, @showcase.reload.scale_int
137
+ end
138
+
139
+ test "scale_with_values scale_val round-trips" do
140
+ frame = field_frame(:scale_val)
141
+ put form_element_showcase_path(
142
+ @showcase,
143
+ attribute: "scale_val",
144
+ form_element: "scale_with_values",
145
+ update: frame
146
+ ), params: { underscored_param_root => { scale_val: 3 } }, headers: field_headers(:scale_val)
147
+
148
+ assert_response :success
149
+ assert_equal 3, @showcase.reload.scale_val
150
+ end
151
+
126
152
  end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../example_app/example_integration_test_case"
4
+
5
+ # HABTM helpers on FormElementShowcase:
6
+ # check_list (locales) -- editable multi-select
7
+ # info_list (locales_display) -- read-only mirror of the same association
8
+ # via `alias_method :locales_display, :locales`
9
+ #
10
+ # Locale (not Role) is the showcase association because Role is reserved
11
+ # for the auth Member/User model in this example app; reusing it on
12
+ # FormElementShowcase would coincidentally share rows with roles_users
13
+ # which is confusing.
14
+ class ExampleAppShowcaseLocalesAssociationsTest < ExampleAppIntegrationTestCase
15
+ setup do
16
+ @en = Locale.find_or_create_by!(name: "en") { |l| l.title = "English" }
17
+ @nl = Locale.find_or_create_by!(name: "nl") { |l| l.title = "Nederlands" }
18
+ @de = Locale.find_or_create_by!(name: "de") { |l| l.title = "Deutsch" }
19
+
20
+ @showcase = FormElementShowcase.find_or_create_by!(title: "Locales demo")
21
+ @showcase.locales.clear
22
+ end
23
+
24
+ def field_frame(attr)
25
+ "form_element_showcase_#{@showcase.id}_#{attr}"
26
+ end
27
+
28
+ def field_headers(attr)
29
+ { "Turbo-Frame" => field_frame(attr), "Accept" => "text/html" }
30
+ end
31
+
32
+ test "check_list locales toggles the HABTM association" do
33
+ frame = field_frame(:locales)
34
+
35
+ # Initially empty; PUT with two locales checked.
36
+ put form_element_showcase_path(
37
+ @showcase,
38
+ attribute: "locales",
39
+ form_element: "check_list",
40
+ update: frame
41
+ ), params: { locales: { @en.id.to_s => 1, @de.id.to_s => 1 } }, headers: field_headers(:locales)
42
+
43
+ assert_response :success
44
+ assert_equal [@en.id, @de.id].sort, @showcase.reload.locale_ids.sort
45
+
46
+ # PUT again with only one locale; the missing one is uncoupled.
47
+ put form_element_showcase_path(
48
+ @showcase,
49
+ attribute: "locales",
50
+ form_element: "check_list",
51
+ update: frame
52
+ ), params: { locales: { @nl.id.to_s => 1 } }, headers: field_headers(:locales)
53
+
54
+ assert_response :success
55
+ assert_equal [@nl.id], @showcase.reload.locale_ids
56
+ end
57
+
58
+ test "info_list locales_display mirrors the locales association read-only" do
59
+ @showcase.locales << @en unless @showcase.locales.where(id: @en.id).exists?
60
+
61
+ row_frame = "form_element_showcase_#{@showcase.id}"
62
+ get form_element_showcase_path(@showcase, update: row_frame),
63
+ headers: { "Turbo-Frame" => row_frame, "Accept" => "text/html" }
64
+
65
+ assert_response :success
66
+ info_frame = field_frame(:locales_display)
67
+ assert_includes @response.body, %(<turbo-frame id="#{info_frame}">),
68
+ "expected info_list frame for :locales_display"
69
+ # info_list_show renders each item's `_presentation`. Locale's is `title`.
70
+ assert_match(/<turbo-frame id="#{info_frame}">.*#{Regexp.escape(@en.title)}/m, @response.body,
71
+ "expected #{@en.title.inspect} inside the locales_display info_list frame")
72
+ end
73
+
74
+ test "info_list locales_display empty-state renders the -- placeholder" do
75
+ @showcase.locales.clear
76
+
77
+ row_frame = "form_element_showcase_#{@showcase.id}"
78
+ get form_element_showcase_path(@showcase, update: row_frame),
79
+ headers: { "Turbo-Frame" => row_frame, "Accept" => "text/html" }
80
+
81
+ assert_response :success
82
+ info_frame = field_frame(:locales_display)
83
+ assert_match(/<turbo-frame id="#{info_frame}">[^<]*<div class='row [^']+'>--<\/div>/m, @response.body,
84
+ "expected empty `--` placeholder inside the locales_display frame")
85
+ end
86
+ end
@@ -5,9 +5,7 @@ require_relative "../example_app/example_integration_test_case"
5
5
  # Numeric Tier 1 helpers on FormElementShowcase:
6
6
  # integer_field (count) + numericality validation regression
7
7
  # decimal_field (price)
8
- # (money_field is dropped from the showcase; the runtime helper depends on
9
- # money-rails' `humanized_money_with_symbol`, which is not in the installer
10
- # Gemfile. See CHANGELOG 8.1.6 "Dropped" section.)
8
+ # money_field (amount, money-rails `monetize :amount_cents`)
11
9
  class ExampleAppShowcaseNumericFieldsTest < ExampleAppIntegrationTestCase
12
10
  setup do
13
11
  @showcase = FormElementShowcase.find_or_create_by!(title: "Numeric demo")
@@ -49,24 +47,46 @@ class ExampleAppShowcaseNumericFieldsTest < ExampleAppIntegrationTestCase
49
47
  assert_equal "99.95", @showcase.reload.price
50
48
  end
51
49
 
50
+ test "money_field amount round-trips through monetize :amount_cents" do
51
+ skip "money-rails monetize not configured" unless FormElementShowcase.respond_to?(:monetized_attributes) &&
52
+ FormElementShowcase.monetized_attributes.key?("amount")
53
+
54
+ frame = "form_element_showcase_#{@showcase.id}_amount"
55
+ headers = { "Turbo-Frame" => frame, "Accept" => "text/html" }
56
+
57
+ put form_element_showcase_path(
58
+ @showcase,
59
+ attribute: "amount",
60
+ form_element: "money_field",
61
+ update: frame
62
+ ), params: { amount: "12.34" }, headers: headers
63
+
64
+ assert_response :success
65
+ assert_includes @response.body, %(<turbo-frame id="#{frame}">)
66
+ reloaded = @showcase.reload
67
+ assert_equal 1234, reloaded.amount_cents,
68
+ "expected monetize to parse '12.34' into 1234 cents, got #{reloaded.amount_cents.inspect}"
69
+ end
70
+
52
71
  test "integer_field count rejects non-integer via top-level create" do
53
72
  # The controller's create iterates every attribute and calls each
54
- # form_element's update method. Several helpers crash on nil params:
55
- # - month_year_picker_update -> Date.parse("") raises
56
- # - dropdown_with_integers_update / dropdown_with_values{_with_stars}_update
57
- # -> params[:_form_element_showcase][:attr] dereferences nil
58
- # We supply just enough to let the create walk reach the validation step.
73
+ # form_element's update method. Several helpers used to crash on nil
74
+ # params (month_year_picker_update, scale_*_update, dropdown_*_update)
75
+ # so we supply just enough to let the create walk reach validation.
59
76
  assert_no_difference "FormElementShowcase.count" do
60
77
  post form_element_showcases_path(update: @list_frame),
61
78
  params: {
62
79
  title: "Bad Count",
63
80
  count: "abc",
81
+ amount: "0.00",
64
82
  start_month: "September 2026",
65
83
  _form_element_showcase: {
66
84
  rating_int: 1,
67
85
  priority: 1,
68
86
  priority2: 1,
69
87
  stars: 1,
88
+ scale_int: 1,
89
+ scale_val: 1,
70
90
  },
71
91
  },
72
92
  headers: @list_headers
@@ -13,6 +13,7 @@ class ExampleAppShowcasePageRenderTest < ExampleAppIntegrationTestCase
13
13
  body_plain_area
14
14
  count
15
15
  price
16
+ amount
16
17
  meeting_date
17
18
  meeting_time
18
19
  birth_month
@@ -23,11 +24,14 @@ class ExampleAppShowcasePageRenderTest < ExampleAppIntegrationTestCase
23
24
  priority
24
25
  priority2
25
26
  stars
27
+ scale_int
28
+ scale_val
26
29
  attachment
27
30
  jingle
28
31
  cover
29
32
  description
30
- roles
33
+ locales
34
+ locales_display
31
35
  created_at
32
36
  updated_at
33
37
  ].freeze
@@ -43,8 +47,7 @@ class ExampleAppShowcasePageRenderTest < ExampleAppIntegrationTestCase
43
47
  ].freeze
44
48
 
45
49
  setup do
46
- locale = Locale.find_or_create_by!(name: "en") { |l| l.title = "English" }
47
- @role = Role.find_or_create_by!(name: "superadmin") { |r| r.description = "Super Admin" }
50
+ @locale = Locale.find_or_create_by!(name: "en") { |l| l.title = "English" }
48
51
 
49
52
  @full = FormElementShowcase.find_or_create_by!(title: "Full demo") do |s|
50
53
  s.body_plain_area = "Plain text body"
@@ -60,19 +63,24 @@ class ExampleAppShowcasePageRenderTest < ExampleAppIntegrationTestCase
60
63
  s.priority = 2
61
64
  s.priority2 = 3
62
65
  s.stars = 4
66
+ s.scale_int = 3
67
+ s.scale_val = 2
68
+ s.amount = Money.from_amount(99.95, "USD") if s.respond_to?(:amount=) && defined?(Money)
63
69
  s.description = "<p>A rich-text body.</p>"
64
70
  end
65
- @full.roles << @role unless @full.roles.where(id: @role.id).exists?
71
+ @full.locales << @locale unless @full.locales.where(id: @locale.id).exists?
66
72
 
67
73
  @empty = FormElementShowcase.find_or_create_by!(title: "Empty demo") do |s|
68
74
  # Keep dropdown/scale integers at valid indices so the show helpers
69
- # do not crash on nil. The point of "empty demo" is that roles and
70
- # uploads are blank, not every integer attribute.
75
+ # do not crash on nil. The point of "empty demo" is that locales
76
+ # and uploads are blank, not every integer attribute.
71
77
  s.gender = 1
72
78
  s.rating_int = 1
73
79
  s.priority = 1
74
80
  s.priority2 = 1
75
81
  s.stars = 1
82
+ s.scale_int = 1
83
+ s.scale_val = 1
76
84
  end
77
85
  end
78
86
 
@@ -95,22 +103,21 @@ class ExampleAppShowcasePageRenderTest < ExampleAppIntegrationTestCase
95
103
  "expected header label for #{attr} (#{label.inspect})"
96
104
  end
97
105
 
98
- assert_includes @response.body, @role.name,
99
- "expected info_list to render the role's _presentation"
106
+ assert_includes @response.body, @locale.title,
107
+ "expected info_list to render the locale's _presentation"
100
108
  end
101
109
 
102
- test "empty showcase info_list renders the no-roles placeholder" do
110
+ test "empty showcase info_list renders the no-locales placeholder" do
103
111
  row_frame = "form_element_showcase_#{@empty.id}"
104
112
  get form_element_showcase_path(@empty, update: row_frame),
105
113
  headers: { "Turbo-Frame" => row_frame, "Accept" => "text/html" }
106
114
 
107
115
  assert_response :success
108
- frame = "form_element_showcase_#{@empty.id}_roles"
116
+ frame = "form_element_showcase_#{@empty.id}_locales_display"
109
117
  body = @response.body
110
118
  assert_includes body, %(<turbo-frame id="#{frame}">)
111
- frame_block = body[body.index(%(<turbo-frame id="#{frame}">"))..-1] rescue nil
112
119
  # info_list_show emits a `--` placeholder for empty associations.
113
120
  assert_match(/<turbo-frame id="#{frame}">[^<]*<div class='row [^']+'>--<\/div>/m, body,
114
- "expected info_list empty placeholder `--` inside roles frame")
121
+ "expected info_list empty placeholder `--` inside locales_display frame")
115
122
  end
116
123
  end
@@ -15,6 +15,7 @@ class ExampleAppFormElementShowcaseTest < ActiveSupport::TestCase
15
15
  header_numbers
16
16
  count
17
17
  price
18
+ amount
18
19
  header_dates
19
20
  meeting_date
20
21
  meeting_time
@@ -27,13 +28,16 @@ class ExampleAppFormElementShowcaseTest < ActiveSupport::TestCase
27
28
  priority
28
29
  priority2
29
30
  stars
31
+ scale_int
32
+ scale_val
30
33
  header_files
31
34
  attachment
32
35
  jingle
33
36
  cover
34
37
  header_rich
35
38
  description
36
- roles
39
+ locales
40
+ locales_display
37
41
  header_meta
38
42
  created_at
39
43
  updated_at
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.6
4
+ version: 8.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ace Suares
@@ -94,6 +94,9 @@ files:
94
94
  - lib/installer_templates/example_app_assets/3stars.png
95
95
  - lib/installer_templates/example_app_assets/4stars.png
96
96
  - lib/installer_templates/example_app_assets/5stars.png
97
+ - lib/installer_templates/example_app_assets/sample.txt
98
+ - lib/installer_templates/example_app_assets/sample.wav
99
+ - lib/installer_templates/example_app_assets/sample_cover.png
97
100
  - lib/installer_templates/example_app_tests/test/example_app/example_integration_test_case.rb
98
101
  - lib/installer_templates/example_app_tests/test/integration/example_app_apartment_field_turbo_test.rb
99
102
  - lib/installer_templates/example_app_tests/test/integration/example_app_apartment_name_list_test.rb
@@ -111,6 +114,7 @@ files:
111
114
  - lib/installer_templates/example_app_tests/test/integration/example_app_routing_test.rb
112
115
  - lib/installer_templates/example_app_tests/test/integration/example_app_showcase_choice_scale_fields_test.rb
113
116
  - lib/installer_templates/example_app_tests/test/integration/example_app_showcase_date_time_fields_test.rb
117
+ - lib/installer_templates/example_app_tests/test/integration/example_app_showcase_locales_associations_test.rb
114
118
  - lib/installer_templates/example_app_tests/test/integration/example_app_showcase_numeric_fields_test.rb
115
119
  - lib/installer_templates/example_app_tests/test/integration/example_app_showcase_page_render_test.rb
116
120
  - lib/installer_templates/example_app_tests/test/integration/example_app_showcase_text_fields_test.rb