bootstrap_form 5.1.0 → 5.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (171) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +21 -8
  3. data/.gitignore +4 -2
  4. data/.rubocop.yml +2 -1
  5. data/.yarnrc +5 -0
  6. data/CHANGELOG.md +13 -3
  7. data/CONTRIBUTING.md +101 -14
  8. data/Dangerfile +4 -4
  9. data/Dockerfile +5 -5
  10. data/Gemfile +5 -21
  11. data/README.md +108 -42
  12. data/RELEASING.md +12 -1
  13. data/Rakefile +7 -6
  14. data/bootstrap_form.gemspec +6 -8
  15. data/docker-compose.yml +6 -24
  16. data/gemfiles/6.0.gemfile +1 -1
  17. data/gemfiles/6.1.gemfile +1 -1
  18. data/gemfiles/7.0.gemfile +2 -3
  19. data/gemfiles/common.gemfile +28 -0
  20. data/gemfiles/edge.gemfile +3 -2
  21. data/lib/bootstrap_form/components/labels.rb +3 -9
  22. data/lib/bootstrap_form/components/validation.rb +36 -19
  23. data/lib/bootstrap_form/form_builder.rb +4 -1
  24. data/lib/bootstrap_form/form_group.rb +9 -6
  25. data/lib/bootstrap_form/form_group_builder.rb +10 -7
  26. data/lib/bootstrap_form/helpers/bootstrap.rb +7 -8
  27. data/lib/bootstrap_form/helpers/field.rb +26 -0
  28. data/lib/bootstrap_form/helpers.rb +1 -0
  29. data/lib/bootstrap_form/inputs/base.rb +2 -2
  30. data/lib/bootstrap_form/inputs/check_box.rb +22 -6
  31. data/lib/bootstrap_form/inputs/radio_button.rb +3 -3
  32. data/lib/bootstrap_form/inputs/range_field.rb +1 -1
  33. data/lib/bootstrap_form/inputs.rb +1 -1
  34. data/lib/bootstrap_form/version.rb +2 -1
  35. data/lib/bootstrap_form.rb +1 -1
  36. metadata +14 -146
  37. data/demo/.postcssrc.yml +0 -3
  38. data/demo/.ruby-version +0 -1
  39. data/demo/Gemfile +0 -80
  40. data/demo/Gemfile.lock +0 -261
  41. data/demo/Procfile.dev +0 -2
  42. data/demo/README.md +0 -17
  43. data/demo/Rakefile +0 -6
  44. data/demo/app/assets/builds/.keep +0 -0
  45. data/demo/app/assets/builds/application.js.LICENSE.txt +0 -9
  46. data/demo/app/assets/config/manifest.js +0 -2
  47. data/demo/app/assets/stylesheets/actiontext.css +0 -31
  48. data/demo/app/assets/stylesheets/actiontext.scss +0 -38
  49. data/demo/app/assets/stylesheets/application.scss +0 -1
  50. data/demo/app/controllers/application_controller.rb +0 -2
  51. data/demo/app/controllers/bootstrap_controller.rb +0 -29
  52. data/demo/app/controllers/users_controller.rb +0 -9
  53. data/demo/app/helpers/bootstrap_helper.rb +0 -27
  54. data/demo/app/javascript/application.js +0 -3
  55. data/demo/app/javascript/channels/consumer.js +0 -6
  56. data/demo/app/javascript/channels/index.js +0 -5
  57. data/demo/app/javascript/packs/application.js +0 -11
  58. data/demo/app/models/address.rb +0 -3
  59. data/demo/app/models/application_record.rb +0 -3
  60. data/demo/app/models/faux_user.rb +0 -9
  61. data/demo/app/models/skill.rb +0 -15
  62. data/demo/app/models/super_user.rb +0 -2
  63. data/demo/app/models/user.rb +0 -25
  64. data/demo/app/views/active_storage/blobs/_blob.html.erb +0 -14
  65. data/demo/app/views/bootstrap/form.html.erb +0 -67
  66. data/demo/app/views/layouts/action_text/contents/_content.html.erb +0 -3
  67. data/demo/app/views/layouts/application.html.erb +0 -76
  68. data/demo/bin/bundle +0 -3
  69. data/demo/bin/dev +0 -9
  70. data/demo/bin/rails +0 -4
  71. data/demo/bin/rake +0 -4
  72. data/demo/bin/setup +0 -36
  73. data/demo/bin/update +0 -31
  74. data/demo/bin/webpack +0 -15
  75. data/demo/bin/webpack-dev-server +0 -15
  76. data/demo/bin/yarn +0 -11
  77. data/demo/config/application.rb +0 -21
  78. data/demo/config/boot.rb +0 -5
  79. data/demo/config/database.yml +0 -21
  80. data/demo/config/environment.rb +0 -5
  81. data/demo/config/environments/development.rb +0 -60
  82. data/demo/config/environments/production.rb +0 -48
  83. data/demo/config/environments/test.rb +0 -46
  84. data/demo/config/initializers/application_controller_renderer.rb +0 -8
  85. data/demo/config/initializers/backtrace_silencers.rb +0 -7
  86. data/demo/config/initializers/cookies_serializer.rb +0 -5
  87. data/demo/config/initializers/filter_parameter_logging.rb +0 -4
  88. data/demo/config/initializers/inflections.rb +0 -16
  89. data/demo/config/initializers/mime_types.rb +0 -4
  90. data/demo/config/initializers/wrap_parameters.rb +0 -14
  91. data/demo/config/locales/en.yml +0 -33
  92. data/demo/config/puma.rb +0 -56
  93. data/demo/config/routes.rb +0 -6
  94. data/demo/config/spring.rb +0 -6
  95. data/demo/config/storage.yml +0 -35
  96. data/demo/config/webpack/development.js +0 -5
  97. data/demo/config/webpack/environment.js +0 -3
  98. data/demo/config/webpack/production.js +0 -5
  99. data/demo/config/webpack/test.js +0 -5
  100. data/demo/config/webpacker.yml +0 -92
  101. data/demo/config.ru +0 -5
  102. data/demo/db/schema.rb +0 -84
  103. data/demo/doc/screenshots/bootstrap/index/00_horizontal_form.png +0 -0
  104. data/demo/doc/screenshots/bootstrap/index/01_with_validation_error.png +0 -0
  105. data/demo/doc/screenshots/bootstrap/index/02_inline_form.png +0 -0
  106. data/demo/doc/screenshots/bootstrap/index/03_simple_action_text_example.png +0 -0
  107. data/demo/doc/screenshots/bootstrap/index/04_floating_labels.png +0 -0
  108. data/demo/doc/screenshots/bootstrap/readme/00_example.png +0 -0
  109. data/demo/doc/screenshots/bootstrap/readme/01_example.png +0 -0
  110. data/demo/doc/screenshots/bootstrap/readme/02_example.png +0 -0
  111. data/demo/doc/screenshots/bootstrap/readme/03_example.png +0 -0
  112. data/demo/doc/screenshots/bootstrap/readme/04_example.png +0 -0
  113. data/demo/doc/screenshots/bootstrap/readme/05_example.png +0 -0
  114. data/demo/doc/screenshots/bootstrap/readme/06_example.png +0 -0
  115. data/demo/doc/screenshots/bootstrap/readme/07_example.png +0 -0
  116. data/demo/doc/screenshots/bootstrap/readme/08_example.png +0 -0
  117. data/demo/doc/screenshots/bootstrap/readme/09_example.png +0 -0
  118. data/demo/doc/screenshots/bootstrap/readme/10_example.png +0 -0
  119. data/demo/doc/screenshots/bootstrap/readme/11_example.png +0 -0
  120. data/demo/doc/screenshots/bootstrap/readme/12_example.png +0 -0
  121. data/demo/doc/screenshots/bootstrap/readme/13_example.png +0 -0
  122. data/demo/doc/screenshots/bootstrap/readme/14_example.png +0 -0
  123. data/demo/doc/screenshots/bootstrap/readme/15_example.png +0 -0
  124. data/demo/doc/screenshots/bootstrap/readme/16_example.png +0 -0
  125. data/demo/doc/screenshots/bootstrap/readme/17_example.png +0 -0
  126. data/demo/doc/screenshots/bootstrap/readme/18_example.png +0 -0
  127. data/demo/doc/screenshots/bootstrap/readme/19_example.png +0 -0
  128. data/demo/doc/screenshots/bootstrap/readme/20_example.png +0 -0
  129. data/demo/doc/screenshots/bootstrap/readme/21_example.png +0 -0
  130. data/demo/doc/screenshots/bootstrap/readme/22_example.png +0 -0
  131. data/demo/doc/screenshots/bootstrap/readme/23_example.png +0 -0
  132. data/demo/doc/screenshots/bootstrap/readme/24_example.png +0 -0
  133. data/demo/doc/screenshots/bootstrap/readme/25_example.png +0 -0
  134. data/demo/doc/screenshots/bootstrap/readme/26_example.png +0 -0
  135. data/demo/doc/screenshots/bootstrap/readme/27_example.png +0 -0
  136. data/demo/doc/screenshots/bootstrap/readme/28_example.png +0 -0
  137. data/demo/doc/screenshots/bootstrap/readme/29_example.png +0 -0
  138. data/demo/doc/screenshots/bootstrap/readme/30_example.png +0 -0
  139. data/demo/doc/screenshots/bootstrap/readme/31_example.png +0 -0
  140. data/demo/doc/screenshots/bootstrap/readme/32_example.png +0 -0
  141. data/demo/doc/screenshots/bootstrap/readme/33_example.png +0 -0
  142. data/demo/doc/screenshots/bootstrap/readme/34_example.png +0 -0
  143. data/demo/doc/screenshots/bootstrap/readme/35_example.png +0 -0
  144. data/demo/doc/screenshots/bootstrap/readme/36_example.png +0 -0
  145. data/demo/doc/screenshots/bootstrap/readme/37_example.png +0 -0
  146. data/demo/doc/screenshots/bootstrap/readme/38_example.png +0 -0
  147. data/demo/doc/screenshots/bootstrap/readme/39_example.png +0 -0
  148. data/demo/doc/screenshots/bootstrap/readme/40_example.png +0 -0
  149. data/demo/doc/screenshots/bootstrap/readme/41_example.png +0 -0
  150. data/demo/doc/screenshots/bootstrap/readme/42_example.png +0 -0
  151. data/demo/doc/screenshots/bootstrap/readme/43_example.png +0 -0
  152. data/demo/doc/screenshots/bootstrap/readme/44_example.png +0 -0
  153. data/demo/doc/screenshots/bootstrap/readme/45_example.png +0 -0
  154. data/demo/doc/screenshots/bootstrap/readme/46_example.png +0 -0
  155. data/demo/doc/screenshots/bootstrap/readme/47_example.png +0 -0
  156. data/demo/doc/screenshots/bootstrap/readme/48_example.png +0 -0
  157. data/demo/doc/screenshots/bootstrap/readme/49_example.png +0 -0
  158. data/demo/doc/screenshots/bootstrap/readme/50_example.png +0 -0
  159. data/demo/log/.keep +0 -0
  160. data/demo/package.json +0 -21
  161. data/demo/public/favicon.ico +0 -0
  162. data/demo/test/application_system_test_case.rb +0 -8
  163. data/demo/test/controllers/bootstrap_controller_test.rb +0 -8
  164. data/demo/test/controllers/users_controller_test.rb +0 -13
  165. data/demo/test/fixtures/action_text/rich_texts.yml +0 -4
  166. data/demo/test/fixtures/users.yml +0 -2
  167. data/demo/test/system/bootstrap_test.rb +0 -84
  168. data/demo/test/test_helper.rb +0 -10
  169. data/demo/webpack.config.js +0 -20
  170. data/demo/yarn.lock +0 -7176
  171. data/gemfiles/5.2.gemfile +0 -4
data/README.md CHANGED
@@ -25,8 +25,8 @@ Some other nice things that `bootstrap_form` does for you are:
25
25
 
26
26
  `bootstrap_form` supports at a minimum the currently supported versions of Ruby and Rails:
27
27
 
28
- * Ruby 2.5+
29
- * Rails 5.2+
28
+ * Ruby 3.0+ (https://www.ruby-lang.org/en/downloads/branches/)
29
+ * Rails 6.0+ (https://guides.rubyonrails.org/maintenance_policy.html)
30
30
  * Bootstrap 5.0+
31
31
 
32
32
  ## Installation
@@ -42,7 +42,7 @@ And follow the remaining instructions in the [official bootstrap installation gu
42
42
  Add the `bootstrap_form` gem to your `Gemfile`:
43
43
 
44
44
  ```ruby
45
- gem "bootstrap_form", "~> 5.1"
45
+ gem "bootstrap_form", "~> 5.2"
46
46
  ```
47
47
 
48
48
  Then:
@@ -84,7 +84,7 @@ This generates the following HTML:
84
84
  <form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
85
85
  <div class="mb-3">
86
86
  <label class="form-label required" for="user_email">Email</label>
87
- <input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com">
87
+ <input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
88
88
  </div>
89
89
  <div class="mb-3">
90
90
  <label class="form-label" for="user_password">Password</label>
@@ -125,8 +125,6 @@ This generates:
125
125
 
126
126
  ### bootstrap_form_with
127
127
 
128
- Note that `form_with` in Rails 5.1 does not add IDs to form elements and labels by default, which are both important to Bootstrap markup. This behaviour is corrected in Rails 5.2.
129
-
130
128
  To get started, just use the `bootstrap_form_with` helper in place of `form_with`. Here's an example:
131
129
 
132
130
  ![Example 2](demo/doc/screenshots/bootstrap/readme/02_example.png "Example 2")
@@ -145,7 +143,7 @@ This generates:
145
143
  <form accept-charset="UTF-8" action="/users" method="post">
146
144
  <div class="mb-3">
147
145
  <label class="form-label required" for="user_email">Email</label>
148
- <input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com">
146
+ <input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
149
147
  </div>
150
148
  <div class="mb-3">
151
149
  <label class="form-label" for="user_password">Password</label>
@@ -200,7 +198,7 @@ date_field password_field time_field
200
198
  date_select phone_field time_select
201
199
  datetime_field radio_button time_zone_select
202
200
  datetime_local_field range_field url_field
203
- datetime_select rich_text_area (Rails 6+) week_field
201
+ datetime_select rich_text_area week_field
204
202
  ```
205
203
 
206
204
  By default, the helpers generate a `label` tag, and an `input`, `select`, or `textarea` tag, by calling the Rails `label` helper, and then the Rails helper with the same name as the `bootstrap_form` helper.
@@ -278,7 +276,7 @@ This generates:
278
276
  ```html
279
277
  <div class="mb-3">
280
278
  <label class="form-label custom-class required" for="user_email">Email</label>
281
- <input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com">
279
+ <input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="text" value="steve@example.com">
282
280
  </div>
283
281
  ```
284
282
 
@@ -294,7 +292,7 @@ This generates:
294
292
  ```html
295
293
  <div class="mb-3">
296
294
  <label class="form-label visually-hidden required" for="user_email">Email</label>
297
- <input class="form-control" id="user_email" name="user[email]" placeholder="Email" type="text" value="steve@example.com">
295
+ <input aria-required="true" class="form-control" id="user_email" name="user[email]" placeholder="Email" required="required" type="text" value="steve@example.com">
298
296
  </div>
299
297
  ```
300
298
 
@@ -312,7 +310,7 @@ This generates:
312
310
  ```html
313
311
  <div class="mb-3">
314
312
  <label class="form-label required" for="user_email">Email</label>
315
- <input class="custom-class" id="user_email" name="user[email]" type="text" value="steve@example.com">
313
+ <input aria-required="true" class="custom-class" id="user_email" name="user[email]" required="required" type="text" value="steve@example.com">
316
314
  </div>
317
315
  ```
318
316
 
@@ -438,7 +436,7 @@ This generates:
438
436
  <div class="mb-3">
439
437
  <label class="form-label required" for="user_email">Email</label>
440
438
  <div class="input-group input-group-lg">
441
- <input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com">
439
+ <input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
442
440
  <input class="btn btn-primary" data-disable-with="Subscribe" name="commit" type="submit" value="Subscribe">
443
441
  </div>
444
442
  </div>
@@ -503,7 +501,7 @@ Generated HTML:
503
501
 
504
502
  ```html
505
503
  <div class="mb-3">
506
- <input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com">
504
+ <input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
507
505
  </div>
508
506
  ```
509
507
 
@@ -753,7 +751,7 @@ This generates:
753
751
  ```html
754
752
  <div class="mb-3">
755
753
  <label class="form-label" for="user_excellence">Excellence</label>
756
- <input class="form-control" id="user_excellence" name="user[excellence]" type="range">
754
+ <input class="form-range" id="user_excellence" name="user[excellence]" type="range">
757
755
  </div>
758
756
  ```
759
757
 
@@ -771,7 +769,7 @@ This generates:
771
769
  ```html
772
770
  <div class="mb-3">
773
771
  <label class="form-label required" for="user_email">Email</label>
774
- <input class="form-control-plaintext" id="user_email" name="user[email]" readonly type="text" value="steve@example.com">
772
+ <input aria-required="true" class="form-control-plaintext" id="user_email" name="user[email]" readonly required="required" type="text" value="steve@example.com">
775
773
  </div>
776
774
  ```
777
775
 
@@ -791,7 +789,7 @@ This generates:
791
789
  <div class="mb-3 row">
792
790
  <label class="form-label col-form-label col-sm-2 required" for="user_email">Email</label>
793
791
  <div class="col-sm-10">
794
- <input class="form-control-plaintext" id="user_email" name="user[email]" readonly type="text" value="steve@example.com">
792
+ <input aria-required="true" class="form-control-plaintext" id="user_email" name="user[email]" readonly required="required" type="text" value="steve@example.com">
795
793
  </div>
796
794
  </div>
797
795
  </form>
@@ -946,8 +944,6 @@ will be rendered as
946
944
 
947
945
  ## Rich Text Areas AKA Trix Editor
948
946
 
949
- If you're using Rails 6, `bootstrap_form` supports the `rich_text_area` helper.
950
-
951
947
  ![Example 34](demo/doc/screenshots/bootstrap/readme/34_example.png "Example 34")
952
948
  ```erb
953
949
  <%= f.rich_text_area(:life_story) %>
@@ -1054,7 +1050,7 @@ This generates:
1054
1050
  <form accept-charset="UTF-8" action="/users" class="new_user row row-cols-auto g-3 align-items-center" id="new_user" method="post">
1055
1051
  <div class="col">
1056
1052
  <label class="form-label visually-hidden mr-sm-2 required" for="user_email">Email</label>
1057
- <input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com">
1053
+ <input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
1058
1054
  </div>
1059
1055
  <div class="col">
1060
1056
  <label class="form-label visually-hidden mr-sm-2" for="user_password">Password</label>
@@ -1116,7 +1112,7 @@ This generates:
1116
1112
  <div class="mb-3 row">
1117
1113
  <label class="form-label col-form-label col-sm-2 required" for="user_email">Email</label>
1118
1114
  <div class="col-sm-10">
1119
- <input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com">
1115
+ <input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
1120
1116
  </div>
1121
1117
  </div>
1122
1118
  <div class="mb-3 row">
@@ -1134,7 +1130,7 @@ This generates:
1134
1130
  </div>
1135
1131
  </div>
1136
1132
  </div>
1137
-
1133
+
1138
1134
  <div class="mb-3 row">
1139
1135
  <div class="col-sm-10 offset-sm-2">
1140
1136
  <input class="btn btn-secondary" data-disable-with="Create User" name="commit" type="submit" value="Create User">
@@ -1163,7 +1159,7 @@ This generates:
1163
1159
  <div class="mb-3 row">
1164
1160
  <label class="form-label col-form-label col-sm-2 required" for="user_email">Email</label>
1165
1161
  <div class="col-sm-10">
1166
- <input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com">
1162
+ <input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
1167
1163
  </div>
1168
1164
  </div>
1169
1165
  <div class="mb-3 row">
@@ -1220,7 +1216,7 @@ This generates:
1220
1216
  <div class="mb-3 row">
1221
1217
  <label class="form-label col-form-label col-sm-2 required" for="user_email">Email</label>
1222
1218
  <div class="col-sm-10">
1223
- <input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com">
1219
+ <input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
1224
1220
  </div>
1225
1221
  </div>
1226
1222
  <div class="mb-3 row">
@@ -1260,7 +1256,7 @@ This generates:
1260
1256
  <div class="mb-3 row">
1261
1257
  <label class="form-label col-form-label col-sm-2 required" for="user_email">Email</label>
1262
1258
  <div class="col-sm-10">
1263
- <input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com">
1259
+ <input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
1264
1260
  </div>
1265
1261
  </div>
1266
1262
  <div class="mb-3">
@@ -1301,7 +1297,7 @@ This generates:
1301
1297
  <form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
1302
1298
  <div class="mb-3">
1303
1299
  <label class="form-label required" for="user_email">Email</label>
1304
- <input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com">
1300
+ <input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
1305
1301
  </div>
1306
1302
  <div class="mb-3">
1307
1303
  <label class="form-label" for="user_password">Password</label>
@@ -1337,7 +1333,7 @@ This generates:
1337
1333
  ```html
1338
1334
  <form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
1339
1335
  <div class="mb-3 form-floating">
1340
- <input class="form-control" id="user_email" name="user[email]" placeholder="Email" type="email" value="steve@example.com">
1336
+ <input aria-required="true" class="form-control" id="user_email" name="user[email]" placeholder="Email" required="required" type="email" value="steve@example.com">
1341
1337
  <label class="form-label required" for="user_email">Email</label>
1342
1338
  </div>
1343
1339
  <div class="mb-3 form-floating">
@@ -1369,18 +1365,29 @@ Rails normally wraps fields with validation errors in a `div.field_with_errors`,
1369
1365
  By default, fields that have validation errors will be outlined in red and the
1370
1366
  error will be displayed below the field. Here's an example:
1371
1367
 
1368
+ ![Example 44](demo/doc/screenshots/bootstrap/readme/44_example.png "Example 44")
1369
+ ```erb
1370
+ <%= bootstrap_form_for(@user_with_error) do |f| %>
1371
+ <%= f.email_field :email %>
1372
+ <% end %>
1373
+ ```
1374
+
1375
+ Generated HTML:
1376
+
1372
1377
  ```html
1373
- <div class="mb-3">
1374
- <label class="form-label form-control-label" for="user_email">Email</label>
1375
- <input class="form-control is-invalid" id="user_email" name="user[email]" type="email" value="">
1376
- <small class="invalid-feedback">can't be blank</small>
1377
- </div>
1378
+ <form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
1379
+ <div class="mb-3">
1380
+ <label class="form-label required" for="user_email">Email</label>
1381
+ <input aria-required="true" class="form-control is-invalid" id="user_email" name="user[email]" required="required" type="email" value="steve.example.com">
1382
+ <div class="invalid-feedback">is invalid</div>
1383
+ </div>
1384
+ </form>
1378
1385
  ```
1379
1386
 
1380
1387
  You can turn off inline errors for the entire form like this:
1381
1388
 
1382
1389
  ```erb
1383
- <%= bootstrap_form_for(@user, inline_errors: false) do |f| %>
1390
+ <%= bootstrap_form_for(@user_with_error, inline_errors: false) do |f| %>
1384
1391
  ...
1385
1392
  <% end %>
1386
1393
  ```
@@ -1390,12 +1397,24 @@ You can turn off inline errors for the entire form like this:
1390
1397
  You can also display validation errors in the field's label; just turn
1391
1398
  on the `:label_errors` option. Here's an example:
1392
1399
 
1400
+ ![Example 45](demo/doc/screenshots/bootstrap/readme/45_example.png "Example 45")
1393
1401
  ```erb
1394
- <%= bootstrap_form_for(@user, label_errors: true) do |f| %>
1395
- ...
1402
+ <%= bootstrap_form_for(@user_with_error, label_errors: true) do |f| %>
1403
+ <%= f.email_field :email %>
1396
1404
  <% end %>
1397
1405
  ```
1398
1406
 
1407
+ Generated HTML:
1408
+
1409
+ ```html
1410
+ <form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
1411
+ <div class="mb-3">
1412
+ <label class="form-label required text-danger" for="user_email">Email is invalid</label>
1413
+ <input aria-required="true" class="form-control is-invalid" id="user_email" name="user[email]" required="required" type="email" value="steve.example.com">
1414
+ </div>
1415
+ </form>
1416
+ ```
1417
+
1399
1418
  By default, turning on `:label_errors` will also turn off
1400
1419
  `:inline_errors`. If you want both turned on, you can do that too:
1401
1420
 
@@ -1411,7 +1430,7 @@ To display an error message with an error summary, you can use the
1411
1430
  `alert_message` helper. This won't output anything unless a model validation
1412
1431
  has failed.
1413
1432
 
1414
- ![Example 44](demo/doc/screenshots/bootstrap/readme/44_example.png "Example 44")
1433
+ ![Example 46](demo/doc/screenshots/bootstrap/readme/46_example.png "Example 46")
1415
1434
  ```erb
1416
1435
  <%= bootstrap_form_for @user_with_error do |f| %>
1417
1436
  <%= f.alert_message "Please fix the errors below." %>
@@ -1434,7 +1453,7 @@ Which outputs:
1434
1453
 
1435
1454
  You can turn off the error summary like this:
1436
1455
 
1437
- ![Example 45](demo/doc/screenshots/bootstrap/readme/45_example.png "Example 45")
1456
+ ![Example 47](demo/doc/screenshots/bootstrap/readme/47_example.png "Example 47")
1438
1457
  ```erb
1439
1458
  <%= bootstrap_form_for @user_with_error do |f| %>
1440
1459
  <%= f.alert_message "Please fix the errors below.", error_summary: false %>
@@ -1451,7 +1470,7 @@ This generates:
1451
1470
 
1452
1471
  To output a simple unordered list of errors, use the `error_summary` helper.
1453
1472
 
1454
- ![Example 46](demo/doc/screenshots/bootstrap/readme/46_example.png "Example 46")
1473
+ ![Example 48](demo/doc/screenshots/bootstrap/readme/48_example.png "Example 48")
1455
1474
  ```erb
1456
1475
  <%= bootstrap_form_for @user_with_error do |f| %>
1457
1476
  <%= f.error_summary %>
@@ -1473,7 +1492,7 @@ Which outputs:
1473
1492
 
1474
1493
  If you want to display a custom inline error for a specific attribute not represented by a form field, use the `errors_on` helper.
1475
1494
 
1476
- ![Example 47](demo/doc/screenshots/bootstrap/readme/47_example.png "Example 47")
1495
+ ![Example 49](demo/doc/screenshots/bootstrap/readme/49_example.png "Example 49")
1477
1496
  ```erb
1478
1497
  <%= bootstrap_form_for @user_with_error do |f| %>
1479
1498
  <%= f.errors_on :email %>
@@ -1490,7 +1509,7 @@ Which outputs:
1490
1509
 
1491
1510
  You can hide the attribute name like this:
1492
1511
 
1493
- ![Example 48](demo/doc/screenshots/bootstrap/readme/48_example.png "Example 48")
1512
+ ![Example 50](demo/doc/screenshots/bootstrap/readme/50_example.png "Example 50")
1494
1513
  ```erb
1495
1514
  <%= bootstrap_form_for @user_with_error do |f| %>
1496
1515
  <%= f.errors_on :email, hide_attribute_name: true %>
@@ -1507,7 +1526,7 @@ Which outputs:
1507
1526
 
1508
1527
  You can also use a custom class for the wrapping div, like this:
1509
1528
 
1510
- ![Example 49](demo/doc/screenshots/bootstrap/readme/49_example.png "Example 49")
1529
+ ![Example 51](demo/doc/screenshots/bootstrap/readme/51_example.png "Example 51")
1511
1530
  ```erb
1512
1531
  <%= bootstrap_form_for @user_with_error do |f| %>
1513
1532
  <%= f.errors_on :email, custom_class: 'custom-error' %>
@@ -1542,7 +1561,7 @@ ActiveModel::Validations::PresenceValidator.
1542
1561
 
1543
1562
  In cases where this behaviour is undesirable, use the `required` option to force the class to be present or absent:
1544
1563
 
1545
- ![Example 50](demo/doc/screenshots/bootstrap/readme/50_example.png "Example 50")
1564
+ ![Example 52](demo/doc/screenshots/bootstrap/readme/52_example.png "Example 52")
1546
1565
  ```erb
1547
1566
  <%= f.password_field :login, label: "New Username", required: true %>
1548
1567
  <%= f.password_field :password, label: "New Password", required: false %>
@@ -1553,7 +1572,7 @@ This generates:
1553
1572
  ```html
1554
1573
  <div class="mb-3">
1555
1574
  <label class="form-label required" for="user_login">New Username</label>
1556
- <input class="form-control" id="user_login" name="user[login]" required="required" type="password">
1575
+ <input aria-required="true" class="form-control" id="user_login" name="user[login]" required="required" type="password">
1557
1576
  </div>
1558
1577
  <div class="mb-3">
1559
1578
  <label class="form-label" for="user_password">New Password</label>
@@ -1561,6 +1580,53 @@ This generates:
1561
1580
  </div>
1562
1581
  ```
1563
1582
 
1583
+ ### Required belongs_to associations
1584
+
1585
+ Adding a form control for a `belongs_to` field will automatically pick up the associated presence validator.
1586
+
1587
+ ![Example 53](demo/doc/screenshots/bootstrap/readme/53_example.png "Example 53")
1588
+ ```erb
1589
+ <%= bootstrap_form_for(@address, url: '/address') do |f| %>
1590
+ <%= f.collection_select :user_id, @users, :id, :email, include_blank: "Select a value" %>
1591
+ <%= f.text_field :street %>
1592
+ <%= f.text_field :city %>
1593
+ <%= f.text_field :state %>
1594
+ <%= f.text_field :zip_code %>
1595
+ <%= f.submit "Save" %>
1596
+ <% end %>
1597
+ ```
1598
+
1599
+ Generated HTML:
1600
+
1601
+ ```html
1602
+ <form accept-charset="UTF-8" action="/address" class="new_address" id="new_address_1" method="post">
1603
+ <div class="mb-3">
1604
+ <label class="form-label required" for="address_user_id">User</label>
1605
+ <select class="form-select" id="address_user_id" name="address[user_id]">
1606
+ <option value="">Select a value</option>
1607
+ <option value="">steve@example.com</option>
1608
+ </select>
1609
+ </div>
1610
+ <div class="mb-3">
1611
+ <label class="form-label" for="address_street">Street</label>
1612
+ <input class="form-control" id="address_street" name="address[street]" type="text" value="Foo">
1613
+ </div>
1614
+ <div class="mb-3">
1615
+ <label class="form-label" for="address_city">City</label>
1616
+ <input class="form-control" id="address_city" name="address[city]" type="text">
1617
+ </div>
1618
+ <div class="mb-3">
1619
+ <label class="form-label" for="address_state">State</label>
1620
+ <input class="form-control" id="address_state" name="address[state]" type="text">
1621
+ </div>
1622
+ <div class="mb-3">
1623
+ <label class="form-label" for="address_zip_code">Zip code</label>
1624
+ <input class="form-control" id="address_zip_code" name="address[zip_code]" type="text">
1625
+ </div>
1626
+ <input class="btn btn-secondary" data-disable-with="Save" name="commit" type="submit" value="Save">
1627
+ </form>
1628
+ ```
1629
+
1564
1630
  ## Internationalization
1565
1631
 
1566
1632
  bootstrap_form follows standard rails conventions so it's i18n-ready. See more
data/RELEASING.md CHANGED
@@ -11,7 +11,18 @@ Follow these steps to release a new version of bootstrap_form to rubygems.org.
11
11
  ## How to release
12
12
 
13
13
  1. Run `BUNDLE_GEMFILE=gemfiles/7.0.gemfile bundle update` to make sure that you have all the gems necessary for testing and releasing.
14
- 2. **Ensure the tests are passing by running `BUNDLE_GEMFILE=gemfiles/7.0.gemfile bundle update`.** (Currently this step shows a lot of warnings about method redefinitions, but otherwise everything must be green before release.)
14
+ 2. **Ensure the tests are passing by running the tests**
15
+
16
+ (There should be no errors or warnings.)
17
+
18
+ BUNDLE_GEMFILE=gemfiles/7.0.gemfile bundle exec rake test
19
+
20
+ 2. **Ensure the demo tests are passing by running**
21
+
22
+ cd demo
23
+ bundle update
24
+ bundle exec rake test:all
25
+
15
26
  3. Determine which would be the correct next version number according to [semver](http://semver.org/).
16
27
  4. Update the version in `./lib/bootstrap_form/version.rb`.
17
28
  5. Update the GitHub diff links at the beginning of `CHANGELOG.md` (The pattern should be obvious when you look at them).
data/Rakefile CHANGED
@@ -17,12 +17,13 @@ end
17
17
 
18
18
  require 'bundler/gem_tasks'
19
19
 
20
- require 'rake/testtask'
20
+ require "minitest/test_task"
21
21
 
22
- Rake::TestTask.new(:test) do |t|
23
- t.libs << 'test'
24
- t.pattern = 'test/**/*_test.rb'
25
- t.verbose = false
22
+ Minitest::TestTask.create(:test) do |t|
23
+ t.libs << "test"
24
+ t.libs << "lib"
25
+ t.warning = false
26
+ t.test_globs = ["test/**/*_test.rb"]
26
27
  end
27
28
 
28
29
  # This automatically updates GitHub Releases whenever we `rake release` the gem
@@ -34,4 +35,4 @@ end
34
35
  desc 'Run RuboCop checks'
35
36
  RuboCop::RakeTask.new(:rubocop)
36
37
 
37
- task default: %i[test rubocop]
38
+ task default: %i[test rubocop:autocorrect]
@@ -3,30 +3,28 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
4
  require "bootstrap_form/version"
5
5
 
6
- REQUIRED_RAILS_VERSION = ">= 5.2".freeze
7
-
8
6
  Gem::Specification.new do |s|
9
7
  s.name = "bootstrap_form"
10
8
  s.version = BootstrapForm::VERSION
11
9
  s.authors = ["Stephen Potenza", "Carlos Lopes"]
12
10
  s.email = ["potenza@gmail.com", "carlos.el.lopes@gmail.com"]
13
11
  s.homepage = "https://github.com/bootstrap-ruby/bootstrap_form"
14
- s.summary = "Rails form builder that makes it easy to style forms using "\
12
+ s.summary = "Rails form builder that makes it easy to style forms using " \
15
13
  "Bootstrap 5"
16
- s.description = "bootstrap_form is a rails form builder that makes it super "\
14
+ s.description = "bootstrap_form is a rails form builder that makes it super " \
17
15
  "easy to create beautiful-looking forms using Bootstrap 5"
18
16
  s.license = "MIT"
19
17
  s.metadata = { "rubygems_mfa_required" => "true" }
20
18
 
21
19
  s.files = `git ls-files -z`.split("\x0").reject do |f|
22
- f.match(%r{^(test)/})
20
+ f.match(%r{^(test)/|^(demo)/})
23
21
  end
24
22
 
25
23
  s.bindir = "exe"
26
24
  s.require_paths = ["lib"]
27
25
 
28
- s.required_ruby_version = ">= 2.7"
26
+ s.required_ruby_version = ">= 3.0"
29
27
 
30
- s.add_dependency("actionpack", REQUIRED_RAILS_VERSION)
31
- s.add_dependency("activemodel", REQUIRED_RAILS_VERSION)
28
+ s.add_dependency("actionpack", BootstrapForm::REQUIRED_RAILS_VERSION)
29
+ s.add_dependency("activemodel", BootstrapForm::REQUIRED_RAILS_VERSION)
32
30
  end
data/docker-compose.yml CHANGED
@@ -5,9 +5,10 @@ services:
5
5
  build:
6
6
  context: .
7
7
  args:
8
- NODE_MAJOR: '12'
9
- YARN_VERSION: '1.22.4'
10
- image: bootstrap-form:0.0.1
8
+ NODE_MAJOR: "12"
9
+ YARN_VERSION: "1.22.4"
10
+ RUBY_VERSION: ${RUBY_VERSION}
11
+ image: bootstrap-form:latest-$RUBY_VERSION
11
12
  tmpfs:
12
13
  - /tmp
13
14
 
@@ -17,15 +18,6 @@ services:
17
18
  tty: true
18
19
  volumes:
19
20
  - .:/app:cached
20
- # - rails_cache:/app/tmp/cache
21
- # - bundle:/app/vendor/bundle
22
- # - node_modules:/app/node_modules
23
- # - packs:/app/public/packs
24
- - /etc/passwd:/etc/passwd:ro
25
- # One or the other of the following lines might be redundant, or one might be
26
- # better than the other.
27
- - ~/.ssh:${HOME}/.ssh
28
- - ${SSH_AUTH_SOCK}:/ssh-agent
29
21
  environment:
30
22
  - SSH_AUTH_SOCK=/ssh-agent
31
23
  - NODE_ENV=development
@@ -34,16 +26,6 @@ services:
34
26
  - WEBPACKER_DEV_SERVER_HOST=webpacker
35
27
  - WEB_CONCURRENCY=1
36
28
  - HISTFILE=/app/.bash_history
29
+ ports:
30
+ - "3000:3000"
37
31
  command: /bin/bash
38
-
39
- # server:
40
- # <<: *shell
41
- # command: sh -c "cd demo/app && bundle exec rails server -b 0.0.0.0"
42
- # ports:
43
- # - '3000:3000'
44
-
45
- # volumes:
46
- # bundle:
47
- # node_modules:
48
- # rails_cache:
49
- # packs:
data/gemfiles/6.0.gemfile CHANGED
@@ -1,4 +1,4 @@
1
- gems = "#{File.dirname __dir__}/Gemfile"
1
+ gems = "#{__dir__}/common.gemfile"
2
2
  eval File.read(gems), binding, gems # rubocop: disable Security/Eval
3
3
 
4
4
  gem "rails", "~> 6.0.0"
data/gemfiles/6.1.gemfile CHANGED
@@ -1,4 +1,4 @@
1
- gems = "#{File.dirname __dir__}/Gemfile"
1
+ gems = "#{__dir__}/common.gemfile"
2
2
  eval File.read(gems), binding, gems # rubocop: disable Security/Eval
3
3
 
4
4
  gem "rails", "~> 6.1.0"
data/gemfiles/7.0.gemfile CHANGED
@@ -1,6 +1,5 @@
1
- gems = "#{File.dirname __dir__}/Gemfile"
1
+ gems = "#{__dir__}/common.gemfile"
2
2
  eval File.read(gems), binding, gems # rubocop: disable Security/Eval
3
3
 
4
- # 7.0.0 has an issue with Ruby 3.1.
5
- # And a test case has an issue with 7.0.1
6
4
  gem "rails", "~> 7.0.2"
5
+ gem "sprockets-rails", require: "sprockets/railtie"
@@ -0,0 +1,28 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec path: File.dirname(__dir__)
4
+
5
+ # To test with different Rails versions, use the files in `./gemfiles`
6
+
7
+ group :development do
8
+ gem "htmlbeautifier"
9
+ gem "puma"
10
+ gem "rubocop-performance", require: false
11
+ gem "rubocop-rails", require: false
12
+ end
13
+
14
+ group :test do
15
+ gem "diffy"
16
+ gem "equivalent-xml"
17
+ gem "mocha"
18
+ gem "sqlite3"
19
+ end
20
+
21
+ group :development, :test do
22
+ gem "debug"
23
+ gem "pry-byebug"
24
+ end
25
+
26
+ group :ci do
27
+ gem "danger"
28
+ end
@@ -1,4 +1,5 @@
1
- gems = "#{File.dirname __dir__}/Gemfile"
1
+ gems = "#{__dir__}/common.gemfile"
2
2
  eval File.read(gems), binding, gems # rubocop: disable Security/Eval
3
3
 
4
- gem "rails", git: "https://github.com/rails/rails.git"
4
+ gem "rails", git: "https://github.com/rails/rails.git", branch: "main"
5
+ gem "sprockets-rails", require: "sprockets/railtie"
@@ -24,14 +24,8 @@ module BootstrapForm
24
24
 
25
25
  def label_classes(name, options, custom_label_col, group_layout)
26
26
  classes = ["form-label", options[:class], label_layout_classes(custom_label_col, group_layout)]
27
-
28
- case options.delete(:required)
29
- when true
30
- classes << "required"
31
- when nil, :default
32
- classes << "required" if required_attribute?(object, name)
33
- end
34
-
27
+ classes << "required" if required_field_options(options, name)[:required]
28
+ options.delete(:required)
35
29
  classes << "text-danger" if label_errors && error?(name)
36
30
  classes.flatten.compact
37
31
  end
@@ -46,7 +40,7 @@ module BootstrapForm
46
40
 
47
41
  def label_text(name, options)
48
42
  if label_errors && error?(name)
49
- (options[:text] || object.class.human_attribute_name(name)).to_s.concat(" #{get_error_messages(name)}")
43
+ (options[:text] || object.class.human_attribute_name(name)).to_s + " #{get_error_messages(name)}"
50
44
  else
51
45
  options[:text] || object&.class.try(:human_attribute_name, name)
52
46
  end