bootstrap_form 4.0.0 → 4.1.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.
@@ -1,19 +1,20 @@
1
- require_relative 'aliasing'
2
- require_relative 'helpers/bootstrap'
1
+ require_relative "aliasing"
2
+ require_relative "helpers/bootstrap"
3
3
 
4
4
  module BootstrapForm
5
- class FormBuilder < ActionView::Helpers::FormBuilder
5
+ # TODO: Refactor this class and remove the rubocop:disable
6
+ class FormBuilder < ActionView::Helpers::FormBuilder # rubocop:disable Metrics/ClassLength
6
7
  extend BootstrapForm::Aliasing
7
8
  include BootstrapForm::Helpers::Bootstrap
8
9
 
9
10
  attr_reader :layout, :label_col, :control_col, :has_error, :inline_errors, :label_errors, :acts_like_form_tag
10
11
 
11
- FIELD_HELPERS = %w{color_field date_field datetime_field datetime_local_field
12
- email_field month_field number_field password_field phone_field
13
- range_field search_field telephone_field text_area text_field time_field
14
- url_field week_field}
12
+ FIELD_HELPERS = %w[color_field date_field datetime_field datetime_local_field
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
15
16
 
16
- DATE_SELECT_HELPERS = %w{date_select time_select datetime_select}
17
+ DATE_SELECT_HELPERS = %w[date_select time_select datetime_select].freeze
17
18
 
18
19
  delegate :content_tag, :capture, :concat, to: :@template
19
20
 
@@ -23,10 +24,10 @@ module BootstrapForm
23
24
  @control_col = options[:control_col] || default_control_col
24
25
  @label_errors = options[:label_errors] || false
25
26
  @inline_errors = if options[:inline_errors].nil?
26
- @label_errors != true
27
- else
28
- options[:inline_errors] != false
29
- end
27
+ @label_errors != true
28
+ else
29
+ options[:inline_errors] != false
30
+ end
30
31
  @acts_like_form_tag = options[:acts_like_form_tag]
31
32
 
32
33
  super
@@ -36,7 +37,7 @@ module BootstrapForm
36
37
  with_method_name = "#{method_name}_with_bootstrap"
37
38
  without_method_name = "#{method_name}_without_bootstrap"
38
39
 
39
- define_method(with_method_name) do |name, options = {}|
40
+ define_method(with_method_name) do |name, options={}|
40
41
  form_group_builder(name, options) do
41
42
  prepend_and_append_input(name, options) do
42
43
  send(without_method_name, name, options)
@@ -51,12 +52,10 @@ module BootstrapForm
51
52
  with_method_name = "#{method_name}_with_bootstrap"
52
53
  without_method_name = "#{method_name}_without_bootstrap"
53
54
 
54
- define_method(with_method_name) do |name, options = {}, html_options = {}|
55
+ define_method(with_method_name) do |name, options={}, html_options={}|
55
56
  form_group_builder(name, options, html_options) do
56
57
  html_class = control_specific_class(method_name)
57
- if @layout == :horizontal && !options[:skip_inline].present?
58
- html_class = "#{html_class} form-inline"
59
- end
58
+ html_class = "#{html_class} form-inline" if @layout == :horizontal && options[:skip_inline].blank?
60
59
  content_tag(:div, class: html_class) do
61
60
  input_with_error(name) do
62
61
  send(without_method_name, name, options, html_options)
@@ -68,7 +67,7 @@ module BootstrapForm
68
67
  bootstrap_method_alias method_name
69
68
  end
70
69
 
71
- def file_field_with_bootstrap(name, options = {})
70
+ def file_field_with_bootstrap(name, options={})
72
71
  options = options.reverse_merge(control_class: "custom-file-input")
73
72
  form_group_builder(name, options) do
74
73
  content_tag(:div, class: "custom-file") do
@@ -88,7 +87,7 @@ module BootstrapForm
88
87
 
89
88
  bootstrap_method_alias :file_field
90
89
 
91
- def select_with_bootstrap(method, choices = nil, options = {}, html_options = {}, &block)
90
+ def select_with_bootstrap(method, choices=nil, options={}, html_options={}, &block)
92
91
  form_group_builder(method, options, html_options) do
93
92
  prepend_and_append_input(method, options) do
94
93
  select_without_bootstrap(method, choices, options, html_options, &block)
@@ -98,7 +97,7 @@ module BootstrapForm
98
97
 
99
98
  bootstrap_method_alias :select
100
99
 
101
- def collection_select_with_bootstrap(method, collection, value_method, text_method, options = {}, html_options = {})
100
+ def collection_select_with_bootstrap(method, collection, value_method, text_method, options={}, html_options={})
102
101
  form_group_builder(method, options, html_options) do
103
102
  input_with_error(method) do
104
103
  collection_select_without_bootstrap(method, collection, value_method, text_method, options, html_options)
@@ -108,17 +107,21 @@ module BootstrapForm
108
107
 
109
108
  bootstrap_method_alias :collection_select
110
109
 
111
- def grouped_collection_select_with_bootstrap(method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
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={})
112
113
  form_group_builder(method, options, html_options) do
113
114
  input_with_error(method) do
114
- grouped_collection_select_without_bootstrap(method, collection, group_method, group_label_method, option_key_method, option_value_method, options, html_options)
115
+ grouped_collection_select_without_bootstrap(method, collection, group_method,
116
+ group_label_method, option_key_method,
117
+ option_value_method, options, html_options)
115
118
  end
116
119
  end
117
120
  end
118
121
 
119
122
  bootstrap_method_alias :grouped_collection_select
120
123
 
121
- def time_zone_select_with_bootstrap(method, priority_zones = nil, options = {}, html_options = {})
124
+ def time_zone_select_with_bootstrap(method, priority_zones=nil, options={}, html_options={})
122
125
  form_group_builder(method, options, html_options) do
123
126
  input_with_error(method) do
124
127
  time_zone_select_without_bootstrap(method, priority_zones, options, html_options)
@@ -128,9 +131,10 @@ module BootstrapForm
128
131
 
129
132
  bootstrap_method_alias :time_zone_select
130
133
 
131
- def check_box_with_bootstrap(name, options = {}, checked_value = "1", unchecked_value = "0", &block)
134
+ def check_box_with_bootstrap(name, options={}, checked_value="1", unchecked_value="0", &block)
132
135
  options = options.symbolize_keys!
133
- check_box_options = options.except(:label, :label_class, :error_message, :help, :inline, :custom, :hide_label, :skip_label, :wrapper_class)
136
+ check_box_options = options.except(:label, :label_class, :error_message, :help,
137
+ :inline, :custom, :hide_label, :skip_label, :wrapper_class)
134
138
  check_box_classes = [check_box_options[:class]]
135
139
  check_box_classes << "position-static" if options[:skip_label] || options[:hide_label]
136
140
  check_box_classes << "is-invalid" if has_error?(name)
@@ -139,12 +143,12 @@ module BootstrapForm
139
143
  label_classes << hide_class if options[:hide_label]
140
144
 
141
145
  if options[:custom]
142
- check_box_options[:class] = (["custom-control-input"] + check_box_classes).compact.join(' ')
146
+ check_box_options[:class] = (["custom-control-input"] + check_box_classes).compact.join(" ")
143
147
  wrapper_class = ["custom-control", "custom-checkbox"]
144
148
  wrapper_class.append("custom-control-inline") if layout_inline?(options[:inline])
145
149
  label_class = label_classes.prepend("custom-control-label").compact.join(" ")
146
150
  else
147
- check_box_options[:class] = (["form-check-input"] + check_box_classes).compact.join(' ')
151
+ check_box_options[:class] = (["form-check-input"] + check_box_classes).compact.join(" ")
148
152
  wrapper_class = ["form-check"]
149
153
  wrapper_class.append("form-check-inline") if layout_inline?(options[:inline])
150
154
  label_class = label_classes.prepend("form-check-label").compact.join(" ")
@@ -160,7 +164,7 @@ module BootstrapForm
160
164
  # https://github.com/rails/rails/blob/5-0-stable/actionview/lib/action_view/helpers/tags/base.rb#L123-L125
161
165
  if options[:multiple]
162
166
  label_name =
163
- "#{name}_#{checked_value.to_s.gsub(/\s/, "_").gsub(/[^-[[:word:]]]/, "").mb_chars.downcase.to_s}"
167
+ "#{name}_#{checked_value.to_s.gsub(/\s/, '_').gsub(/[^-[[:word:]]]/, '').mb_chars.downcase}"
164
168
  end
165
169
 
166
170
  label_options = { class: label_class }
@@ -170,10 +174,10 @@ module BootstrapForm
170
174
 
171
175
  content_tag(:div, class: wrapper_class.compact.join(" ")) do
172
176
  html = if options[:skip_label]
173
- checkbox_html
174
- else
175
- checkbox_html.concat(label(label_name, label_description, label_options))
176
- end
177
+ checkbox_html
178
+ else
179
+ checkbox_html.concat(label(label_name, label_description, label_options))
180
+ end
177
181
  html.concat(generate_error(name)) if options[:error_message]
178
182
  html
179
183
  end
@@ -183,21 +187,23 @@ module BootstrapForm
183
187
 
184
188
  def radio_button_with_bootstrap(name, value, *args)
185
189
  options = args.extract_options!.symbolize_keys!
186
- radio_options = options.except(:label, :label_class, :error_message, :help, :inline, :custom, :hide_label, :skip_label, :wrapper_class)
190
+ radio_options = options.except(:label, :label_class, :error_message, :help,
191
+ :inline, :custom, :hide_label, :skip_label,
192
+ :wrapper_class)
187
193
  radio_classes = [options[:class]]
188
194
  radio_classes << "position-static" if options[:skip_label] || options[:hide_label]
189
195
  radio_classes << "is-invalid" if has_error?(name)
190
196
 
191
- label_classes = [options[:label_class]]
197
+ label_classes = [options[:label_class]]
192
198
  label_classes << hide_class if options[:hide_label]
193
199
 
194
200
  if options[:custom]
195
- radio_options[:class] = radio_classes.prepend("custom-control-input").compact.join(' ')
201
+ radio_options[:class] = radio_classes.prepend("custom-control-input").compact.join(" ")
196
202
  wrapper_class = ["custom-control", "custom-radio"]
197
203
  wrapper_class.append("custom-control-inline") if layout_inline?(options[:inline])
198
204
  label_class = label_classes.prepend("custom-control-label").compact.join(" ")
199
205
  else
200
- radio_options[:class] = radio_classes.prepend("form-check-input").compact.join(' ')
206
+ radio_options[:class] = radio_classes.prepend("form-check-input").compact.join(" ")
201
207
  wrapper_class = ["form-check"]
202
208
  wrapper_class.append("form-check-inline") if layout_inline?(options[:inline])
203
209
  wrapper_class.append("disabled") if options[:disabled]
@@ -212,10 +218,10 @@ module BootstrapForm
212
218
 
213
219
  content_tag(:div, class: wrapper_class.compact.join(" ")) do
214
220
  html = if options[:skip_label]
215
- radio_html
216
- else
217
- radio_html.concat(label(name, options[:label], label_options))
218
- end
221
+ radio_html
222
+ else
223
+ radio_html.concat(label(name, options[:label], label_options))
224
+ end
219
225
  html.concat(generate_error(name)) if options[:error_message]
220
226
  html
221
227
  end
@@ -228,7 +234,7 @@ module BootstrapForm
228
234
  options[:multiple] = true
229
235
  check_box(name, options, value, nil)
230
236
  end
231
- hidden_field(args.first,{value: "", multiple: true}).concat(html)
237
+ hidden_field(args.first, value: "", multiple: true).concat(html)
232
238
  end
233
239
 
234
240
  bootstrap_method_alias :collection_check_boxes
@@ -245,13 +251,15 @@ module BootstrapForm
245
251
  options = args.extract_options!
246
252
  name = args.first
247
253
 
248
- options[:class] = ["form-group", options[:class]].compact.join(' ')
254
+ options[:class] = ["form-group", options[:class]].compact.join(" ")
249
255
  options[:class] << " row" if get_group_layout(options[:layout]) == :horizontal &&
250
256
  !options[:class].split.include?("form-row")
251
257
  options[:class] << " form-inline" if field_inline_override?(options[:layout])
252
258
  options[:class] << " #{feedback_class}" if options[:icon]
253
259
 
254
- content_tag(:div, options.except(:append, :id, :label, :help, :icon, :input_group_class, :label_col, :control_col, :layout, :prepend)) do
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
255
263
  label = generate_label(options[:id], name, options[:label], options[:label_col], options[:layout]) if options[:label]
256
264
  control = capture(&block)
257
265
 
@@ -260,6 +268,7 @@ module BootstrapForm
260
268
 
261
269
  if get_group_layout(options[:layout]) == :horizontal
262
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]
263
272
  unless options[:label]
264
273
  control_offset = offset_col(options[:label_col] || @label_col)
265
274
  control_class = "#{control_class} #{control_offset}"
@@ -272,13 +281,13 @@ module BootstrapForm
272
281
  end
273
282
  end
274
283
 
275
- def fields_for_with_bootstrap(record_name, record_object = nil, fields_options = {}, &block)
284
+ def fields_for_with_bootstrap(record_name, record_object=nil, fields_options={}, &block)
276
285
  if record_object.is_a?(Hash) && record_object.extractable_options?
277
286
  fields_options = record_object
278
287
  record_object = nil
279
288
  end
280
289
  fields_options[:layout] ||= options[:layout]
281
- fields_options[:label_col] = fields_options[:label_col].present? ? "#{fields_options[:label_col]}" : options[:label_col]
290
+ fields_options[:label_col] = fields_options[:label_col].present? ? (fields_options[:label_col]).to_s : options[:label_col]
282
291
  fields_options[:control_col] ||= options[:control_col]
283
292
  fields_options[:inline_errors] ||= options[:inline_errors]
284
293
  fields_options[:label_errors] ||= options[:label_errors]
@@ -293,19 +302,19 @@ module BootstrapForm
293
302
 
294
303
  private
295
304
 
296
- def layout_default?(field_layout = nil)
305
+ def layout_default?(field_layout=nil)
297
306
  [:default, nil].include? layout_in_effect(field_layout)
298
307
  end
299
308
 
300
- def layout_horizontal?(field_layout = nil)
309
+ def layout_horizontal?(field_layout=nil)
301
310
  layout_in_effect(field_layout) == :horizontal
302
311
  end
303
312
 
304
- def layout_inline?(field_layout = nil)
313
+ def layout_inline?(field_layout=nil)
305
314
  layout_in_effect(field_layout) == :inline
306
315
  end
307
316
 
308
- def field_inline_override?(field_layout = nil)
317
+ def field_inline_override?(field_layout=nil)
309
318
  field_layout == :inline && layout != :inline
310
319
  end
311
320
 
@@ -346,7 +355,7 @@ module BootstrapForm
346
355
  end
347
356
 
348
357
  def control_specific_class(method)
349
- "rails-bootstrap-forms-#{method.gsub(/_/, "-")}"
358
+ "rails-bootstrap-forms-#{method.tr('_', '-')}"
350
359
  end
351
360
 
352
361
  def has_error?(name)
@@ -354,10 +363,9 @@ module BootstrapForm
354
363
  end
355
364
 
356
365
  def required_attribute?(obj, attribute)
366
+ return false unless obj && attribute
357
367
 
358
- return false unless obj and attribute
359
-
360
- target = (obj.class == Class) ? obj : obj.class
368
+ target = obj.class == Class ? obj : obj.class
361
369
 
362
370
  target_validators = if target.respond_to? :validators_on
363
371
  target.validators_on(attribute).map(&:class)
@@ -366,17 +374,20 @@ module BootstrapForm
366
374
  end
367
375
 
368
376
  has_presence_validator = target_validators.include?(
369
- ActiveModel::Validations::PresenceValidator)
377
+ ActiveModel::Validations::PresenceValidator
378
+ )
370
379
 
371
380
  if defined? ActiveRecord::Validations::PresenceValidator
372
381
  has_presence_validator |= target_validators.include?(
373
- ActiveRecord::Validations::PresenceValidator)
382
+ ActiveRecord::Validations::PresenceValidator
383
+ )
374
384
  end
375
385
 
376
386
  has_presence_validator
377
387
  end
378
388
 
379
- def form_group_builder(method, options, html_options = nil)
389
+ # TODO: Refactor this method and remove the rubocop:disable
390
+ def form_group_builder(method, options, html_options=nil) # rubocop:disable Metrics/MethodLength
380
391
  options.symbolize_keys!
381
392
 
382
393
  wrapper_class = options.delete(:wrapper_class)
@@ -396,6 +407,7 @@ module BootstrapForm
396
407
  icon = options.delete(:icon)
397
408
  label_col = options.delete(:label_col)
398
409
  control_col = options.delete(:control_col)
410
+ add_control_col_class = options.delete(:add_control_col_class)
399
411
  layout = get_group_layout(options.delete(:layout))
400
412
  form_group_options = {
401
413
  id: options[:id],
@@ -403,13 +415,12 @@ module BootstrapForm
403
415
  icon: icon,
404
416
  label_col: label_col,
405
417
  control_col: control_col,
418
+ add_control_col_class: add_control_col_class,
406
419
  layout: layout,
407
420
  class: wrapper_class
408
421
  }
409
422
 
410
- if wrapper_options.is_a?(Hash)
411
- form_group_options.merge!(wrapper_options)
412
- end
423
+ form_group_options.merge!(wrapper_options) if wrapper_options.is_a?(Hash)
413
424
 
414
425
  unless options.delete(:skip_label)
415
426
  if options[:label].is_a?(Hash)
@@ -420,27 +431,32 @@ module BootstrapForm
420
431
  label_class ||= options.delete(:label_class)
421
432
  label_class = hide_class if options.delete(:hide_label) || options[:label_as_placeholder]
422
433
 
423
- if options[:label].is_a?(String)
424
- label_text ||= options.delete(:label)
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
425
439
  end
426
440
 
427
441
  form_group_options[:label] = {
428
442
  text: label_text,
429
443
  class: label_class,
430
- skip_required: options.delete(:skip_required)
444
+ required: options[:required]
431
445
  }.merge(css_options[:id].present? ? { for: css_options[:id] } : {})
432
446
 
433
- if options.delete(:label_as_placeholder)
434
- css_options[:placeholder] = label_text || object.class.human_attribute_name(method)
435
- end
447
+ css_options[:placeholder] = label_text || object.class.human_attribute_name(method) if options.delete(:label_as_placeholder)
436
448
  end
437
449
 
438
- form_group(method, form_group_options) do
450
+ if wrapper_options == false
439
451
  yield
452
+ else
453
+ form_group(method, form_group_options) do
454
+ yield
455
+ end
440
456
  end
441
457
  end
442
458
 
443
- def convert_form_tag_options(method, options = {})
459
+ def convert_form_tag_options(method, options={})
444
460
  unless @options[:skip_default_ids]
445
461
  options[:name] ||= method
446
462
  options[:id] ||= method
@@ -463,7 +479,10 @@ module BootstrapForm
463
479
  classes << "mr-sm-2"
464
480
  end
465
481
 
466
- unless options.delete(:skip_required)
482
+ case options.delete(:required)
483
+ when true
484
+ classes << "required"
485
+ when nil, :default
467
486
  classes << "required" if required_attribute?(object, name)
468
487
  end
469
488
 
@@ -487,7 +506,7 @@ module BootstrapForm
487
506
  def generate_error(name)
488
507
  if has_inline_error?(name)
489
508
  help_text = get_error_messages(name)
490
- help_klass = 'invalid-feedback'
509
+ help_klass = "invalid-feedback"
491
510
  help_tag = :div
492
511
 
493
512
  content_tag(help_tag, help_text, class: help_klass)
@@ -497,7 +516,7 @@ module BootstrapForm
497
516
  def generate_help(name, help_text)
498
517
  return if help_text == false || has_inline_error?(name)
499
518
 
500
- help_klass ||= 'form-text text-muted'
519
+ help_klass ||= "form-text text-muted"
501
520
  help_text ||= get_help_text_by_i18n_key(name)
502
521
  help_tag ||= :small
503
522
 
@@ -508,7 +527,7 @@ module BootstrapForm
508
527
  object.errors[name].join(", ")
509
528
  end
510
529
 
511
- def inputs_collection(name, collection, value, text, options = {}, &block)
530
+ def inputs_collection(name, collection, value, text, options={})
512
531
  options[:inline] ||= layout_inline?(options[:layout])
513
532
  form_group_builder(name, options) do
514
533
  inputs = ""
@@ -517,7 +536,7 @@ module BootstrapForm
517
536
  input_options = options.merge(label: text.respond_to?(:call) ? text.call(obj) : obj.send(text))
518
537
 
519
538
  input_value = value.respond_to?(:call) ? value.call(obj) : obj.send(value)
520
- if checked = input_options[:checked]
539
+ if (checked = input_options[:checked])
521
540
  input_options[:checked] = checked == input_value ||
522
541
  Array(checked).try(:include?, input_value) ||
523
542
  checked == obj ||
@@ -525,7 +544,7 @@ module BootstrapForm
525
544
  end
526
545
 
527
546
  input_options.delete(:class)
528
- inputs << block.call(name, input_value, input_options.merge(error_message: i == collection.size - 1))
547
+ inputs << yield(name, input_value, input_options.merge(error_message: i == collection.size - 1))
529
548
  end
530
549
 
531
550
  inputs.html_safe
@@ -535,27 +554,29 @@ module BootstrapForm
535
554
  def get_help_text_by_i18n_key(name)
536
555
  if object
537
556
 
538
- if object.class.respond_to?(:model_name)
539
- partial_scope = object.class.model_name.name
540
- else
541
- partial_scope = object.class.name
542
- end
557
+ partial_scope = if object.class.respond_to?(:model_name)
558
+ object.class.model_name.name
559
+ else
560
+ object.class.name
561
+ end
543
562
 
544
563
  underscored_scope = "activerecord.help.#{partial_scope.underscore}"
545
564
  downcased_scope = "activerecord.help.#{partial_scope.downcase}"
546
- # First check for a subkey :html, as it is also accepted by i18n, and the simple check for name would return an hash instead of a string (both with .presence returning true!)
547
- help_text = I18n.t("#{name}.html", scope: underscored_scope, default: '').html_safe.presence
548
- help_text ||= if text = I18n.t("#{name}.html", scope: downcased_scope, default: '').html_safe.presence
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)
549
570
  warn "I18n key '#{downcased_scope}.#{name}' is deprecated, use '#{underscored_scope}.#{name}' instead"
550
571
  text
551
572
  end
552
- help_text ||= I18n.t(name, scope: underscored_scope, default: '').presence
553
- help_text ||= if text = I18n.t(name, scope: downcased_scope, default: '').presence
573
+ help_text ||= I18n.t(name, scope: underscored_scope, default: "").presence
574
+ help_text ||= if (text = I18n.t(name, scope: downcased_scope, default: "").presence)
554
575
  warn "I18n key '#{downcased_scope}.#{name}' is deprecated, use '#{underscored_scope}.#{name}' instead"
555
576
  text
556
577
  end
557
- help_text ||= I18n.t("#{name}_html", scope: underscored_scope, default: '').html_safe.presence
558
- help_text ||= if text = I18n.t("#{name}_html", scope: downcased_scope, default: '').html_safe.presence
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)
559
580
  warn "I18n key '#{downcased_scope}.#{name}' is deprecated, use '#{underscored_scope}.#{name}' instead"
560
581
  text
561
582
  end