bootstrap_form 5.3.2 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.devcontainer.json +38 -0
- data/.github/workflows/ruby.yml +11 -4
- data/.gitignore +27 -8
- data/.rubocop.yml +5 -6
- data/.yarnrc +1 -1
- data/CHANGELOG.md +5 -0
- data/CONTRIBUTING.md +34 -82
- data/DOCKER.md +95 -0
- data/Gemfile +5 -1
- data/README.md +143 -80
- data/RELEASING.md +3 -8
- data/Rakefile +23 -0
- data/bootstrap_form.gemspec +1 -1
- data/compose.yml +36 -0
- data/gemfiles/7.2.gemfile +9 -0
- data/gemfiles/8.0.gemfile +9 -0
- data/gemfiles/8.1.gemfile +9 -0
- data/gemfiles/common.gemfile +1 -2
- data/gemfiles/edge.gemfile +5 -1
- data/lib/bootstrap_form/action_view_extensions/form_helper.rb +6 -6
- data/lib/bootstrap_form/components/labels.rb +4 -3
- data/lib/bootstrap_form/components/validation.rb +1 -2
- data/lib/bootstrap_form/form_builder.rb +16 -8
- data/lib/bootstrap_form/form_group.rb +3 -3
- data/lib/bootstrap_form/form_group_builder.rb +3 -3
- data/lib/bootstrap_form/helpers/bootstrap.rb +15 -12
- data/lib/bootstrap_form/inputs/base.rb +15 -6
- data/lib/bootstrap_form/inputs/check_box.rb +11 -5
- data/lib/bootstrap_form/inputs/collection_check_boxes.rb +2 -8
- data/lib/bootstrap_form/inputs/file_field.rb +1 -1
- data/lib/bootstrap_form/inputs/range_field.rb +1 -1
- data/lib/bootstrap_form/inputs/rich_text_area.rb +3 -1
- data/lib/bootstrap_form/inputs/submit.rb +1 -1
- data/lib/bootstrap_form/inputs/text_area.rb +2 -0
- data/lib/bootstrap_form/version.rb +2 -2
- data/lib/bootstrap_form.rb +0 -6
- metadata +14 -12
- data/Dockerfile +0 -21
- data/docker-compose.yml +0 -31
- data/gemfiles/6.1.gemfile +0 -4
- data/gemfiles/7.0.gemfile +0 -5
data/RELEASING.md
CHANGED
|
@@ -14,20 +14,15 @@ Follow these steps to release a new version of bootstrap_form to rubygems.org.
|
|
|
14
14
|
2. Update the version in `./lib/bootstrap_form/version.rb`.
|
|
15
15
|
3. Make sure that you have all the gems necessary for testing and releasing.
|
|
16
16
|
|
|
17
|
-
BUNDLE_GEMFILE=gemfiles/7.
|
|
17
|
+
BUNDLE_GEMFILE=gemfiles/7.2.gemfile bundle update
|
|
18
18
|
|
|
19
19
|
4. **Ensure the tests are passing by running the tests**
|
|
20
20
|
|
|
21
21
|
(There should be no errors or warnings.)
|
|
22
22
|
|
|
23
|
-
BUNDLE_GEMFILE=gemfiles/7.0.gemfile bundle exec rake test
|
|
24
|
-
|
|
25
|
-
5. **Ensure the demo tests are passing by running**
|
|
26
|
-
|
|
27
|
-
cd demo
|
|
28
|
-
bundle update
|
|
29
23
|
bundle exec rake test:all
|
|
30
|
-
|
|
24
|
+
|
|
25
|
+
You will have failures in the system tests unless you're running on Linux. Chrome on each operating system renders slightly differently.
|
|
31
26
|
|
|
32
27
|
6. Update the GitHub diff links at the beginning of `CHANGELOG.md` (The pattern should be obvious when you look at them).
|
|
33
28
|
7. Update the installation instructions in `README.md` to use the new version.
|
data/Rakefile
CHANGED
|
@@ -28,3 +28,26 @@ desc 'Run RuboCop checks'
|
|
|
28
28
|
RuboCop::RakeTask.new(:rubocop)
|
|
29
29
|
|
|
30
30
|
task default: %i[test rubocop:autocorrect]
|
|
31
|
+
|
|
32
|
+
namespace :test do
|
|
33
|
+
desc "Run tests for all supported Rails versions, with current Ruby version"
|
|
34
|
+
task :all do
|
|
35
|
+
original_gemfile = ENV["BUNDLE_GEMFILE"]
|
|
36
|
+
gemfiles = Dir.glob("gemfiles/*.gemfile").reject { |f| File.basename(f) == "common.gemfile" }
|
|
37
|
+
gemfiles.each do |f|
|
|
38
|
+
ENV["BUNDLE_GEMFILE"] = f
|
|
39
|
+
system("bundle check") || system("bundle install")
|
|
40
|
+
system("bundle exec rake test")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
original_directory = Dir.pwd
|
|
44
|
+
Dir.chdir("demo")
|
|
45
|
+
ENV.delete("BUNDLE_GEMFILE")
|
|
46
|
+
system("bundle check") || system("bundle install")
|
|
47
|
+
system("bundle exec rake test:all")
|
|
48
|
+
|
|
49
|
+
ensure
|
|
50
|
+
original_gemfile.nil? ? ENV.delete("BUNDLE_GEMFILE") : ENV["BUNDLE_GEMFILE"] = original_gemfile
|
|
51
|
+
Dir.chdir(original_directory) unless original_directory.nil?
|
|
52
|
+
end
|
|
53
|
+
end
|
data/bootstrap_form.gemspec
CHANGED
|
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
|
|
|
23
23
|
s.bindir = "exe"
|
|
24
24
|
s.require_paths = ["lib"]
|
|
25
25
|
|
|
26
|
-
s.required_ruby_version = ">= 3.
|
|
26
|
+
s.required_ruby_version = ">= 3.2"
|
|
27
27
|
|
|
28
28
|
s.add_dependency("actionpack", BootstrapForm::REQUIRED_RAILS_VERSION)
|
|
29
29
|
s.add_dependency("activemodel", BootstrapForm::REQUIRED_RAILS_VERSION)
|
data/compose.yml
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Set up the Selenium container based on the Selenium official:
|
|
2
|
+
# https://github.com/SeleniumHQ/docker-selenium/blob/trunk/docker-compose-v3.yml
|
|
3
|
+
# And:
|
|
4
|
+
# https://medium.com/@retrorubies/chrome-as-a-service-for-rails-testing-b1a45e70fec1
|
|
5
|
+
services:
|
|
6
|
+
web:
|
|
7
|
+
image: lenchoreyes/jade:rails-app-${RUBY_VERSION:-3.3}-sqlite-${DISTRO:-bookworm}
|
|
8
|
+
stdin_open: true
|
|
9
|
+
tty: true
|
|
10
|
+
volumes:
|
|
11
|
+
- .:/app:cached
|
|
12
|
+
environment:
|
|
13
|
+
- HISTFILE=/app/.bash_history
|
|
14
|
+
- SELENIUM_HOST=selenium
|
|
15
|
+
- SELENIUM_PORT=4444
|
|
16
|
+
- TEST_APP_HOST=web
|
|
17
|
+
- TEST_APP_PORT=3001
|
|
18
|
+
ports:
|
|
19
|
+
- "3000"
|
|
20
|
+
- "3001"
|
|
21
|
+
command: /bin/bash
|
|
22
|
+
|
|
23
|
+
selenium:
|
|
24
|
+
image: selenium/standalone-chrome:133.0
|
|
25
|
+
shm_size: 2gb
|
|
26
|
+
logging:
|
|
27
|
+
driver: none
|
|
28
|
+
stdin_open: true
|
|
29
|
+
tty: true
|
|
30
|
+
environment:
|
|
31
|
+
- LANG=en_CA.UTF-8
|
|
32
|
+
- LANGUAGE=en_CA.UTF-8
|
|
33
|
+
- LANG_WHERE=CA
|
|
34
|
+
- LANG_WHICH=en
|
|
35
|
+
ports:
|
|
36
|
+
- "7900"
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
gems = "#{__dir__}/common.gemfile"
|
|
2
|
+
eval File.read(gems), binding, gems # rubocop: disable Security/Eval
|
|
3
|
+
|
|
4
|
+
gem "bigdecimal" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.4.0")
|
|
5
|
+
gem "drb" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.4.0")
|
|
6
|
+
gem "mutex_m" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.4.0")
|
|
7
|
+
gem "rails", "~> 7.2.0"
|
|
8
|
+
gem "sprockets-rails", require: "sprockets/railtie"
|
|
9
|
+
gem "sqlite3"
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
gems = "#{__dir__}/common.gemfile"
|
|
2
|
+
eval File.read(gems), binding, gems # rubocop: disable Security/Eval
|
|
3
|
+
|
|
4
|
+
gem "bigdecimal" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.4.0")
|
|
5
|
+
gem "drb" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.4.0")
|
|
6
|
+
gem "mutex_m" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.4.0")
|
|
7
|
+
gem "propshaft"
|
|
8
|
+
gem "rails", "~> 8.0.1"
|
|
9
|
+
gem "sqlite3"
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
gems = "#{__dir__}/common.gemfile"
|
|
2
|
+
eval File.read(gems), binding, gems # rubocop: disable Security/Eval
|
|
3
|
+
|
|
4
|
+
gem "bigdecimal" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.4.0")
|
|
5
|
+
gem "drb" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.4.0")
|
|
6
|
+
gem "mutex_m" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.4.0")
|
|
7
|
+
gem "propshaft"
|
|
8
|
+
gem "rails", "~> 8.1.0"
|
|
9
|
+
gem "sqlite3"
|
data/gemfiles/common.gemfile
CHANGED
|
@@ -15,12 +15,11 @@ group :test do
|
|
|
15
15
|
gem "diffy"
|
|
16
16
|
gem "equivalent-xml"
|
|
17
17
|
gem "mocha"
|
|
18
|
-
gem "sqlite3"
|
|
19
18
|
end
|
|
20
19
|
|
|
21
20
|
group :development, :test do
|
|
22
21
|
gem "debug"
|
|
23
|
-
gem "
|
|
22
|
+
gem "ostruct" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.5.0")
|
|
24
23
|
end
|
|
25
24
|
|
|
26
25
|
group :ci do
|
data/gemfiles/edge.gemfile
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
gems = "#{__dir__}/common.gemfile"
|
|
2
2
|
eval File.read(gems), binding, gems # rubocop: disable Security/Eval
|
|
3
3
|
|
|
4
|
+
gem "bigdecimal" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.4.0")
|
|
5
|
+
gem "drb" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.4.0")
|
|
6
|
+
gem "mutex_m" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.4.0")
|
|
7
|
+
gem "propshaft"
|
|
4
8
|
gem "rails", git: "https://github.com/rails/rails.git", branch: "main"
|
|
5
|
-
gem "
|
|
9
|
+
gem "sqlite3"
|
|
@@ -33,20 +33,20 @@ module BootstrapForm
|
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
def bootstrap_form_tag(options={}, &
|
|
36
|
+
def bootstrap_form_tag(options={}, &)
|
|
37
37
|
options[:acts_like_form_tag] = true
|
|
38
38
|
|
|
39
|
-
bootstrap_form_for("", options, &
|
|
39
|
+
bootstrap_form_for("", options, &)
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
-
def bootstrap_fields_for(record_name, record_object=nil, options={}, &
|
|
42
|
+
def bootstrap_fields_for(record_name, record_object=nil, options={}, &)
|
|
43
43
|
options[:builder] = BootstrapForm::FormBuilder
|
|
44
|
-
fields_for(record_name, record_object, options, &
|
|
44
|
+
fields_for(record_name, record_object, options, &)
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
-
def bootstrap_fields(scope=nil, model: nil, **options, &
|
|
47
|
+
def bootstrap_fields(scope=nil, model: nil, **options, &)
|
|
48
48
|
options[:builder] = BootstrapForm::FormBuilder
|
|
49
|
-
fields(scope, model: model, **options, &
|
|
49
|
+
fields(scope, model: model, **options, &)
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
private
|
|
@@ -34,7 +34,7 @@ module BootstrapForm
|
|
|
34
34
|
|
|
35
35
|
def label_layout_classes(custom_label_col, group_layout)
|
|
36
36
|
if layout_horizontal?(group_layout)
|
|
37
|
-
["col-form-label",
|
|
37
|
+
["col-form-label", custom_label_col || label_col]
|
|
38
38
|
elsif layout_inline?(group_layout)
|
|
39
39
|
%w[form-label me-sm-2]
|
|
40
40
|
else
|
|
@@ -43,10 +43,11 @@ module BootstrapForm
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def label_text(name, options)
|
|
46
|
+
label = options[:text] || object&.class&.try(:human_attribute_name, name)&.html_safe # rubocop:disable Rails/OutputSafety, Style/SafeNavigationChainLength
|
|
46
47
|
if label_errors && error?(name)
|
|
47
|
-
(
|
|
48
|
+
(" ".html_safe + get_error_messages(name)).prepend(label)
|
|
48
49
|
else
|
|
49
|
-
|
|
50
|
+
label
|
|
50
51
|
end
|
|
51
52
|
end
|
|
52
53
|
end
|
|
@@ -71,7 +71,6 @@ module BootstrapForm
|
|
|
71
71
|
content_tag(help_tag, help_text, class: help_klass)
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
-
# rubocop:disable Metrics/AbcSize
|
|
75
74
|
def get_error_messages(name)
|
|
76
75
|
object.class.try(:reflections)&.each do |association_name, a|
|
|
77
76
|
next unless a.is_a?(ActiveRecord::Reflection::BelongsToReflection)
|
|
@@ -82,7 +81,7 @@ module BootstrapForm
|
|
|
82
81
|
end
|
|
83
82
|
end
|
|
84
83
|
|
|
85
|
-
object.errors[name]
|
|
84
|
+
safe_join(object.errors[name], ", ")
|
|
86
85
|
end
|
|
87
86
|
# rubocop:enable Metrics/AbcSize
|
|
88
87
|
end
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
# require 'bootstrap_form/aliasing'
|
|
2
2
|
|
|
3
3
|
module BootstrapForm
|
|
4
|
-
class FormBuilder < ActionView::Helpers::FormBuilder
|
|
4
|
+
class FormBuilder < ActionView::Helpers::FormBuilder # rubocop:disable Metrics/ClassLength
|
|
5
5
|
attr_reader :layout, :label_col, :control_col, :has_error, :inline_errors,
|
|
6
6
|
:label_errors, :acts_like_form_tag
|
|
7
7
|
|
|
8
|
+
class << self
|
|
9
|
+
def redefine_rich_text_area?
|
|
10
|
+
ActionView::Helpers::FormBuilder.instance_methods.any? { _1 == :rich_text_area }
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
8
14
|
include BootstrapForm::Helpers::Field
|
|
9
15
|
include BootstrapForm::Helpers::Bootstrap
|
|
10
16
|
|
|
@@ -32,7 +38,7 @@ module BootstrapForm
|
|
|
32
38
|
include BootstrapForm::Inputs::PhoneField
|
|
33
39
|
include BootstrapForm::Inputs::RadioButton
|
|
34
40
|
include BootstrapForm::Inputs::RangeField
|
|
35
|
-
include BootstrapForm::Inputs::RichTextArea
|
|
41
|
+
include BootstrapForm::Inputs::RichTextArea if redefine_rich_text_area?
|
|
36
42
|
include BootstrapForm::Inputs::SearchField
|
|
37
43
|
include BootstrapForm::Inputs::Select
|
|
38
44
|
include BootstrapForm::Inputs::Submit
|
|
@@ -45,6 +51,8 @@ module BootstrapForm
|
|
|
45
51
|
include BootstrapForm::Inputs::UrlField
|
|
46
52
|
include BootstrapForm::Inputs::WeekField
|
|
47
53
|
|
|
54
|
+
include ActionView::Helpers::OutputSafetyHelper
|
|
55
|
+
|
|
48
56
|
delegate :content_tag, :capture, :concat, :tag, to: :@template
|
|
49
57
|
|
|
50
58
|
def initialize(object_name, object, template, options)
|
|
@@ -66,14 +74,14 @@ module BootstrapForm
|
|
|
66
74
|
return unless options[:layout] == :inline
|
|
67
75
|
|
|
68
76
|
options[:html][:class] =
|
|
69
|
-
([*options[:html][:class]&.split(/\s+/)] + %w[row row-cols-auto g-3 align-items-center])
|
|
70
|
-
.compact.uniq
|
|
77
|
+
safe_join(([*options[:html][:class]&.split(/\s+/)] + %w[row row-cols-auto g-3 align-items-center])
|
|
78
|
+
.compact.uniq, " ")
|
|
71
79
|
end
|
|
72
80
|
|
|
73
|
-
def fields_for_with_bootstrap(record_name, record_object=nil, fields_options={}, &
|
|
81
|
+
def fields_for_with_bootstrap(record_name, record_object=nil, fields_options={}, &)
|
|
74
82
|
fields_options = fields_for_options(record_object, fields_options)
|
|
75
83
|
record_object = nil if record_object.is_a?(Hash) && record_object.extractable_options?
|
|
76
|
-
fields_for_without_bootstrap(record_name, record_object, fields_options, &
|
|
84
|
+
fields_for_without_bootstrap(record_name, record_object, fields_options, &)
|
|
77
85
|
end
|
|
78
86
|
|
|
79
87
|
bootstrap_alias :fields_for
|
|
@@ -88,9 +96,9 @@ module BootstrapForm
|
|
|
88
96
|
field_options = fields_options
|
|
89
97
|
field_options = record_object if record_object.is_a?(Hash) && record_object.extractable_options?
|
|
90
98
|
%i[layout control_col inline_errors label_errors].each do |option|
|
|
91
|
-
field_options[option]
|
|
99
|
+
field_options[option] = field_options.key?(option) ? field_options[option] : options[option]
|
|
92
100
|
end
|
|
93
|
-
field_options[:label_col] = field_options[:label_col].present? ?
|
|
101
|
+
field_options[:label_col] = field_options[:label_col].present? ? field_options[:label_col].to_s : options[:label_col]
|
|
94
102
|
field_options
|
|
95
103
|
end
|
|
96
104
|
|
|
@@ -29,15 +29,15 @@ module BootstrapForm
|
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
def form_group_content(label, help_text, options, &
|
|
32
|
+
def form_group_content(label, help_text, options, &)
|
|
33
33
|
label ||= ActiveSupport::SafeBuffer.new
|
|
34
34
|
if group_layout_horizontal?(options[:layout])
|
|
35
|
-
label + tag.div(capture(&
|
|
35
|
+
label + tag.div(capture(&) + help_text, class: form_group_control_class(options))
|
|
36
36
|
else
|
|
37
37
|
content = ActiveSupport::SafeBuffer.new
|
|
38
38
|
# Floating labels need to be rendered after the field
|
|
39
39
|
content << label unless options[:floating]
|
|
40
|
-
content << capture(&
|
|
40
|
+
content << capture(&)
|
|
41
41
|
content << label if options[:floating]
|
|
42
42
|
content << help_text if help_text
|
|
43
43
|
content
|
|
@@ -6,7 +6,7 @@ module BootstrapForm
|
|
|
6
6
|
|
|
7
7
|
private
|
|
8
8
|
|
|
9
|
-
def form_group_builder(method, options, html_options=nil, &
|
|
9
|
+
def form_group_builder(method, options, html_options=nil, &)
|
|
10
10
|
no_wrapper = options[:wrapper] == false
|
|
11
11
|
|
|
12
12
|
options = form_group_builder_options(options, method)
|
|
@@ -21,7 +21,7 @@ module BootstrapForm
|
|
|
21
21
|
if no_wrapper
|
|
22
22
|
yield
|
|
23
23
|
else
|
|
24
|
-
form_group(method, form_group_options, &
|
|
24
|
+
form_group(method, form_group_options, &)
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
|
|
@@ -91,7 +91,7 @@ module BootstrapForm
|
|
|
91
91
|
css_options = html_options || options
|
|
92
92
|
# Add control_class; allow it to be overridden by :control_class option
|
|
93
93
|
control_classes = css_options.delete(:control_class) { control_class }
|
|
94
|
-
css_options[:class] = [control_classes, css_options[:class]].compact
|
|
94
|
+
css_options[:class] = safe_join([control_classes, css_options[:class]].compact, " ")
|
|
95
95
|
css_options[:class] << " is-invalid" if error?(method)
|
|
96
96
|
css_options[:placeholder] = form_group_placeholder(options, method) if options[:label_as_placeholder]
|
|
97
97
|
css_options
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
module BootstrapForm
|
|
2
2
|
module Helpers
|
|
3
3
|
module Bootstrap
|
|
4
|
+
include ActionView::Helpers::OutputSafetyHelper
|
|
5
|
+
|
|
4
6
|
def alert_message(title, options={})
|
|
5
7
|
css = options[:class] || "alert alert-danger"
|
|
6
8
|
return unless object.respond_to?(:errors) && object.errors.full_messages.any?
|
|
@@ -31,11 +33,12 @@ module BootstrapForm
|
|
|
31
33
|
custom_class = options[:custom_class] || false
|
|
32
34
|
|
|
33
35
|
tag.div class: custom_class || "invalid-feedback" do
|
|
34
|
-
if hide_attribute_name
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
errors = if hide_attribute_name
|
|
37
|
+
object.errors[name]
|
|
38
|
+
else
|
|
39
|
+
object.errors.full_messages_for(name)
|
|
40
|
+
end
|
|
41
|
+
safe_join(errors, ", ")
|
|
39
42
|
end
|
|
40
43
|
end
|
|
41
44
|
|
|
@@ -53,17 +56,17 @@ module BootstrapForm
|
|
|
53
56
|
text_field_with_bootstrap(name, static_options)
|
|
54
57
|
end
|
|
55
58
|
|
|
56
|
-
def custom_control(*args, &
|
|
59
|
+
def custom_control(*args, &)
|
|
57
60
|
options = args.extract_options!
|
|
58
61
|
name = args.first
|
|
59
62
|
|
|
60
|
-
form_group_builder(name, options, &
|
|
63
|
+
form_group_builder(name, options, &)
|
|
61
64
|
end
|
|
62
65
|
|
|
63
|
-
def prepend_and_append_input(name, options, &
|
|
66
|
+
def prepend_and_append_input(name, options, &)
|
|
64
67
|
options = options.extract!(:prepend, :append, :input_group_class).compact
|
|
65
68
|
|
|
66
|
-
input = capture(&
|
|
69
|
+
input = capture(&) || ActiveSupport::SafeBuffer.new
|
|
67
70
|
|
|
68
71
|
input = attach_input(options, :prepend) + input + attach_input(options, :append)
|
|
69
72
|
input << generate_error(name)
|
|
@@ -72,8 +75,8 @@ module BootstrapForm
|
|
|
72
75
|
input
|
|
73
76
|
end
|
|
74
77
|
|
|
75
|
-
def input_with_error(name, &
|
|
76
|
-
input = capture(&
|
|
78
|
+
def input_with_error(name, &)
|
|
79
|
+
input = capture(&)
|
|
77
80
|
input << generate_error(name)
|
|
78
81
|
end
|
|
79
82
|
|
|
@@ -93,7 +96,7 @@ module BootstrapForm
|
|
|
93
96
|
tags = [*options[key]].map do |item|
|
|
94
97
|
input_group_content(item)
|
|
95
98
|
end
|
|
96
|
-
|
|
99
|
+
safe_join(tags)
|
|
97
100
|
end
|
|
98
101
|
end
|
|
99
102
|
end
|
|
@@ -6,13 +6,15 @@ module BootstrapForm
|
|
|
6
6
|
extend ActiveSupport::Concern
|
|
7
7
|
|
|
8
8
|
class_methods do
|
|
9
|
-
def bootstrap_field(field_name
|
|
10
|
-
define_method "#{field_name}_with_bootstrap" do |name, options={
|
|
9
|
+
def bootstrap_field(field_name)
|
|
10
|
+
define_method :"#{field_name}_with_bootstrap" do |name, options={}|
|
|
11
11
|
warn_deprecated_layout_value(options)
|
|
12
|
+
options = options.reverse_merge(control_class: "form-range") if field_name == :range_field
|
|
13
|
+
options = options.reverse_merge(control_class: "form-control form-control-color") if field_name == :color_field
|
|
12
14
|
form_group_builder(name, options) do
|
|
13
15
|
prepend_and_append_input(name, options) do
|
|
14
16
|
options[:placeholder] ||= name if options[:floating]
|
|
15
|
-
send("#{field_name}_without_bootstrap"
|
|
17
|
+
send(:"#{field_name}_without_bootstrap", name, options.except(:floating))
|
|
16
18
|
end
|
|
17
19
|
end
|
|
18
20
|
end
|
|
@@ -21,7 +23,7 @@ module BootstrapForm
|
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
def bootstrap_select_group(field_name)
|
|
24
|
-
define_method("#{field_name}_with_bootstrap") do |name, options={}, html_options={}|
|
|
26
|
+
define_method(:"#{field_name}_with_bootstrap") do |name, options={}, html_options={}|
|
|
25
27
|
html_options = html_options.reverse_merge(control_class: "form-select")
|
|
26
28
|
form_group_builder(name, options, html_options) do
|
|
27
29
|
form_group_content_tag(name, field_name, "#{field_name}_without_bootstrap", options, html_options)
|
|
@@ -31,9 +33,16 @@ module BootstrapForm
|
|
|
31
33
|
bootstrap_alias field_name
|
|
32
34
|
end
|
|
33
35
|
|
|
36
|
+
# Creates the methods *_without_bootstrap and *_with_bootstrap.
|
|
37
|
+
#
|
|
38
|
+
# If your application did not include the rails gem for one of the dsl
|
|
39
|
+
# methods, then a name error is raised and suppressed. This can happen
|
|
40
|
+
# if your application does not include the actiontext dependency due to
|
|
41
|
+
# `rich_text_area` not being defined.
|
|
34
42
|
def bootstrap_alias(field_name)
|
|
35
|
-
alias_method "#{field_name}_without_bootstrap"
|
|
36
|
-
alias_method field_name, "#{field_name}_with_bootstrap"
|
|
43
|
+
alias_method :"#{field_name}_without_bootstrap", field_name
|
|
44
|
+
alias_method field_name, :"#{field_name}_with_bootstrap"
|
|
45
|
+
rescue NameError # rubocop:disable Lint/SuppressedException
|
|
37
46
|
end
|
|
38
47
|
end
|
|
39
48
|
|
|
@@ -20,6 +20,8 @@ module BootstrapForm
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
bootstrap_alias :check_box
|
|
23
|
+
alias_method :checkbox_with_bootstrap, :check_box_with_bootstrap if Rails::VERSION::MAJOR >= 8
|
|
24
|
+
bootstrap_alias :checkbox if Rails::VERSION::MAJOR >= 8
|
|
23
25
|
end
|
|
24
26
|
|
|
25
27
|
private
|
|
@@ -42,7 +44,7 @@ module BootstrapForm
|
|
|
42
44
|
check_box_options.merge!(required_field_options(options, name))
|
|
43
45
|
end
|
|
44
46
|
|
|
45
|
-
def check_box_label(name, options, checked_value, &
|
|
47
|
+
def check_box_label(name, options, checked_value, &)
|
|
46
48
|
label_name = if options[:multiple]
|
|
47
49
|
check_box_value(name, checked_value)
|
|
48
50
|
else
|
|
@@ -50,19 +52,20 @@ module BootstrapForm
|
|
|
50
52
|
end
|
|
51
53
|
label_options = { class: check_box_label_class(options) }
|
|
52
54
|
label_options[:for] = options[:id] if options[:id].present?
|
|
53
|
-
label(label_name, check_box_description(name, options, &
|
|
55
|
+
label(label_name, check_box_description(name, options, &), label_options)
|
|
54
56
|
end
|
|
55
57
|
|
|
56
58
|
def check_box_description(name, options, &block)
|
|
57
59
|
content = block ? capture(&block) : options[:label]
|
|
58
|
-
|
|
60
|
+
# Ugh. Next Rails after 7.1 passes `false` when there's no object.
|
|
61
|
+
content || (object && object.class.human_attribute_name(name)) || name.to_s.humanize # rubocop:disable Style/SafeNavigation
|
|
59
62
|
end
|
|
60
63
|
|
|
61
64
|
def check_box_value(name, value)
|
|
62
65
|
# label's `for` attribute needs to match checkbox tag's id,
|
|
63
66
|
# IE sanitized value, IE
|
|
64
67
|
# https://github.com/rails/rails/blob/5-0-stable/actionview/lib/action_view/helpers/tags/base.rb#L123-L125
|
|
65
|
-
"#{name}_#{value.to_s.gsub(/\s/, '_').gsub(/[^-[[:word:]]]/, '').
|
|
68
|
+
"#{name}_#{value.to_s.gsub(/\s/, '_').gsub(/[^-[[:word:]]]/, '').downcase}"
|
|
66
69
|
end
|
|
67
70
|
|
|
68
71
|
def check_box_classes(name, options)
|
|
@@ -83,7 +86,10 @@ module BootstrapForm
|
|
|
83
86
|
def check_box_wrapper_class(options)
|
|
84
87
|
classes = ["form-check"]
|
|
85
88
|
classes << "form-check-inline" if layout_inline?(options[:inline])
|
|
86
|
-
classes << "mb-3" unless options[:multiple] ||
|
|
89
|
+
classes << "mb-3" unless options[:multiple] ||
|
|
90
|
+
%i[horizontal inline].include?(layout) ||
|
|
91
|
+
options[:wrapper_class] == false ||
|
|
92
|
+
options.dig(:wrapper, :class) == false
|
|
87
93
|
classes << "form-switch" if options[:switch]
|
|
88
94
|
classes << options.dig(:wrapper, :class).presence
|
|
89
95
|
classes << options[:wrapper_class].presence
|
|
@@ -21,14 +21,8 @@ module BootstrapForm
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
bootstrap_alias :collection_check_boxes
|
|
24
|
-
|
|
25
|
-
if Rails::VERSION::MAJOR
|
|
26
|
-
def field_name(method, *methods, multiple: false, index: @options[:index])
|
|
27
|
-
object_name = @options.fetch(:as) { @object_name }
|
|
28
|
-
|
|
29
|
-
@template.field_name(object_name, method, *methods, index: index, multiple: multiple)
|
|
30
|
-
end
|
|
31
|
-
end
|
|
24
|
+
alias_method :collection_checkboxes_with_bootstrap, :collection_check_boxes_with_bootstrap if Rails::VERSION::MAJOR >= 8
|
|
25
|
+
bootstrap_alias :collection_checkboxes if Rails::VERSION::MAJOR >= 8
|
|
32
26
|
end
|
|
33
27
|
end
|
|
34
28
|
end
|
|
@@ -10,7 +10,7 @@ module BootstrapForm
|
|
|
10
10
|
def file_field_with_bootstrap(name, options={})
|
|
11
11
|
options = options.reverse_merge(control_class: "form-control")
|
|
12
12
|
form_group_builder(name, options) do
|
|
13
|
-
|
|
13
|
+
prepend_and_append_input(name, options) do
|
|
14
14
|
file_field_without_bootstrap(name, options)
|
|
15
15
|
end
|
|
16
16
|
end
|
|
@@ -10,13 +10,15 @@ module BootstrapForm
|
|
|
10
10
|
def rich_text_area_with_bootstrap(name, options={})
|
|
11
11
|
form_group_builder(name, options) do
|
|
12
12
|
prepend_and_append_input(name, options) do
|
|
13
|
-
options[:class] = ["trix-content", options[:class]].compact
|
|
13
|
+
options[:class] = safe_join(["trix-content", options[:class]].compact, " ")
|
|
14
14
|
rich_text_area_without_bootstrap(name, options)
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
bootstrap_alias :rich_text_area
|
|
20
|
+
alias_method :rich_textarea, :rich_text_area if Rails::VERSION::MAJOR >= 8
|
|
21
|
+
bootstrap_alias :rich_textarea if Rails::VERSION::MAJOR >= 8
|
|
20
22
|
end
|
|
21
23
|
end
|
|
22
24
|
end
|
data/lib/bootstrap_form.rb
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
# NOTE: The rich_text_area and rich_text_area_tag helpers are defined in a file with a different
|
|
2
|
-
# name and not in the usual autoload-reachable way.
|
|
3
|
-
# The following line is definitely need to make `bootstrap_form` work.
|
|
4
|
-
if Rails::VERSION::STRING > "6"
|
|
5
|
-
require "#{Gem::Specification.find_by_name('actiontext').gem_dir}/app/helpers/action_text/tag_helper"
|
|
6
|
-
end
|
|
7
1
|
require "action_view"
|
|
8
2
|
require "action_pack"
|
|
9
3
|
require "bootstrap_form/action_view_extensions/form_helper"
|