bootstrap_form 4.0.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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