formtastic 5.0.0 → 6.0.0.alpha

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.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/integration.yaml +36 -0
  3. data/.github/workflows/test.yml +26 -20
  4. data/.gitignore +2 -1
  5. data/Appraisals +23 -0
  6. data/CHANGELOG.md +18 -0
  7. data/CONTRIBUTING.md +27 -0
  8. data/Gemfile +5 -0
  9. data/MIT-LICENSE +1 -1
  10. data/README.md +9 -41
  11. data/Rakefile +1 -1
  12. data/formtastic.gemspec +17 -10
  13. data/gemfiles/rails_72.gemfile +9 -0
  14. data/gemfiles/rails_80.gemfile +9 -0
  15. data/gemfiles/rails_81.gemfile +9 -0
  16. data/gemfiles/rails_edge.gemfile +9 -0
  17. data/lib/formtastic/form_builder.rb +25 -25
  18. data/lib/formtastic/helpers/action_helper.rb +0 -1
  19. data/lib/formtastic/helpers/errors_helper.rb +71 -14
  20. data/lib/formtastic/helpers/input_helper.rb +4 -2
  21. data/lib/formtastic/i18n.rb +0 -1
  22. data/lib/formtastic/inputs/base/aria.rb +26 -0
  23. data/lib/formtastic/inputs/base/collections.rb +1 -1
  24. data/lib/formtastic/inputs/base/errors.rb +1 -1
  25. data/lib/formtastic/inputs/base/html.rb +1 -1
  26. data/lib/formtastic/inputs/base/labelling.rb +1 -1
  27. data/lib/formtastic/inputs/base/validations.rb +32 -8
  28. data/lib/formtastic/inputs/base.rb +4 -2
  29. data/lib/formtastic/inputs/country_input.rb +9 -6
  30. data/lib/formtastic/version.rb +1 -1
  31. data/lib/formtastic.rb +6 -2
  32. data/lib/generators/formtastic/form/form_generator.rb +2 -3
  33. data/lib/generators/formtastic/install/install_generator.rb +0 -1
  34. data/lib/generators/formtastic/stylesheets/stylesheets_generator.rb +15 -0
  35. data/{app/assets/stylesheets → lib/generators/templates}/formtastic.css +4 -4
  36. data/lib/generators/templates/formtastic.rb +7 -1
  37. data/script/integration-template.rb +14 -11
  38. data/script/integration.sh +17 -4
  39. data/spec/action_class_finder_spec.rb +0 -1
  40. data/spec/actions/button_action_spec.rb +0 -1
  41. data/spec/actions/generic_action_spec.rb +0 -1
  42. data/spec/actions/input_action_spec.rb +0 -1
  43. data/spec/actions/link_action_spec.rb +0 -1
  44. data/spec/builder/custom_builder_spec.rb +0 -1
  45. data/spec/builder/error_proc_spec.rb +0 -1
  46. data/spec/builder/semantic_fields_for_spec.rb +72 -2
  47. data/spec/fast_spec_helper.rb +0 -1
  48. data/spec/generators/formtastic/stylesheets/stylesheets_generator_spec.rb +22 -0
  49. data/spec/helpers/actions_helper_spec.rb +0 -1
  50. data/spec/helpers/form_helper_spec.rb +0 -1
  51. data/spec/helpers/input_helper_spec.rb +12 -1
  52. data/spec/helpers/inputs_helper_spec.rb +0 -1
  53. data/spec/helpers/reflection_helper_spec.rb +0 -1
  54. data/spec/helpers/semantic_errors_helper_spec.rb +114 -7
  55. data/spec/i18n_spec.rb +0 -1
  56. data/spec/input_class_finder_spec.rb +0 -1
  57. data/spec/inputs/base/collections_spec.rb +41 -0
  58. data/spec/inputs/boolean_input_spec.rb +0 -1
  59. data/spec/inputs/check_boxes_input_spec.rb +1 -2
  60. data/spec/inputs/color_input_spec.rb +0 -1
  61. data/spec/inputs/country_input_spec.rb +5 -6
  62. data/spec/inputs/custom_input_spec.rb +0 -1
  63. data/spec/inputs/datalist_input_spec.rb +0 -1
  64. data/spec/inputs/date_picker_input_spec.rb +0 -1
  65. data/spec/inputs/date_select_input_spec.rb +1 -2
  66. data/spec/inputs/datetime_picker_input_spec.rb +0 -1
  67. data/spec/inputs/datetime_select_input_spec.rb +1 -2
  68. data/spec/inputs/email_input_spec.rb +0 -1
  69. data/spec/inputs/file_input_spec.rb +0 -1
  70. data/spec/inputs/hidden_input_spec.rb +0 -1
  71. data/spec/inputs/include_blank_spec.rb +0 -1
  72. data/spec/inputs/label_spec.rb +32 -1
  73. data/spec/inputs/number_input_spec.rb +0 -1
  74. data/spec/inputs/password_input_spec.rb +1 -2
  75. data/spec/inputs/phone_input_spec.rb +0 -1
  76. data/spec/inputs/placeholder_spec.rb +0 -1
  77. data/spec/inputs/radio_input_spec.rb +0 -1
  78. data/spec/inputs/range_input_spec.rb +0 -1
  79. data/spec/inputs/readonly_spec.rb +0 -1
  80. data/spec/inputs/search_input_spec.rb +0 -1
  81. data/spec/inputs/select_input_spec.rb +0 -1
  82. data/spec/inputs/string_input_spec.rb +67 -2
  83. data/spec/inputs/text_input_spec.rb +0 -1
  84. data/spec/inputs/time_picker_input_spec.rb +0 -1
  85. data/spec/inputs/time_select_input_spec.rb +1 -2
  86. data/spec/inputs/time_zone_input_spec.rb +0 -1
  87. data/spec/inputs/url_input_spec.rb +0 -1
  88. data/spec/inputs/with_options_spec.rb +0 -1
  89. data/spec/localizer_spec.rb +0 -1
  90. data/spec/namespaced_class_finder_spec.rb +0 -1
  91. data/spec/spec_helper.rb +2 -1
  92. data/spec/support/custom_macros.rb +11 -3
  93. data/spec/support/specialized_class_finder_shared_example.rb +0 -1
  94. data/spec/support/test_environment.rb +1 -1
  95. metadata +53 -40
  96. data/Gemfile.lock +0 -140
  97. data/app/assets/stylesheets/formtastic_ie6.css +0 -33
  98. data/app/assets/stylesheets/formtastic_ie7.css +0 -23
  99. data/gemfiles/rails_6.0/Gemfile +0 -5
  100. data/gemfiles/rails_6.1/Gemfile +0 -5
  101. data/gemfiles/rails_7.0/Gemfile +0 -5
  102. data/gemfiles/rails_7.1/Gemfile +0 -5
  103. data/gemfiles/rails_edge/Gemfile +0 -13
  104. data/lib/formtastic/engine.rb +0 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 70272678a1b436280de8d89add80583ca886cac153f6d4e43be93e6a641c344f
4
- data.tar.gz: d2549407b0a3c5d21e7afe24cfd21bd008c9ca957bd06cf2d59fb7b3101fa042
3
+ metadata.gz: 211d0d0b33c1ea9fbd35858a71924740a27dd0a39b4e0e0cc48f16e7753388b1
4
+ data.tar.gz: 102435b082e7b83ddcfd874d8fe89f016b622e7f48fea56de0f8a136e162e072
5
5
  SHA512:
6
- metadata.gz: 4164b15cb0dc3eb5d2d90f257977d59b8459a1708f4520ba6ff1708eaf9dd898f2713d9f59945c1d50c2b481e2175c0e3d7af6259c9f1e715a836aac0dd0e53b
7
- data.tar.gz: e93800c9ca16ea4afb445f5a95cb56e1dd0224f06654ef8af7b13dba8ddb4c520e09c4b49c760d10a7e71d6f381f9b6fb91bbe61e26e1cab83823c7e2dc827de
6
+ metadata.gz: 454ed223f77ba1aa04c722e08fde0cf6494343e95f871611bc57275f335cd1cae26933b4ca45505abb58f4cfba539a9ffd0ec9888c55a7cd7a1d2badcbecf7c0
7
+ data.tar.gz: af525b290f06a4bb5753842a52ea6f7ff439b6496a8e435d1fa23ca9d3c2edcbcbc74eb8e44f46adeb7eb608f2fa3ffbcde6b0dfb8919b58dd37b39ab6407349
@@ -0,0 +1,36 @@
1
+ name: integration
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+
9
+ jobs:
10
+ ci:
11
+ runs-on: ubuntu-latest
12
+ needs: test
13
+ steps:
14
+ - uses: actions/checkout@v6
15
+ test:
16
+ runs-on: ubuntu-22.04
17
+
18
+ strategy:
19
+ fail-fast: false
20
+
21
+ steps:
22
+ - uses: actions/checkout@v6
23
+
24
+ - uses: actions/setup-node@v6
25
+ with:
26
+ node-version: 11
27
+
28
+ - name: Set up Ruby
29
+ uses: ruby/setup-ruby@v1
30
+ with:
31
+ ruby-version: '4.0'
32
+ bundler-cache: true
33
+ bundler: latest
34
+
35
+ - name: Run integration
36
+ run: script/integration.sh
@@ -2,6 +2,8 @@ name: test
2
2
 
3
3
  on:
4
4
  push:
5
+ branches:
6
+ - main
5
7
  pull_request:
6
8
 
7
9
  jobs:
@@ -9,41 +11,46 @@ jobs:
9
11
  runs-on: ubuntu-latest
10
12
  needs: test
11
13
  steps:
12
- - uses: actions/checkout@v2
14
+ - uses: actions/checkout@v6
13
15
  test:
14
- runs-on: ubuntu-20.04
16
+ runs-on: ubuntu-22.04
15
17
 
16
18
  strategy:
17
19
  fail-fast: false
18
20
 
19
21
  matrix:
20
22
  gemfile:
21
- - gemfiles/rails_6.0/Gemfile
22
- - gemfiles/rails_6.1/Gemfile
23
- - gemfiles/rails_7.0/Gemfile
24
- - gemfiles/rails_7.1/Gemfile
25
- - gemfiles/rails_edge/Gemfile
23
+ - gemfiles/rails_72.gemfile
24
+ - gemfiles/rails_80.gemfile
25
+ - gemfiles/rails_81.gemfile
26
+ - gemfiles/rails_edge.gemfile
26
27
 
27
28
  ruby:
28
- - 2.6.6
29
- - 2.7.2
30
- - 3.0.0
29
+ - '3.1'
30
+ - '3.2'
31
+ - '3.3'
32
+ - '3.4'
33
+ - '4.0'
31
34
 
32
35
  exclude:
33
- - ruby: 2.6.6
34
- gemfile: gemfiles/rails_7.0/Gemfile
35
- - ruby: 2.6.6
36
- gemfile: gemfiles/rails_7.1/Gemfile
37
- - ruby: 2.6.6
38
- gemfile: gemfiles/rails_edge/Gemfile
36
+ - gemfile: gemfiles/rails_80.gemfile
37
+ ruby: '3.1'
38
+ - gemfile: gemfiles/rails_81.gemfile
39
+ ruby: '3.1'
40
+ - gemfile: gemfiles/rails_edge.gemfile
41
+ ruby: '3.1'
42
+ - gemfile: gemfiles/rails_edge.gemfile
43
+ ruby: '3.2'
44
+ - gemfile: gemfiles/rails_72.gemfile
45
+ ruby: '4.0'
39
46
 
40
47
  env:
41
48
  BUNDLE_GEMFILE: ${{ matrix.gemfile }}
42
49
 
43
50
  steps:
44
- - uses: actions/checkout@v2
51
+ - uses: actions/checkout@v6
45
52
 
46
- - uses: actions/setup-node@v2
53
+ - uses: actions/setup-node@v6
47
54
  with:
48
55
  node-version: 11
49
56
 
@@ -57,5 +64,4 @@ jobs:
57
64
  - name: Run tests
58
65
  run: |
59
66
  bundle exec rake spec
60
- script/integration.sh
61
- continue-on-error: ${{ matrix.gemfile == 'gemfiles/rails_edge/Gemfile' }}
67
+ continue-on-error: ${{ matrix.gemfile == 'gemfiles/rails_edge.gemfile' }}
data/.gitignore CHANGED
@@ -14,5 +14,6 @@ log/*
14
14
  .yardoc
15
15
  doc/
16
16
  tmp
17
- gemfiles/*/Gemfile.lock
17
+ Gemfile.lock
18
+ gemfiles/*.gemfile.lock
18
19
  /dummy/
data/Appraisals ADDED
@@ -0,0 +1,23 @@
1
+ appraise "rails-72" do
2
+ gem "actionpack", "~> 7.2.3"
3
+ gem "activesupport", "~> 7.2.3"
4
+ gem "activerecord", "~> 7.2.3"
5
+ end
6
+
7
+ appraise "rails-80" do
8
+ gem "actionpack", "~> 8.0.4"
9
+ gem "activesupport", "~> 8.0.4"
10
+ gem "activerecord", "~> 8.0.4"
11
+ end
12
+
13
+ appraise "rails-81" do
14
+ gem "actionpack", "~> 8.1.2"
15
+ gem "activesupport", "~> 8.1.2"
16
+ gem "activerecord", "~> 8.1.2"
17
+ end
18
+
19
+ appraise "rails-edge" do
20
+ gem "actionpack", git: "https://github.com/rails/rails.git", branch: "main"
21
+ gem "activesupport", git: "https://github.com/rails/rails.git", branch: "main"
22
+ gem "activerecord", git: "https://github.com/rails/rails.git", branch: "main"
23
+ end
data/CHANGELOG.md CHANGED
@@ -1,4 +1,21 @@
1
+ ## 6.0.0.alpha
2
+
3
+ * Removed support for Rails 6.0 & 7.1 (min version is now 7.2)
4
+ * Removed support for Ruby < 3.1 in line with Rails 7.2
5
+ * Added requirement for minimum Ruby Gems version in line with Rails 7.2
6
+ * Added formtastic:stylesheets generator (does not include legacy IE stylesheets)
7
+ * Removed formtastic engine stylesheets
8
+ * Added `semantic_errors_link_to_inputs` config option to improve accessibility of `semantic_errors`. ([#1388](https://github.com/formtastic/formtastic/pull/1388))
9
+ * Fixed country_select compatibility by switching from v1 to v2 syntax ([#1382](https://github.com/formtastic/formtastic/pull/1382))
10
+ * Fixed that passing caller to Deprecation#warn is deprecated ([#1384](https://github.com/formtastic/formtastic/pull/1384))
11
+ * Added `label_html` option for overriding & adding label HTML attributes ([#1379](https://github.com/formtastic/formtastic/pull/1379))
12
+ * Added better support for collections of Symbols ([#1391](https://github.com/formtastic/formtastic/pull/1391))
13
+ * Fixed issue with inferred max length for integer columns
14
+ * Fixed issue with Prox length validations ([#1405](https://github.com/formtastic/formtastic/pull/1405))
15
+ * Various minor Ruby, Rails, documentation and maintenance activities
16
+
1
17
  ## 5.0.0
18
+
2
19
  * Added support for Rails 7.1 ([#1371](https://github.com/formtastic/formtastic/pull/1371))
3
20
  * Removed support for Rails < 6.0.0 ([#1354](https://github.com/formtastic/formtastic/pull/1354))
4
21
  * Removed support for Rubies < 2.6.0 ([#1332](https://github.com/formtastic/formtastic/pull/1332), [#1355](https://github.com/formtastic/formtastic.git/pull/1355))
@@ -8,6 +25,7 @@
8
25
  * Use frozen_string_literal internally ([#1339](https://github.com/formtastic/formtastic/pull/1339))
9
26
 
10
27
  ## 4.0.0
28
+
11
29
  * Fixed default_columns_for_object when object has non-standard foreign keys (#1241)
12
30
  * Fixed missing constants in production (#911)
13
31
  * Removed support for Rails 3 and 4.0 (#1108)
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,27 @@
1
+ # Contributing
2
+
3
+ ## General Workflow
4
+
5
+ * Fork the project on Github
6
+ * Install development dependencies (`bundle install` and `bundle exec rake appraisal:install`)
7
+ * Run the appraisals to check you've got a clean build with passing tests to work on (`bundle exec rake`)
8
+ * Create a topic branch for your changes
9
+ * Ensure that you provide *documentation* and *test coverage* for your changes (patches won't be accepted without)
10
+ * Ensure that all tests still pass (`bundle exec rake`)
11
+ * Create a pull request on Github (these are also a great place to start a conversation around a WIP patch as early as possible)
12
+
13
+
14
+ ## Continuos Integration
15
+
16
+ Formtastic supports multiple versions of Rails and Ruby. Here's the approach to managing the complexity:
17
+
18
+ * The gemspec has a `required_ruby_version` that matches the minimum Ruby version supported by the minimum Rails version we currently support.
19
+ * The gemspec has a dependency on `actionpack` matching the minimum Rails version we currently support.
20
+ * The gemspec has several development dependencies, but we're not specific about which version. That complexity is handled by Appraisals and/or bundler.
21
+ * There is an Appraisal for each of the Rails versions we currently test with (eg Rails 7, 8 and edge) that can name specific versions of these dependencies and developer dependencies as needed.
22
+ * Use `bundle exec appraisal` to generate new `gemfiles/*` as needed. We do not check-in the `*.gemfile.lock`, so that each Ruby version in the CI matrix can select an appropriate version of each dependency.
23
+ * The GitHub `test.yml` workflow runs a matrix of builds agqainst multiple Ruby and Rails versions, excluding any that don't make sense based on the minimum Ruby version for certain Rails versions.
24
+
25
+
26
+
27
+
data/Gemfile CHANGED
@@ -1,3 +1,8 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ # Which version of Rails to use specifically for local development. These currently match rails_8.gemfile.
4
+ gem "actionpack", "~> 8.0.2"
5
+ gem "activesupport", "~> 8.0.2"
6
+ gem "activerecord", "~> 8.0.2"
7
+
3
8
  gemspec
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2008-2021
1
+ Copyright (c) 2007-2025
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -9,17 +9,15 @@ Formtastic is a Rails FormBuilder DSL (with some other goodies) to make it far e
9
9
 
10
10
  ## Documentation & Support
11
11
 
12
- * [Documentation is available on rdoc.info](https://rdoc.info/projects/formtastic/formtastic)
12
+ * [Documentation is available on rubydoc.info](https://rubydoc.info/github/formtastic/formtastic)
13
13
  * [We track issues & bugs on GitHub](https://github.com/formtastic/formtastic/issues)
14
14
  * [We have a wiki on GitHub](https://github.com/formtastic/formtastic/wiki)
15
15
  * [StackOverflow can help](https://stackoverflow.com/questions/tagged/formtastic)
16
16
 
17
17
  ## Compatibility
18
18
 
19
- * Formtastic 5 requires Rails 6.0 and Ruby 2.6 minimum
20
- * Formtastic 4 requires Rails 5.2 and Ruby 2.4 minimum
21
- * Formtastic 3 requires Rails 3.2.13 minimum
22
- * Formtastic 2 requires Rails 3
19
+ * Formtastic 5.0 (current release) requires Rails 6.0 and Ruby 2.6 minimum
20
+ * Formtastic 6.0 / edge requires Rails 7.2 and Ruby 3.1 minimum, inline with Rails minimum supported versions
23
21
  * Formtastic, much like Rails, is very ActiveRecord-centric. Many are successfully using other ActiveModel-like ORMs and objects (DataMapper, MongoMapper, Mongoid, Authlogic, Devise...) but we're not guaranteeing full compatibility at this stage. Patches are welcome!
24
22
 
25
23
  ## The Story
@@ -101,37 +99,12 @@ $ rails generate formtastic:install
101
99
 
102
100
  ## Stylesheets
103
101
 
104
- A proof-of-concept set of stylesheets are provided which you can include in your layout. Customization is best achieved by overriding these styles in an additional stylesheet.
102
+ An optional proof-of-concept stylesheet can be generated and installed into your app:
105
103
 
106
- Rails 3.1 introduces an asset pipeline that allows plugins like Formtastic to serve their own Stylesheets, Javascripts, etc without having to run generators that copy them across to the host application. Formtastic makes three stylesheets available as an Engine, you just need to require them in your global stylesheets.
107
-
108
- ```css
109
- # app/assets/stylesheets/application.css
110
- *= require formtastic
111
- *= require my_formtastic_changes
112
- ```
113
-
114
- Conditional stylesheets need to be compiled separately to prevent them being bundled and included with other application styles. Remove `require_tree .` from application.css and specify required stylesheets individually.
115
-
116
- ```css
117
- # app/assets/stylesheets/ie6.css
118
- *= require formtastic_ie6
119
-
120
- # app/assets/stylesheets/ie7.css
121
- *= require formtastic_ie7
122
- ```
123
-
124
- ```erb
125
- # app/views/layouts/application.html.erb
126
- <%= stylesheet_link_tag 'application' %>
127
- <!--[if IE 6]><%= stylesheet_link_tag 'ie6' %><![endif]-->
128
- <!--[if IE 7]><%= stylesheet_link_tag 'ie7' %><![endif]-->
104
+ ```shell
105
+ $ rails generate formtastic:stylesheet
129
106
  ```
130
107
 
131
- ```ruby
132
- # config/environments/production.rb
133
- config.assets.precompile += %w( ie6.css ie7.css )
134
- ```
135
108
 
136
109
  ## Usage
137
110
 
@@ -608,18 +581,13 @@ You can use your new input with `:as => :date_picker`.
608
581
 
609
582
  There are none other than Rails itself, but...
610
583
 
611
- * If you want to use the `:country` input, you'll need to install the [country-select plugin](https://github.com/stefanpenner/country_select) (or any other country_select plugin with the same API). Both 1.x and 2.x are supported, but they behave differently when storing data, so please see their [upgrade notes](https://github.com/stefanpenner/country_select/blob/master/UPGRADING.md) if switching from 1.x.
584
+ * If you want to use the `:country` input, you'll need to install the [country-select plugin](https://github.com/countries/country_select) (or any other country_select plugin with the same API).
612
585
  * There are a bunch of development dependencies if you plan to contribute to Formtastic
613
586
 
614
587
 
615
588
  ## How to contribute
616
589
 
617
- * Fork the project on Github
618
- * Install development dependencies (`bundle install` and `bin/appraisal install`)
619
- * Create a topic branch for your changes
620
- * Ensure that you provide *documentation* and *test coverage* for your changes (patches won't be accepted without)
621
- * Ensure that all tests pass (`bundle exec rake`)
622
- * Create a pull request on Github (these are also a great place to start a conversation around a patch as early as possible)
590
+ See `CONTRIBUTING.md`
623
591
 
624
592
 
625
593
  ## Project Info
@@ -628,5 +596,5 @@ Formtastic was created by [Justin French](https://www.justinfrench.com) with con
628
596
 
629
597
  The project is hosted on Github: [https://github.com/formtastic/formtastic](https://github.com/formtastic/formtastic), where your contributions, forkings, comments, issues and feedback are greatly welcomed.
630
598
 
631
- Copyright (c) 2007-2021, released under the MIT license.
599
+ Copyright (c) 2007-2025, released under the MIT license.
632
600
 
data/Rakefile CHANGED
@@ -25,7 +25,7 @@ namespace :appraisal do
25
25
  end
26
26
 
27
27
  def for_all_gemfiles(*args)
28
- Dir.glob("gemfiles/*/Gemfile").sort.each do |gemfile|
28
+ Dir.glob("gemfiles/*.gemfile").sort.each do |gemfile|
29
29
  Bundler.with_original_env do
30
30
  sh({ "APPRAISAL_INITIALIZED" => "true", "BUNDLE_GEMFILE" => gemfile }, "bundle", *args)
31
31
  end
data/formtastic.gemspec CHANGED
@@ -21,18 +21,25 @@ Gem::Specification.new do |s|
21
21
  s.rdoc_options = ["--charset=UTF-8"]
22
22
  s.extra_rdoc_files = ["README.md"]
23
23
 
24
- s.required_ruby_version = '>= 2.6.0'
25
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
26
- s.rubygems_version = %q{1.3.6}
24
+ # Minimum Ruby version is probably the same as whatever the minimum Rails version currently expects.
25
+ s.required_ruby_version = '>= 3.1.0'
27
26
 
28
- s.add_dependency(%q<actionpack>, [">= 6.0.0"])
27
+ # Minimum Ruby Gems version also matches whatever the minimum Rails version currently expects.
28
+ s.required_rubygems_version = ">= 1.8.11"
29
29
 
30
- s.add_development_dependency(%q<rspec-rails>, [">= 4.0"])
31
- s.add_development_dependency(%q<rspec-dom-testing>, [">= 0.1.0"])
32
- s.add_development_dependency(%q<rspec-mocks>, ["~> 3.12.2"])
30
+ # User dependency is really just Rails, where we want describe the minimum version we support,
31
+ # which is probably the oldest version that hasn't reached end-of-life for security updates.
32
+ s.add_dependency(%q<actionpack>, [">= 7.2.0"])
33
33
 
34
- s.add_development_dependency(%q<yard>, ["~> 0.9.20"])
35
- s.add_development_dependency(%q<ammeter>, ["~> 1.1.3"])
34
+ # Development dependencies (for people working on Formtastic) are different to the minimum support
35
+ # version. Instead of specifying a specific version of each, we just specify the stack, and let the
36
+ # details of which versions work with each version of rails be managed in the Appraisal.
37
+ s.add_development_dependency(%q<appraisal>)
38
+ s.add_development_dependency(%q<rspec-rails>)
39
+ s.add_development_dependency(%q<rspec-dom-testing>)
40
+ s.add_development_dependency(%q<rspec-mocks>)
41
+ s.add_development_dependency(%q<yard>)
42
+ s.add_development_dependency(%q<ammeter>)
36
43
  s.add_development_dependency(%q<rake>)
37
- s.add_development_dependency(%q<sqlite3>, ["~> 1.4"])
44
+ s.add_development_dependency(%q<sqlite3>)
38
45
  end
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "actionpack", "~> 7.2.3"
6
+ gem "activesupport", "~> 7.2.3"
7
+ gem "activerecord", "~> 7.2.3"
8
+
9
+ gemspec path: "../"
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "actionpack", "~> 8.0.4"
6
+ gem "activesupport", "~> 8.0.4"
7
+ gem "activerecord", "~> 8.0.4"
8
+
9
+ gemspec path: "../"
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "actionpack", "~> 8.1.2"
6
+ gem "activesupport", "~> 8.1.2"
7
+ gem "activerecord", "~> 8.1.2"
8
+
9
+ gemspec path: "../"
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "actionpack", git: "https://github.com/rails/rails.git", branch: "main"
6
+ gem "activesupport", git: "https://github.com/rails/rails.git", branch: "main"
7
+ gem "activerecord", git: "https://github.com/rails/rails.git", branch: "main"
8
+
9
+ gemspec path: "../"
@@ -16,40 +16,40 @@ module Formtastic
16
16
  self.send(:"#{name}=", default)
17
17
  end
18
18
 
19
- configure :custom_namespace
20
- configure :default_text_field_size
21
- configure :default_text_area_height, 20
22
- configure :default_text_area_width
19
+ # Check {Formtastic::ActionClassFinder} to see how are inputs resolved.
20
+ configure :action_class_finder, Formtastic::ActionClassFinder
21
+ configure :action_namespaces, [::Object, ::Formtastic::Actions]
23
22
  configure :all_fields_required_by_default, true
24
- configure :include_blank_for_select_by_default, true
25
- configure :required_string, proc { %{<abbr title="#{Formtastic::I18n.t(:required)}">*</abbr>}.html_safe }
26
- configure :optional_string, ''
27
- configure :inline_errors, :sentence
28
- configure :label_str_method, :humanize
29
23
  configure :collection_label_methods, %w[to_label display_name full_name name title username login value to_s]
30
24
  configure :collection_value_methods, %w[id to_s]
31
- configure :file_methods, [ :file?, :public_filename, :filename ]
32
- configure :file_metadata_suffixes, ['content_type', 'file_name', 'file_size']
33
- configure :priority_countries, ["Australia", "Canada", "United Kingdom", "United States"]
34
- configure :i18n_lookups_by_default, true
35
- configure :i18n_cache_lookups, true
36
- configure :i18n_localizer, Formtastic::Localizer
37
- configure :escape_html_entities_in_hints_and_labels, true
25
+ configure :custom_namespace
38
26
  configure :default_commit_button_accesskey
39
- configure :default_inline_error_class, 'inline-errors'
40
27
  configure :default_error_list_class, 'errors'
41
28
  configure :default_hint_class, 'inline-hints'
42
- configure :use_required_attribute, false
43
- configure :perform_browser_validations, false
29
+ configure :default_inline_error_class, 'inline-errors'
30
+ configure :default_text_area_height, 20
31
+ configure :default_text_area_width
32
+ configure :default_text_field_size
33
+ configure :escape_html_entities_in_hints_and_labels, true
34
+ configure :file_metadata_suffixes, ['content_type', 'file_name', 'file_size']
35
+ configure :file_methods, [ :file?, :public_filename, :filename ]
36
+ configure :i18n_cache_lookups, true
37
+ configure :i18n_localizer, Formtastic::Localizer
38
+ configure :i18n_lookups_by_default, true
39
+ configure :include_blank_for_select_by_default, true
40
+ configure :inline_errors, :sentence
44
41
  # Check {Formtastic::InputClassFinder} to see how are inputs resolved.
45
- configure :input_namespaces, [::Object, ::Formtastic::Inputs]
46
42
  configure :input_class_finder, Formtastic::InputClassFinder
47
- # Check {Formtastic::ActionClassFinder} to see how are inputs resolved.
48
- configure :action_namespaces, [::Object, ::Formtastic::Actions]
49
- configure :action_class_finder, Formtastic::ActionClassFinder
50
-
51
- configure :skipped_columns, [:created_at, :updated_at, :created_on, :updated_on, :lock_version, :version]
43
+ configure :input_namespaces, [::Object, ::Formtastic::Inputs]
44
+ configure :label_str_method, :humanize
45
+ configure :optional_string, ''
46
+ configure :perform_browser_validations, false
47
+ configure :priority_countries, ["Australia", "Canada", "United Kingdom", "United States"]
52
48
  configure :priority_time_zones, []
49
+ configure :required_string, proc { %{<abbr title="#{Formtastic::I18n.t(:required)}">*</abbr>}.html_safe }
50
+ configure :semantic_errors_link_to_inputs, false
51
+ configure :skipped_columns, [:created_at, :updated_at, :created_on, :updated_on, :lock_version, :version]
52
+ configure :use_required_attribute, false
53
53
 
54
54
  attr_reader :template
55
55
 
@@ -1,4 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
1
  # frozen_string_literal: true
3
2
  module Formtastic
4
3
  module Helpers
@@ -16,6 +16,10 @@ module Formtastic
16
16
  # A hash can be used as the last set of arguments to pass HTML attributes to the `<ul>`
17
17
  # wrapper.
18
18
  #
19
+ # # in config/initializers/formtastic.rb
20
+ # Setting `Formtastic::FormBuilder.semantic_errors_link_to_inputs = true`
21
+ # will render attribute errors as links to the corresponding errored inputs.
22
+ #
19
23
  # @example A list of errors on the base model
20
24
  # <%= semantic_form_for ... %>
21
25
  # <%= f.semantic_errors %>
@@ -41,24 +45,37 @@ module Formtastic
41
45
  # <% end %>
42
46
  def semantic_errors(*args)
43
47
  html_options = args.extract_options!
44
- args = args - [:base]
45
- full_errors = args.inject([]) do |array, method|
46
- attribute = localized_string(method, method.to_sym, :label) || humanized_attribute_name(method)
47
- errors = Array(@object.errors[method.to_sym]).to_sentence
48
- errors.present? ? array << [attribute, errors].join(" ") : array ||= []
49
- end
50
- full_errors << @object.errors[:base]
51
- full_errors.flatten!
52
- full_errors.compact!
53
- return nil if full_errors.blank?
54
48
  html_options[:class] ||= "errors"
55
- template.content_tag(:ul, html_options) do
56
- full_errors.map { |error| template.content_tag(:li, error) }.join.html_safe
49
+
50
+ if Formtastic::FormBuilder.semantic_errors_link_to_inputs
51
+ attribute_error_hash = semantic_error_hash_from_attributes(args)
52
+ return nil if @object.errors[:base].blank? && attribute_error_hash.blank?
53
+
54
+ template.content_tag(:ul, html_options) do
55
+ (
56
+ @object.errors[:base].map { |base_error| template.content_tag(:li, base_error) } <<
57
+ attribute_error_hash.map { |attribute, error_message|
58
+ template.content_tag(:li) do
59
+ template.content_tag(:a, href: "##{object_name}_#{attribute}") do
60
+ error_message
61
+ end
62
+ end
63
+ }
64
+ ).join.html_safe
65
+ end
66
+ else
67
+ full_errors = @object.errors[:base]
68
+ full_errors += semantic_error_list_from_attributes(args)
69
+ return nil if full_errors.blank?
70
+
71
+ template.content_tag(:ul, html_options) do
72
+ full_errors.map { |error| template.content_tag(:li, error) }.join.html_safe
73
+ end
57
74
  end
58
75
  end
59
-
76
+
60
77
  protected
61
-
78
+
62
79
  def error_keys(method, options)
63
80
  @methods_for_error ||= {}
64
81
  @methods_for_error[method] ||= begin
@@ -77,6 +94,46 @@ module Formtastic
77
94
  def render_inline_errors?
78
95
  @object && @object.respond_to?(:errors) && Formtastic::FormBuilder::INLINE_ERROR_TYPES.include?(inline_errors)
79
96
  end
97
+
98
+ def semantic_error_list_from_attributes(*args)
99
+ attribute_errors = []
100
+ args = args.flatten
101
+ args.each do |attribute|
102
+ next if attribute == :base
103
+
104
+ full_message = error_message_for_attribute(attribute)
105
+
106
+ attribute_errors << full_message unless full_message.blank?
107
+ end
108
+
109
+ attribute_errors
110
+ end
111
+
112
+ # returns { 'attribute': 'error_message_for_attribute' }
113
+ def semantic_error_hash_from_attributes(*args)
114
+ attribute_error_hash = {}
115
+ args = args.flatten
116
+ args.each do |attribute|
117
+ next if attribute == :base
118
+
119
+ full_message = error_message_for_attribute(attribute)
120
+
121
+ attribute_error_hash[attribute] = full_message unless full_message.blank?
122
+ end
123
+
124
+ attribute_error_hash
125
+ end
126
+
127
+ # Returns "Attribute error_message_sentence" localized, humanized
128
+ def error_message_for_attribute(attribute)
129
+ attribute_string = localized_string(attribute, attribute.to_sym, :label) || humanized_attribute_name(attribute)
130
+ error_message = @object.errors[attribute.to_sym]&.to_sentence
131
+
132
+ return nil if error_message.blank?
133
+
134
+ full_message = [attribute_string, error_message].join(" ")
135
+ full_message
136
+ end
80
137
  end
81
138
  end
82
139
  end
@@ -1,4 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
1
  # frozen_string_literal: true
3
2
  module Formtastic
4
3
  module Helpers
@@ -177,6 +176,9 @@ module Formtastic
177
176
  # @example Changing or adding to HTML attributes in the main `<input>` or `<select>` tag
178
177
  # <%= f.input :title, :input_html => { :onchange => "somethingAwesome();", :class => 'awesome' } %>
179
178
  #
179
+ # @example Changing or adding to HTML attributes in the main `<label>` tag
180
+ # <%= f.input :title, :label_html => { :data => { :tooltip => 'Great Tooltip' } } %>
181
+ #
180
182
  # @example Changing or adding to HTML attributes in the wrapper `<li>` tag
181
183
  # <%= f.input :title, :wrapper_html => { :class => "important-input" } %>
182
184
  #
@@ -278,7 +280,7 @@ module Formtastic
278
280
  return :number
279
281
  when :float, :decimal
280
282
  return :number
281
- when :datetime, :timestamp
283
+ when :datetime, :timestamp, :timestamptz
282
284
  return :datetime_select
283
285
  when :time
284
286
  return :time_select
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  module Formtastic