bootstrap_form 4.1.0 → 4.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +18 -0
- data/.rubocop.yml +3 -2
- data/.travis.yml +7 -1
- data/CHANGELOG.md +15 -1
- data/CONTRIBUTING.md +11 -0
- data/Dangerfile +4 -4
- data/Gemfile +7 -2
- data/OLD-README.md +795 -0
- data/README.md +150 -93
- data/Rakefile +2 -4
- data/bootstrap_form.gemspec +2 -1
- data/demo/.postcssrc.yml +3 -0
- data/demo/app/assets/config/manifest.js +2 -0
- data/demo/app/assets/stylesheets/actiontext.scss +38 -0
- data/demo/app/assets/stylesheets/application.scss +1 -0
- data/demo/app/helpers/bootstrap_helper.rb +16 -10
- data/demo/app/javascript/channels/consumer.js +6 -0
- data/demo/app/javascript/channels/index.js +5 -0
- data/demo/app/javascript/packs/application.js +11 -0
- data/demo/app/models/user.rb +2 -0
- data/demo/app/views/active_storage/blobs/_blob.html.erb +14 -0
- data/demo/app/views/bootstrap/form.html.erb +2 -1
- data/demo/app/views/layouts/application.html.erb +3 -0
- data/demo/bin/webpack +15 -0
- data/demo/bin/webpack-dev-server +15 -0
- data/demo/config/application.rb +2 -3
- data/demo/config/environments/development.rb +3 -1
- data/demo/config/environments/production.rb +48 -0
- data/demo/config/webpack/development.js +5 -0
- data/demo/config/webpack/environment.js +3 -0
- data/demo/config/webpack/production.js +5 -0
- data/demo/config/webpack/test.js +5 -0
- data/demo/config/webpacker.yml +92 -0
- data/demo/db/schema.rb +63 -18
- data/demo/package.json +13 -1
- data/demo/test/fixtures/action_text/rich_texts.yml +4 -0
- data/demo/yarn.lock +6257 -0
- data/lib/bootstrap_form.rb +34 -8
- data/lib/bootstrap_form/action_view_extensions/form_helper.rb +71 -0
- data/lib/bootstrap_form/components.rb +17 -0
- data/lib/bootstrap_form/components/hints.rb +60 -0
- data/lib/bootstrap_form/components/labels.rb +56 -0
- data/lib/bootstrap_form/components/layout.rb +39 -0
- data/lib/bootstrap_form/components/validation.rb +61 -0
- data/lib/bootstrap_form/engine.rb +10 -0
- data/lib/bootstrap_form/form_builder.rb +54 -524
- data/lib/bootstrap_form/form_group.rb +64 -0
- data/lib/bootstrap_form/form_group_builder.rb +103 -0
- data/lib/bootstrap_form/helpers.rb +9 -0
- data/lib/bootstrap_form/helpers/bootstrap.rb +39 -31
- data/lib/bootstrap_form/inputs.rb +40 -0
- data/lib/bootstrap_form/inputs/base.rb +40 -0
- data/lib/bootstrap_form/inputs/check_box.rb +89 -0
- data/lib/bootstrap_form/inputs/collection_check_boxes.rb +23 -0
- data/lib/bootstrap_form/inputs/collection_radio_buttons.rb +21 -0
- data/lib/bootstrap_form/inputs/collection_select.rb +25 -0
- data/lib/bootstrap_form/inputs/color_field.rb +14 -0
- data/lib/bootstrap_form/inputs/date_field.rb +14 -0
- data/lib/bootstrap_form/inputs/date_select.rb +14 -0
- data/lib/bootstrap_form/inputs/datetime_field.rb +14 -0
- data/lib/bootstrap_form/inputs/datetime_local_field.rb +14 -0
- data/lib/bootstrap_form/inputs/datetime_select.rb +14 -0
- data/lib/bootstrap_form/inputs/email_field.rb +14 -0
- data/lib/bootstrap_form/inputs/file_field.rb +35 -0
- data/lib/bootstrap_form/inputs/grouped_collection_select.rb +29 -0
- data/lib/bootstrap_form/inputs/inputs_collection.rb +44 -0
- data/lib/bootstrap_form/inputs/month_field.rb +14 -0
- data/lib/bootstrap_form/inputs/number_field.rb +14 -0
- data/lib/bootstrap_form/inputs/password_field.rb +14 -0
- data/lib/bootstrap_form/inputs/phone_field.rb +14 -0
- data/lib/bootstrap_form/inputs/radio_button.rb +77 -0
- data/lib/bootstrap_form/inputs/range_field.rb +14 -0
- data/lib/bootstrap_form/inputs/rich_text_area.rb +23 -0
- data/lib/bootstrap_form/inputs/search_field.rb +14 -0
- data/lib/bootstrap_form/inputs/select.rb +22 -0
- data/lib/bootstrap_form/inputs/telephone_field.rb +14 -0
- data/lib/bootstrap_form/inputs/text_area.rb +14 -0
- data/lib/bootstrap_form/inputs/text_field.rb +14 -0
- data/lib/bootstrap_form/inputs/time_field.rb +14 -0
- data/lib/bootstrap_form/inputs/time_select.rb +14 -0
- data/lib/bootstrap_form/inputs/time_zone_select.rb +22 -0
- data/lib/bootstrap_form/inputs/url_field.rb +14 -0
- data/lib/bootstrap_form/inputs/week_field.rb +14 -0
- data/lib/bootstrap_form/version.rb +1 -1
- metadata +79 -6
- data/.rubocop_todo.yml +0 -104
- data/lib/bootstrap_form/aliasing.rb +0 -35
- data/lib/bootstrap_form/helper.rb +0 -52
data/lib/bootstrap_form.rb
CHANGED
@@ -1,13 +1,39 @@
|
|
1
|
-
|
2
|
-
|
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 + # rubocop:disable Rails/DynamicFindBy
|
6
|
+
"/app/helpers/action_text/tag_helper"
|
7
|
+
end
|
8
|
+
require "action_view"
|
9
|
+
require "action_pack"
|
10
|
+
require "bootstrap_form/action_view_extensions/form_helper"
|
3
11
|
|
4
12
|
module BootstrapForm
|
5
|
-
|
6
|
-
|
7
|
-
|
13
|
+
extend ActiveSupport::Autoload
|
14
|
+
|
15
|
+
eager_autoload do
|
16
|
+
autoload :FormBuilder
|
17
|
+
autoload :FormGroupBuilder
|
18
|
+
autoload :FormGroup
|
19
|
+
autoload :Components
|
20
|
+
autoload :Inputs
|
21
|
+
autoload :Helpers
|
8
22
|
end
|
9
|
-
end
|
10
23
|
|
11
|
-
|
12
|
-
|
24
|
+
def self.eager_load!
|
25
|
+
super
|
26
|
+
BootstrapForm::Components.eager_load!
|
27
|
+
BootstrapForm::Helpers.eager_load!
|
28
|
+
BootstrapForm::Inputs.eager_load!
|
29
|
+
end
|
30
|
+
|
31
|
+
mattr_accessor :field_error_proc
|
32
|
+
# rubocop:disable Style/ClassVars
|
33
|
+
@@field_error_proc = proc do |html_tag, _instance_tag|
|
34
|
+
html_tag
|
35
|
+
end
|
36
|
+
# rubocop:enable Style/ClassVars
|
13
37
|
end
|
38
|
+
|
39
|
+
require "bootstrap_form/engine" if defined?(Rails)
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BootstrapForm
|
4
|
+
module ActionViewExtensions
|
5
|
+
# This module creates BootstrapForm wrappers around the default form_with
|
6
|
+
# and form_for methods
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
#
|
10
|
+
# bootstrap_form_for @user do |f|
|
11
|
+
# f.text_field :name
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# Example:
|
15
|
+
#
|
16
|
+
# bootstrap_form_with model: @user do |f|
|
17
|
+
# f.text_field :name
|
18
|
+
# end
|
19
|
+
module FormHelper
|
20
|
+
def bootstrap_form_for(record, options={}, &block)
|
21
|
+
options.reverse_merge!(builder: BootstrapForm::FormBuilder)
|
22
|
+
|
23
|
+
options = process_options(options)
|
24
|
+
|
25
|
+
with_bootstrap_form_field_error_proc do
|
26
|
+
form_for(record, options, &block)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def bootstrap_form_with(options={}, &block)
|
31
|
+
options.reverse_merge!(builder: BootstrapForm::FormBuilder)
|
32
|
+
|
33
|
+
options = process_options(options)
|
34
|
+
|
35
|
+
with_bootstrap_form_field_error_proc do
|
36
|
+
form_with(options, &block)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def bootstrap_form_tag(options={}, &block)
|
41
|
+
options[:acts_like_form_tag] = true
|
42
|
+
|
43
|
+
bootstrap_form_for("", options, &block)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def process_options(options)
|
49
|
+
options[:html] ||= {}
|
50
|
+
options[:html][:role] ||= "form"
|
51
|
+
|
52
|
+
options[:layout] == :inline &&
|
53
|
+
options[:html][:class] = [options[:html][:class], "form-inline"].compact.join(" ")
|
54
|
+
|
55
|
+
options
|
56
|
+
end
|
57
|
+
|
58
|
+
def with_bootstrap_form_field_error_proc
|
59
|
+
original_proc = ActionView::Base.field_error_proc
|
60
|
+
ActionView::Base.field_error_proc = BootstrapForm.field_error_proc
|
61
|
+
yield
|
62
|
+
ensure
|
63
|
+
ActionView::Base.field_error_proc = original_proc
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
ActiveSupport.on_load(:action_view) do
|
70
|
+
include BootstrapForm::ActionViewExtensions::FormHelper
|
71
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BootstrapForm
|
4
|
+
module Components
|
5
|
+
extend ActiveSupport::Autoload
|
6
|
+
|
7
|
+
autoload :Hints
|
8
|
+
autoload :Labels
|
9
|
+
autoload :Layout
|
10
|
+
autoload :Validation
|
11
|
+
|
12
|
+
include Hints
|
13
|
+
include Labels
|
14
|
+
include Layout
|
15
|
+
include Validation
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BootstrapForm
|
4
|
+
module Components
|
5
|
+
module Hints
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def generate_help(name, help_text)
|
11
|
+
return if help_text == false || inline_error?(name)
|
12
|
+
|
13
|
+
help_klass ||= "form-text text-muted"
|
14
|
+
help_text ||= get_help_text_by_i18n_key(name)
|
15
|
+
help_tag ||= :small
|
16
|
+
|
17
|
+
content_tag(help_tag, help_text, class: help_klass) if help_text.present?
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_help_text_by_i18n_key(name)
|
21
|
+
return unless object
|
22
|
+
|
23
|
+
partial_scope = if object.class.respond_to?(:model_name)
|
24
|
+
object.class.model_name.name
|
25
|
+
else
|
26
|
+
object.class.name
|
27
|
+
end
|
28
|
+
|
29
|
+
# First check for a subkey :html, as it is also accepted by i18n, and the
|
30
|
+
# simple check for name would return an hash instead of a string (both
|
31
|
+
# with .presence returning true!)
|
32
|
+
help_text = nil
|
33
|
+
["#{name}.html", name, "#{name}_html"].each do |scope|
|
34
|
+
break if help_text
|
35
|
+
|
36
|
+
help_text = scoped_help_text(scope, partial_scope)
|
37
|
+
end
|
38
|
+
help_text
|
39
|
+
end
|
40
|
+
|
41
|
+
def scoped_help_text(name, partial_scope)
|
42
|
+
underscored_scope = "activerecord.help.#{partial_scope.underscore}"
|
43
|
+
downcased_scope = "activerecord.help.#{partial_scope.downcase}"
|
44
|
+
|
45
|
+
help_text = translated_help_text(name, underscored_scope).presence
|
46
|
+
|
47
|
+
help_text ||= if (text = translated_help_text(name, downcased_scope).presence)
|
48
|
+
warn "I18n key '#{downcased_scope}.#{name}' is deprecated, use '#{underscored_scope}.#{name}' instead"
|
49
|
+
text
|
50
|
+
end
|
51
|
+
|
52
|
+
help_text
|
53
|
+
end
|
54
|
+
|
55
|
+
def translated_help_text(name, scope)
|
56
|
+
ActiveSupport::SafeBuffer.new I18n.t(name, scope: scope, default: "")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BootstrapForm
|
4
|
+
module Components
|
5
|
+
module Labels
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def generate_label(id, name, options, custom_label_col, group_layout)
|
11
|
+
return if options.blank?
|
12
|
+
|
13
|
+
# id is the caller's options[:id] at the only place this method is called.
|
14
|
+
# The options argument is a small subset of the options that might have
|
15
|
+
# been passed to generate_label's caller, and definitely doesn't include
|
16
|
+
# :id.
|
17
|
+
options[:for] = id if acts_like_form_tag
|
18
|
+
|
19
|
+
options[:class] = label_classes(name, options, custom_label_col, group_layout)
|
20
|
+
options.delete(:class) if options[:class].none?
|
21
|
+
|
22
|
+
label(name, label_text(name, options), options.except(:text))
|
23
|
+
end
|
24
|
+
|
25
|
+
def label_classes(name, options, custom_label_col, group_layout)
|
26
|
+
classes = [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
|
+
|
35
|
+
classes << "text-danger" if label_errors && error?(name)
|
36
|
+
classes.flatten.compact
|
37
|
+
end
|
38
|
+
|
39
|
+
def label_layout_classes(custom_label_col, group_layout)
|
40
|
+
if layout_horizontal?(group_layout)
|
41
|
+
["col-form-label", (custom_label_col || label_col)]
|
42
|
+
elsif layout_inline?(group_layout)
|
43
|
+
["mr-sm-2"]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def label_text(name, options)
|
48
|
+
if label_errors && error?(name)
|
49
|
+
(options[:text] || object.class.human_attribute_name(name)).to_s.concat(" #{get_error_messages(name)}")
|
50
|
+
else
|
51
|
+
options[:text]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BootstrapForm
|
4
|
+
module Components
|
5
|
+
module Layout
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def layout_default?(field_layout=nil)
|
11
|
+
[:default, nil].include? layout_in_effect(field_layout)
|
12
|
+
end
|
13
|
+
|
14
|
+
def layout_horizontal?(field_layout=nil)
|
15
|
+
layout_in_effect(field_layout) == :horizontal
|
16
|
+
end
|
17
|
+
|
18
|
+
def layout_inline?(field_layout=nil)
|
19
|
+
layout_in_effect(field_layout) == :inline
|
20
|
+
end
|
21
|
+
|
22
|
+
def field_inline_override?(field_layout=nil)
|
23
|
+
field_layout == :inline && layout != :inline
|
24
|
+
end
|
25
|
+
|
26
|
+
# true and false should only come from check_box and radio_button,
|
27
|
+
# and those don't have a :horizontal layout
|
28
|
+
def layout_in_effect(field_layout)
|
29
|
+
field_layout = :inline if field_layout == true
|
30
|
+
field_layout = :default if field_layout == false
|
31
|
+
field_layout || layout
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_group_layout(group_layout)
|
35
|
+
group_layout || layout
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BootstrapForm
|
4
|
+
module Components
|
5
|
+
module Validation
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def error?(name)
|
11
|
+
object.respond_to?(:errors) && !(name.nil? || object.errors[name].empty?)
|
12
|
+
end
|
13
|
+
|
14
|
+
def required_attribute?(obj, attribute)
|
15
|
+
return false unless obj && attribute
|
16
|
+
|
17
|
+
target = obj.class == Class ? obj : obj.class
|
18
|
+
|
19
|
+
target_validators = if target.respond_to? :validators_on
|
20
|
+
target.validators_on(attribute).map(&:class)
|
21
|
+
else
|
22
|
+
[]
|
23
|
+
end
|
24
|
+
|
25
|
+
presence_validator?(target_validators)
|
26
|
+
end
|
27
|
+
|
28
|
+
def presence_validator?(target_validators)
|
29
|
+
has_presence_validator = target_validators.include?(
|
30
|
+
ActiveModel::Validations::PresenceValidator
|
31
|
+
)
|
32
|
+
|
33
|
+
if defined? ActiveRecord::Validations::PresenceValidator
|
34
|
+
has_presence_validator |= target_validators.include?(
|
35
|
+
ActiveRecord::Validations::PresenceValidator
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
has_presence_validator
|
40
|
+
end
|
41
|
+
|
42
|
+
def inline_error?(name)
|
43
|
+
error?(name) && inline_errors
|
44
|
+
end
|
45
|
+
|
46
|
+
def generate_error(name)
|
47
|
+
return unless inline_error?(name)
|
48
|
+
|
49
|
+
help_text = get_error_messages(name)
|
50
|
+
help_klass = "invalid-feedback"
|
51
|
+
help_tag = :div
|
52
|
+
|
53
|
+
content_tag(help_tag, help_text, class: help_klass)
|
54
|
+
end
|
55
|
+
|
56
|
+
def get_error_messages(name)
|
57
|
+
object.errors[name].join(", ")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -1,20 +1,47 @@
|
|
1
|
-
|
2
|
-
require_relative "helpers/bootstrap"
|
1
|
+
# require 'bootstrap_form/aliasing'
|
3
2
|
|
4
3
|
module BootstrapForm
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
include BootstrapForm::Helpers::Bootstrap
|
9
|
-
|
10
|
-
attr_reader :layout, :label_col, :control_col, :has_error, :inline_errors, :label_errors, :acts_like_form_tag
|
4
|
+
class FormBuilder < ActionView::Helpers::FormBuilder
|
5
|
+
attr_reader :layout, :label_col, :control_col, :has_error, :inline_errors,
|
6
|
+
:label_errors, :acts_like_form_tag
|
11
7
|
|
12
|
-
|
13
|
-
email_field month_field number_field password_field phone_field
|
14
|
-
range_field search_field telephone_field text_area text_field time_field
|
15
|
-
url_field week_field].freeze
|
8
|
+
include BootstrapForm::Helpers::Bootstrap
|
16
9
|
|
17
|
-
|
10
|
+
include BootstrapForm::FormGroupBuilder
|
11
|
+
include BootstrapForm::FormGroup
|
12
|
+
include BootstrapForm::Components
|
13
|
+
|
14
|
+
include BootstrapForm::Inputs::Base
|
15
|
+
include BootstrapForm::Inputs::CheckBox
|
16
|
+
include BootstrapForm::Inputs::CollectionCheckBoxes
|
17
|
+
include BootstrapForm::Inputs::CollectionRadioButtons
|
18
|
+
include BootstrapForm::Inputs::CollectionSelect
|
19
|
+
include BootstrapForm::Inputs::ColorField
|
20
|
+
include BootstrapForm::Inputs::DateField
|
21
|
+
include BootstrapForm::Inputs::DateSelect
|
22
|
+
include BootstrapForm::Inputs::DatetimeField
|
23
|
+
include BootstrapForm::Inputs::DatetimeLocalField
|
24
|
+
include BootstrapForm::Inputs::DatetimeSelect
|
25
|
+
include BootstrapForm::Inputs::EmailField
|
26
|
+
include BootstrapForm::Inputs::FileField
|
27
|
+
include BootstrapForm::Inputs::GroupedCollectionSelect
|
28
|
+
include BootstrapForm::Inputs::MonthField
|
29
|
+
include BootstrapForm::Inputs::NumberField
|
30
|
+
include BootstrapForm::Inputs::PasswordField
|
31
|
+
include BootstrapForm::Inputs::PhoneField
|
32
|
+
include BootstrapForm::Inputs::RadioButton
|
33
|
+
include BootstrapForm::Inputs::RangeField
|
34
|
+
include BootstrapForm::Inputs::RichTextArea if Rails::VERSION::MAJOR >= 6
|
35
|
+
include BootstrapForm::Inputs::SearchField
|
36
|
+
include BootstrapForm::Inputs::Select
|
37
|
+
include BootstrapForm::Inputs::TelephoneField
|
38
|
+
include BootstrapForm::Inputs::TextArea
|
39
|
+
include BootstrapForm::Inputs::TextField
|
40
|
+
include BootstrapForm::Inputs::TimeField
|
41
|
+
include BootstrapForm::Inputs::TimeSelect
|
42
|
+
include BootstrapForm::Inputs::TimeZoneSelect
|
43
|
+
include BootstrapForm::Inputs::UrlField
|
44
|
+
include BootstrapForm::Inputs::WeekField
|
18
45
|
|
19
46
|
delegate :content_tag, :capture, :concat, to: :@template
|
20
47
|
|
@@ -23,278 +50,24 @@ module BootstrapForm
|
|
23
50
|
@label_col = options[:label_col] || default_label_col
|
24
51
|
@control_col = options[:control_col] || default_control_col
|
25
52
|
@label_errors = options[:label_errors] || false
|
53
|
+
|
26
54
|
@inline_errors = if options[:inline_errors].nil?
|
27
55
|
@label_errors != true
|
28
56
|
else
|
29
57
|
options[:inline_errors] != false
|
30
58
|
end
|
31
59
|
@acts_like_form_tag = options[:acts_like_form_tag]
|
32
|
-
|
33
60
|
super
|
34
61
|
end
|
35
62
|
|
36
|
-
FIELD_HELPERS.each do |method_name|
|
37
|
-
with_method_name = "#{method_name}_with_bootstrap"
|
38
|
-
without_method_name = "#{method_name}_without_bootstrap"
|
39
|
-
|
40
|
-
define_method(with_method_name) do |name, options={}|
|
41
|
-
form_group_builder(name, options) do
|
42
|
-
prepend_and_append_input(name, options) do
|
43
|
-
send(without_method_name, name, options)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
bootstrap_method_alias method_name
|
49
|
-
end
|
50
|
-
|
51
|
-
DATE_SELECT_HELPERS.each do |method_name|
|
52
|
-
with_method_name = "#{method_name}_with_bootstrap"
|
53
|
-
without_method_name = "#{method_name}_without_bootstrap"
|
54
|
-
|
55
|
-
define_method(with_method_name) do |name, options={}, html_options={}|
|
56
|
-
form_group_builder(name, options, html_options) do
|
57
|
-
html_class = control_specific_class(method_name)
|
58
|
-
html_class = "#{html_class} form-inline" if @layout == :horizontal && options[:skip_inline].blank?
|
59
|
-
content_tag(:div, class: html_class) do
|
60
|
-
input_with_error(name) do
|
61
|
-
send(without_method_name, name, options, html_options)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
bootstrap_method_alias method_name
|
68
|
-
end
|
69
|
-
|
70
|
-
def file_field_with_bootstrap(name, options={})
|
71
|
-
options = options.reverse_merge(control_class: "custom-file-input")
|
72
|
-
form_group_builder(name, options) do
|
73
|
-
content_tag(:div, class: "custom-file") do
|
74
|
-
input_with_error(name) do
|
75
|
-
placeholder = options.delete(:placeholder) || "Choose file"
|
76
|
-
placeholder_opts = { class: "custom-file-label" }
|
77
|
-
placeholder_opts[:for] = options[:id] if options[:id].present?
|
78
|
-
|
79
|
-
input = file_field_without_bootstrap(name, options)
|
80
|
-
placeholder_label = label(name, placeholder, placeholder_opts)
|
81
|
-
concat(input)
|
82
|
-
concat(placeholder_label)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
bootstrap_method_alias :file_field
|
89
|
-
|
90
|
-
def select_with_bootstrap(method, choices=nil, options={}, html_options={}, &block)
|
91
|
-
form_group_builder(method, options, html_options) do
|
92
|
-
prepend_and_append_input(method, options) do
|
93
|
-
select_without_bootstrap(method, choices, options, html_options, &block)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
bootstrap_method_alias :select
|
99
|
-
|
100
|
-
def collection_select_with_bootstrap(method, collection, value_method, text_method, options={}, html_options={})
|
101
|
-
form_group_builder(method, options, html_options) do
|
102
|
-
input_with_error(method) do
|
103
|
-
collection_select_without_bootstrap(method, collection, value_method, text_method, options, html_options)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
bootstrap_method_alias :collection_select
|
109
|
-
|
110
|
-
def grouped_collection_select_with_bootstrap(method, collection, group_method,
|
111
|
-
group_label_method, option_key_method,
|
112
|
-
option_value_method, options={}, html_options={})
|
113
|
-
form_group_builder(method, options, html_options) do
|
114
|
-
input_with_error(method) do
|
115
|
-
grouped_collection_select_without_bootstrap(method, collection, group_method,
|
116
|
-
group_label_method, option_key_method,
|
117
|
-
option_value_method, options, html_options)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
bootstrap_method_alias :grouped_collection_select
|
123
|
-
|
124
|
-
def time_zone_select_with_bootstrap(method, priority_zones=nil, options={}, html_options={})
|
125
|
-
form_group_builder(method, options, html_options) do
|
126
|
-
input_with_error(method) do
|
127
|
-
time_zone_select_without_bootstrap(method, priority_zones, options, html_options)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
bootstrap_method_alias :time_zone_select
|
133
|
-
|
134
|
-
def check_box_with_bootstrap(name, options={}, checked_value="1", unchecked_value="0", &block)
|
135
|
-
options = options.symbolize_keys!
|
136
|
-
check_box_options = options.except(:label, :label_class, :error_message, :help,
|
137
|
-
:inline, :custom, :hide_label, :skip_label, :wrapper_class)
|
138
|
-
check_box_classes = [check_box_options[:class]]
|
139
|
-
check_box_classes << "position-static" if options[:skip_label] || options[:hide_label]
|
140
|
-
check_box_classes << "is-invalid" if has_error?(name)
|
141
|
-
|
142
|
-
label_classes = [options[:label_class]]
|
143
|
-
label_classes << hide_class if options[:hide_label]
|
144
|
-
|
145
|
-
if options[:custom]
|
146
|
-
check_box_options[:class] = (["custom-control-input"] + check_box_classes).compact.join(" ")
|
147
|
-
wrapper_class = ["custom-control", "custom-checkbox"]
|
148
|
-
wrapper_class.append("custom-control-inline") if layout_inline?(options[:inline])
|
149
|
-
label_class = label_classes.prepend("custom-control-label").compact.join(" ")
|
150
|
-
else
|
151
|
-
check_box_options[:class] = (["form-check-input"] + check_box_classes).compact.join(" ")
|
152
|
-
wrapper_class = ["form-check"]
|
153
|
-
wrapper_class.append("form-check-inline") if layout_inline?(options[:inline])
|
154
|
-
label_class = label_classes.prepend("form-check-label").compact.join(" ")
|
155
|
-
end
|
156
|
-
|
157
|
-
checkbox_html = check_box_without_bootstrap(name, check_box_options, checked_value, unchecked_value)
|
158
|
-
label_content = block_given? ? capture(&block) : options[:label]
|
159
|
-
label_description = label_content || (object && object.class.human_attribute_name(name)) || name.to_s.humanize
|
160
|
-
|
161
|
-
label_name = name
|
162
|
-
# label's `for` attribute needs to match checkbox tag's id,
|
163
|
-
# IE sanitized value, IE
|
164
|
-
# https://github.com/rails/rails/blob/5-0-stable/actionview/lib/action_view/helpers/tags/base.rb#L123-L125
|
165
|
-
if options[:multiple]
|
166
|
-
label_name =
|
167
|
-
"#{name}_#{checked_value.to_s.gsub(/\s/, '_').gsub(/[^-[[:word:]]]/, '').mb_chars.downcase}"
|
168
|
-
end
|
169
|
-
|
170
|
-
label_options = { class: label_class }
|
171
|
-
label_options[:for] = options[:id] if options[:id].present?
|
172
|
-
|
173
|
-
wrapper_class.append(options[:wrapper_class]) if options[:wrapper_class]
|
174
|
-
|
175
|
-
content_tag(:div, class: wrapper_class.compact.join(" ")) do
|
176
|
-
html = if options[:skip_label]
|
177
|
-
checkbox_html
|
178
|
-
else
|
179
|
-
checkbox_html.concat(label(label_name, label_description, label_options))
|
180
|
-
end
|
181
|
-
html.concat(generate_error(name)) if options[:error_message]
|
182
|
-
html
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
bootstrap_method_alias :check_box
|
187
|
-
|
188
|
-
def radio_button_with_bootstrap(name, value, *args)
|
189
|
-
options = args.extract_options!.symbolize_keys!
|
190
|
-
radio_options = options.except(:label, :label_class, :error_message, :help,
|
191
|
-
:inline, :custom, :hide_label, :skip_label,
|
192
|
-
:wrapper_class)
|
193
|
-
radio_classes = [options[:class]]
|
194
|
-
radio_classes << "position-static" if options[:skip_label] || options[:hide_label]
|
195
|
-
radio_classes << "is-invalid" if has_error?(name)
|
196
|
-
|
197
|
-
label_classes = [options[:label_class]]
|
198
|
-
label_classes << hide_class if options[:hide_label]
|
199
|
-
|
200
|
-
if options[:custom]
|
201
|
-
radio_options[:class] = radio_classes.prepend("custom-control-input").compact.join(" ")
|
202
|
-
wrapper_class = ["custom-control", "custom-radio"]
|
203
|
-
wrapper_class.append("custom-control-inline") if layout_inline?(options[:inline])
|
204
|
-
label_class = label_classes.prepend("custom-control-label").compact.join(" ")
|
205
|
-
else
|
206
|
-
radio_options[:class] = radio_classes.prepend("form-check-input").compact.join(" ")
|
207
|
-
wrapper_class = ["form-check"]
|
208
|
-
wrapper_class.append("form-check-inline") if layout_inline?(options[:inline])
|
209
|
-
wrapper_class.append("disabled") if options[:disabled]
|
210
|
-
label_class = label_classes.prepend("form-check-label").compact.join(" ")
|
211
|
-
end
|
212
|
-
radio_html = radio_button_without_bootstrap(name, value, radio_options)
|
213
|
-
|
214
|
-
label_options = { value: value, class: label_class }
|
215
|
-
label_options[:for] = options[:id] if options[:id].present?
|
216
|
-
|
217
|
-
wrapper_class.append(options[:wrapper_class]) if options[:wrapper_class]
|
218
|
-
|
219
|
-
content_tag(:div, class: wrapper_class.compact.join(" ")) do
|
220
|
-
html = if options[:skip_label]
|
221
|
-
radio_html
|
222
|
-
else
|
223
|
-
radio_html.concat(label(name, options[:label], label_options))
|
224
|
-
end
|
225
|
-
html.concat(generate_error(name)) if options[:error_message]
|
226
|
-
html
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
bootstrap_method_alias :radio_button
|
231
|
-
|
232
|
-
def collection_check_boxes_with_bootstrap(*args)
|
233
|
-
html = inputs_collection(*args) do |name, value, options|
|
234
|
-
options[:multiple] = true
|
235
|
-
check_box(name, options, value, nil)
|
236
|
-
end
|
237
|
-
hidden_field(args.first, value: "", multiple: true).concat(html)
|
238
|
-
end
|
239
|
-
|
240
|
-
bootstrap_method_alias :collection_check_boxes
|
241
|
-
|
242
|
-
def collection_radio_buttons_with_bootstrap(*args)
|
243
|
-
inputs_collection(*args) do |name, value, options|
|
244
|
-
radio_button(name, value, options)
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
bootstrap_method_alias :collection_radio_buttons
|
249
|
-
|
250
|
-
def form_group(*args, &block)
|
251
|
-
options = args.extract_options!
|
252
|
-
name = args.first
|
253
|
-
|
254
|
-
options[:class] = ["form-group", options[:class]].compact.join(" ")
|
255
|
-
options[:class] << " row" if get_group_layout(options[:layout]) == :horizontal &&
|
256
|
-
!options[:class].split.include?("form-row")
|
257
|
-
options[:class] << " form-inline" if field_inline_override?(options[:layout])
|
258
|
-
options[:class] << " #{feedback_class}" if options[:icon]
|
259
|
-
|
260
|
-
content_tag(:div, options.except(:append, :id, :label, :help, :icon,
|
261
|
-
:input_group_class, :label_col, :control_col,
|
262
|
-
:add_control_col_class, :layout, :prepend)) do
|
263
|
-
label = generate_label(options[:id], name, options[:label], options[:label_col], options[:layout]) if options[:label]
|
264
|
-
control = capture(&block)
|
265
|
-
|
266
|
-
help = options[:help]
|
267
|
-
help_text = generate_help(name, help).to_s
|
268
|
-
|
269
|
-
if get_group_layout(options[:layout]) == :horizontal
|
270
|
-
control_class = options[:control_col] || control_col
|
271
|
-
control_class = [control_class, options[:add_control_col_class]].compact.join(" ") if options[:add_control_col_class]
|
272
|
-
unless options[:label]
|
273
|
-
control_offset = offset_col(options[:label_col] || @label_col)
|
274
|
-
control_class = "#{control_class} #{control_offset}"
|
275
|
-
end
|
276
|
-
control = content_tag(:div, control + help_text, class: control_class)
|
277
|
-
concat(label).concat(control)
|
278
|
-
else
|
279
|
-
concat(label).concat(control).concat(help_text)
|
280
|
-
end
|
281
|
-
end
|
282
|
-
end
|
283
|
-
|
284
63
|
def fields_for_with_bootstrap(record_name, record_object=nil, fields_options={}, &block)
|
285
|
-
|
286
|
-
|
64
|
+
fields_options = fields_for_options(record_object, fields_options)
|
65
|
+
record_object.is_a?(Hash) && record_object.extractable_options? &&
|
287
66
|
record_object = nil
|
288
|
-
end
|
289
|
-
fields_options[:layout] ||= options[:layout]
|
290
|
-
fields_options[:label_col] = fields_options[:label_col].present? ? (fields_options[:label_col]).to_s : options[:label_col]
|
291
|
-
fields_options[:control_col] ||= options[:control_col]
|
292
|
-
fields_options[:inline_errors] ||= options[:inline_errors]
|
293
|
-
fields_options[:label_errors] ||= options[:label_errors]
|
294
67
|
fields_for_without_bootstrap(record_name, record_object, fields_options, &block)
|
295
68
|
end
|
296
69
|
|
297
|
-
|
70
|
+
bootstrap_alias :fields_for
|
298
71
|
|
299
72
|
# the Rails `fields` method passes its options
|
300
73
|
# to the builder, so there is no need to write a `bootstrap_form` helper
|
@@ -302,32 +75,15 @@ module BootstrapForm
|
|
302
75
|
|
303
76
|
private
|
304
77
|
|
305
|
-
def
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
layout_in_effect(field_layout) == :inline
|
315
|
-
end
|
316
|
-
|
317
|
-
def field_inline_override?(field_layout=nil)
|
318
|
-
field_layout == :inline && layout != :inline
|
319
|
-
end
|
320
|
-
|
321
|
-
# true and false should only come from check_box and radio_button,
|
322
|
-
# and those don't have a :horizontal layout
|
323
|
-
def layout_in_effect(field_layout)
|
324
|
-
field_layout = :inline if field_layout == true
|
325
|
-
field_layout = :default if field_layout == false
|
326
|
-
field_layout || layout
|
327
|
-
end
|
328
|
-
|
329
|
-
def get_group_layout(group_layout)
|
330
|
-
group_layout || layout
|
78
|
+
def fields_for_options(record_object, fields_options)
|
79
|
+
field_options = fields_options
|
80
|
+
record_object.is_a?(Hash) && record_object.extractable_options? &&
|
81
|
+
field_options = record_object
|
82
|
+
%i[layout control_col inline_errors label_errors].each do |option|
|
83
|
+
field_options[option] ||= options[option]
|
84
|
+
end
|
85
|
+
field_options[:label_col] = field_options[:label_col].present? ? (field_options[:label_col]).to_s : options[:label_col]
|
86
|
+
field_options
|
331
87
|
end
|
332
88
|
|
333
89
|
def default_label_col
|
@@ -355,233 +111,7 @@ module BootstrapForm
|
|
355
111
|
end
|
356
112
|
|
357
113
|
def control_specific_class(method)
|
358
|
-
"rails-bootstrap-forms-#{method.tr('_', '-')}"
|
359
|
-
end
|
360
|
-
|
361
|
-
def has_error?(name)
|
362
|
-
object.respond_to?(:errors) && !(name.nil? || object.errors[name].empty?)
|
363
|
-
end
|
364
|
-
|
365
|
-
def required_attribute?(obj, attribute)
|
366
|
-
return false unless obj && attribute
|
367
|
-
|
368
|
-
target = obj.class == Class ? obj : obj.class
|
369
|
-
|
370
|
-
target_validators = if target.respond_to? :validators_on
|
371
|
-
target.validators_on(attribute).map(&:class)
|
372
|
-
else
|
373
|
-
[]
|
374
|
-
end
|
375
|
-
|
376
|
-
has_presence_validator = target_validators.include?(
|
377
|
-
ActiveModel::Validations::PresenceValidator
|
378
|
-
)
|
379
|
-
|
380
|
-
if defined? ActiveRecord::Validations::PresenceValidator
|
381
|
-
has_presence_validator |= target_validators.include?(
|
382
|
-
ActiveRecord::Validations::PresenceValidator
|
383
|
-
)
|
384
|
-
end
|
385
|
-
|
386
|
-
has_presence_validator
|
387
|
-
end
|
388
|
-
|
389
|
-
# TODO: Refactor this method and remove the rubocop:disable
|
390
|
-
def form_group_builder(method, options, html_options=nil) # rubocop:disable Metrics/MethodLength
|
391
|
-
options.symbolize_keys!
|
392
|
-
|
393
|
-
wrapper_class = options.delete(:wrapper_class)
|
394
|
-
wrapper_options = options.delete(:wrapper)
|
395
|
-
|
396
|
-
html_options.symbolize_keys! if html_options
|
397
|
-
|
398
|
-
# Add control_class; allow it to be overridden by :control_class option
|
399
|
-
css_options = html_options || options
|
400
|
-
control_classes = css_options.delete(:control_class) { control_class }
|
401
|
-
css_options[:class] = [control_classes, css_options[:class]].compact.join(" ")
|
402
|
-
css_options[:class] << " is-invalid" if has_error?(method)
|
403
|
-
|
404
|
-
options = convert_form_tag_options(method, options) if acts_like_form_tag
|
405
|
-
|
406
|
-
help = options.delete(:help)
|
407
|
-
icon = options.delete(:icon)
|
408
|
-
label_col = options.delete(:label_col)
|
409
|
-
control_col = options.delete(:control_col)
|
410
|
-
add_control_col_class = options.delete(:add_control_col_class)
|
411
|
-
layout = get_group_layout(options.delete(:layout))
|
412
|
-
form_group_options = {
|
413
|
-
id: options[:id],
|
414
|
-
help: help,
|
415
|
-
icon: icon,
|
416
|
-
label_col: label_col,
|
417
|
-
control_col: control_col,
|
418
|
-
add_control_col_class: add_control_col_class,
|
419
|
-
layout: layout,
|
420
|
-
class: wrapper_class
|
421
|
-
}
|
422
|
-
|
423
|
-
form_group_options.merge!(wrapper_options) if wrapper_options.is_a?(Hash)
|
424
|
-
|
425
|
-
unless options.delete(:skip_label)
|
426
|
-
if options[:label].is_a?(Hash)
|
427
|
-
label_text = options[:label].delete(:text)
|
428
|
-
label_class = options[:label].delete(:class)
|
429
|
-
options.delete(:label)
|
430
|
-
end
|
431
|
-
label_class ||= options.delete(:label_class)
|
432
|
-
label_class = hide_class if options.delete(:hide_label) || options[:label_as_placeholder]
|
433
|
-
|
434
|
-
label_text ||= options.delete(:label) if options[:label].is_a?(String)
|
435
|
-
|
436
|
-
if options.key?(:skip_required)
|
437
|
-
warn "`:skip_required` is deprecated, use `:required: false` instead"
|
438
|
-
options[:required] = options.delete(:skip_required) ? false : :default
|
439
|
-
end
|
440
|
-
|
441
|
-
form_group_options[:label] = {
|
442
|
-
text: label_text,
|
443
|
-
class: label_class,
|
444
|
-
required: options[:required]
|
445
|
-
}.merge(css_options[:id].present? ? { for: css_options[:id] } : {})
|
446
|
-
|
447
|
-
css_options[:placeholder] = label_text || object.class.human_attribute_name(method) if options.delete(:label_as_placeholder)
|
448
|
-
end
|
449
|
-
|
450
|
-
if wrapper_options == false
|
451
|
-
yield
|
452
|
-
else
|
453
|
-
form_group(method, form_group_options) do
|
454
|
-
yield
|
455
|
-
end
|
456
|
-
end
|
457
|
-
end
|
458
|
-
|
459
|
-
def convert_form_tag_options(method, options={})
|
460
|
-
unless @options[:skip_default_ids]
|
461
|
-
options[:name] ||= method
|
462
|
-
options[:id] ||= method
|
463
|
-
end
|
464
|
-
options
|
465
|
-
end
|
466
|
-
|
467
|
-
def generate_label(id, name, options, custom_label_col, group_layout)
|
468
|
-
# id is the caller's options[:id] at the only place this method is called.
|
469
|
-
# The options argument is a small subset of the options that might have
|
470
|
-
# been passed to generate_label's caller, and definitely doesn't include
|
471
|
-
# :id.
|
472
|
-
options[:for] = id if acts_like_form_tag
|
473
|
-
classes = [options[:class]]
|
474
|
-
|
475
|
-
if layout_horizontal?(group_layout)
|
476
|
-
classes << "col-form-label"
|
477
|
-
classes << (custom_label_col || label_col)
|
478
|
-
elsif layout_inline?(group_layout)
|
479
|
-
classes << "mr-sm-2"
|
480
|
-
end
|
481
|
-
|
482
|
-
case options.delete(:required)
|
483
|
-
when true
|
484
|
-
classes << "required"
|
485
|
-
when nil, :default
|
486
|
-
classes << "required" if required_attribute?(object, name)
|
487
|
-
end
|
488
|
-
|
489
|
-
options[:class] = classes.compact.join(" ").strip
|
490
|
-
options.delete(:class) if options[:class].empty?
|
491
|
-
|
492
|
-
if label_errors && has_error?(name)
|
493
|
-
error_messages = get_error_messages(name)
|
494
|
-
label_text = (options[:text] || object.class.human_attribute_name(name)).to_s.concat(" #{error_messages}")
|
495
|
-
options[:class] = [options[:class], "text-danger"].compact.join(" ")
|
496
|
-
label(name, label_text, options.except(:text))
|
497
|
-
else
|
498
|
-
label(name, options[:text], options.except(:text))
|
499
|
-
end
|
500
|
-
end
|
501
|
-
|
502
|
-
def has_inline_error?(name)
|
503
|
-
has_error?(name) && inline_errors
|
504
|
-
end
|
505
|
-
|
506
|
-
def generate_error(name)
|
507
|
-
if has_inline_error?(name)
|
508
|
-
help_text = get_error_messages(name)
|
509
|
-
help_klass = "invalid-feedback"
|
510
|
-
help_tag = :div
|
511
|
-
|
512
|
-
content_tag(help_tag, help_text, class: help_klass)
|
513
|
-
end
|
514
|
-
end
|
515
|
-
|
516
|
-
def generate_help(name, help_text)
|
517
|
-
return if help_text == false || has_inline_error?(name)
|
518
|
-
|
519
|
-
help_klass ||= "form-text text-muted"
|
520
|
-
help_text ||= get_help_text_by_i18n_key(name)
|
521
|
-
help_tag ||= :small
|
522
|
-
|
523
|
-
content_tag(help_tag, help_text, class: help_klass) if help_text.present?
|
524
|
-
end
|
525
|
-
|
526
|
-
def get_error_messages(name)
|
527
|
-
object.errors[name].join(", ")
|
528
|
-
end
|
529
|
-
|
530
|
-
def inputs_collection(name, collection, value, text, options={})
|
531
|
-
options[:inline] ||= layout_inline?(options[:layout])
|
532
|
-
form_group_builder(name, options) do
|
533
|
-
inputs = ""
|
534
|
-
|
535
|
-
collection.each_with_index do |obj, i|
|
536
|
-
input_options = options.merge(label: text.respond_to?(:call) ? text.call(obj) : obj.send(text))
|
537
|
-
|
538
|
-
input_value = value.respond_to?(:call) ? value.call(obj) : obj.send(value)
|
539
|
-
if (checked = input_options[:checked])
|
540
|
-
input_options[:checked] = checked == input_value ||
|
541
|
-
Array(checked).try(:include?, input_value) ||
|
542
|
-
checked == obj ||
|
543
|
-
Array(checked).try(:include?, obj)
|
544
|
-
end
|
545
|
-
|
546
|
-
input_options.delete(:class)
|
547
|
-
inputs << yield(name, input_value, input_options.merge(error_message: i == collection.size - 1))
|
548
|
-
end
|
549
|
-
|
550
|
-
inputs.html_safe
|
551
|
-
end
|
552
|
-
end
|
553
|
-
|
554
|
-
def get_help_text_by_i18n_key(name)
|
555
|
-
if object
|
556
|
-
|
557
|
-
partial_scope = if object.class.respond_to?(:model_name)
|
558
|
-
object.class.model_name.name
|
559
|
-
else
|
560
|
-
object.class.name
|
561
|
-
end
|
562
|
-
|
563
|
-
underscored_scope = "activerecord.help.#{partial_scope.underscore}"
|
564
|
-
downcased_scope = "activerecord.help.#{partial_scope.downcase}"
|
565
|
-
# First check for a subkey :html, as it is also accepted by i18n, and the
|
566
|
-
# simple check for name would return an hash instead of a string (both
|
567
|
-
# with .presence returning true!)
|
568
|
-
help_text = I18n.t("#{name}.html", scope: underscored_scope, default: "").html_safe.presence
|
569
|
-
help_text ||= if (text = I18n.t("#{name}.html", scope: downcased_scope, default: "").html_safe.presence)
|
570
|
-
warn "I18n key '#{downcased_scope}.#{name}' is deprecated, use '#{underscored_scope}.#{name}' instead"
|
571
|
-
text
|
572
|
-
end
|
573
|
-
help_text ||= I18n.t(name, scope: underscored_scope, default: "").presence
|
574
|
-
help_text ||= if (text = I18n.t(name, scope: downcased_scope, default: "").presence)
|
575
|
-
warn "I18n key '#{downcased_scope}.#{name}' is deprecated, use '#{underscored_scope}.#{name}' instead"
|
576
|
-
text
|
577
|
-
end
|
578
|
-
help_text ||= I18n.t("#{name}_html", scope: underscored_scope, default: "").html_safe.presence
|
579
|
-
help_text ||= if (text = I18n.t("#{name}_html", scope: downcased_scope, default: "").html_safe.presence)
|
580
|
-
warn "I18n key '#{downcased_scope}.#{name}' is deprecated, use '#{underscored_scope}.#{name}' instead"
|
581
|
-
text
|
582
|
-
end
|
583
|
-
help_text
|
584
|
-
end
|
114
|
+
"rails-bootstrap-forms-#{method.to_s.tr('_', '-')}"
|
585
115
|
end
|
586
116
|
end
|
587
117
|
end
|