comfy_bootstrap_form 4.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +621 -0
  4. data/Rakefile +37 -0
  5. data/app/assets/stylesheets/rails_bootstrap_forms.css +10 -0
  6. data/lib/bootstrap_form.rb +13 -0
  7. data/lib/bootstrap_form/aliasing.rb +35 -0
  8. data/lib/bootstrap_form/form_builder.rb +460 -0
  9. data/lib/bootstrap_form/helper.rb +36 -0
  10. data/lib/bootstrap_form/helpers/bootstrap.rb +94 -0
  11. data/lib/bootstrap_form/helpers/nested_form.rb +33 -0
  12. data/lib/bootstrap_form/version.rb +3 -0
  13. data/lib/comfy_bootstrap_form.rb +1 -0
  14. data/test/bootstrap_checkbox_test.rb +144 -0
  15. data/test/bootstrap_fields_test.rb +152 -0
  16. data/test/bootstrap_form_group_test.rb +313 -0
  17. data/test/bootstrap_form_test.rb +276 -0
  18. data/test/bootstrap_other_components_test.rb +86 -0
  19. data/test/bootstrap_radio_button_test.rb +124 -0
  20. data/test/bootstrap_selects_test.rb +160 -0
  21. data/test/dummy/Gemfile +45 -0
  22. data/test/dummy/Gemfile.lock +120 -0
  23. data/test/dummy/README.rdoc +28 -0
  24. data/test/dummy/Rakefile +10 -0
  25. data/test/dummy/app/assets/javascripts/application.js +16 -0
  26. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  27. data/test/dummy/app/controllers/application_controller.rb +5 -0
  28. data/test/dummy/app/helpers/application_helper.rb +2 -0
  29. data/test/dummy/app/models/address.rb +3 -0
  30. data/test/dummy/app/models/faux_user.rb +9 -0
  31. data/test/dummy/app/models/super_user.rb +2 -0
  32. data/test/dummy/app/models/user.rb +9 -0
  33. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  34. data/test/dummy/bin/bundle +3 -0
  35. data/test/dummy/bin/rails +4 -0
  36. data/test/dummy/bin/rake +4 -0
  37. data/test/dummy/config.ru +4 -0
  38. data/test/dummy/config/application.rb +23 -0
  39. data/test/dummy/config/boot.rb +4 -0
  40. data/test/dummy/config/database.yml +25 -0
  41. data/test/dummy/config/environment.rb +5 -0
  42. data/test/dummy/config/environments/development.rb +29 -0
  43. data/test/dummy/config/environments/production.rb +80 -0
  44. data/test/dummy/config/environments/test.rb +53 -0
  45. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  46. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  47. data/test/dummy/config/initializers/generic_migration.rb +6 -0
  48. data/test/dummy/config/initializers/inflections.rb +16 -0
  49. data/test/dummy/config/initializers/mime_types.rb +5 -0
  50. data/test/dummy/config/initializers/secret_token.rb +12 -0
  51. data/test/dummy/config/initializers/session_store.rb +3 -0
  52. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  53. data/test/dummy/config/locales/en.yml +23 -0
  54. data/test/dummy/config/routes.rb +3 -0
  55. data/test/dummy/db/migrate/20130703191909_create_users.rb +13 -0
  56. data/test/dummy/db/migrate/20130703191937_create_addresses.rb +13 -0
  57. data/test/dummy/db/migrate/20130912171202_add_preferences_to_user.rb +5 -0
  58. data/test/dummy/db/migrate/20140327190145_add_terms_to_user.rb +5 -0
  59. data/test/dummy/db/migrate/20140922133133_add_type_to_users.rb +5 -0
  60. data/test/dummy/db/schema.rb +38 -0
  61. data/test/dummy/db/seeds.rb +7 -0
  62. data/test/dummy/db/test.sqlite3 +0 -0
  63. data/test/dummy/log/test.log +18394 -0
  64. data/test/dummy/public/404.html +58 -0
  65. data/test/dummy/public/422.html +58 -0
  66. data/test/dummy/public/500.html +57 -0
  67. data/test/dummy/public/favicon.ico +0 -0
  68. data/test/dummy/public/robots.txt +5 -0
  69. data/test/dummy/test/fixtures/addresses.yml +15 -0
  70. data/test/dummy/test/fixtures/users.yml +15 -0
  71. data/test/dummy/test/models/address_test.rb +7 -0
  72. data/test/dummy/test/models/user_test.rb +7 -0
  73. data/test/dummy/test/test_helper.rb +15 -0
  74. data/test/special_form_class_models_test.rb +43 -0
  75. data/test/test_helper.rb +86 -0
  76. metadata +309 -0
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'BootstrapForm'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+
24
+
25
+ Bundler::GemHelper.install_tasks
26
+
27
+ require 'rake/testtask'
28
+
29
+ Rake::TestTask.new(:test) do |t|
30
+ t.libs << 'lib'
31
+ t.libs << 'test'
32
+ t.pattern = 'test/**/*_test.rb'
33
+ t.verbose = false
34
+ end
35
+
36
+
37
+ task :default => :test
@@ -0,0 +1,10 @@
1
+ .rails-bootstrap-forms-date-select select,
2
+ .rails-bootstrap-forms-time-select select,
3
+ .rails-bootstrap-forms-datetime-select select {
4
+ display: inline-block;
5
+ width: auto;
6
+ }
7
+
8
+ .rails-bootstrap-forms-error-summary {
9
+ margin-top: 10px;
10
+ }
@@ -0,0 +1,13 @@
1
+ require 'bootstrap_form/form_builder'
2
+ require 'bootstrap_form/helper'
3
+
4
+ module BootstrapForm
5
+ module Rails
6
+ class Engine < ::Rails::Engine
7
+ end
8
+ end
9
+ end
10
+
11
+ ActiveSupport.on_load(:action_view) do
12
+ include BootstrapForm::Helper
13
+ end
@@ -0,0 +1,35 @@
1
+ module BootstrapForm
2
+ # This module implements the old ActiveSupport alias_method_chain feature
3
+ # with a new name, and without the deprecation warnings. In ActiveSupport 5+,
4
+ # this style of patching was deprecated in favor of Module.prepend. But
5
+ # Module.prepend is not present in Ruby 1.9, which we would still like to
6
+ # support. So we continue to use of alias_method_chain, albeit with a
7
+ # different name to avoid collisions.
8
+ module Aliasing
9
+ # This code is copied and pasted from ActiveSupport, but with :bootstrap
10
+ # hardcoded as the feature name, and with the deprecation warning removed.
11
+ def bootstrap_method_alias(target)
12
+ feature = :bootstrap
13
+
14
+ # Strip out punctuation on predicates, bang or writer methods since
15
+ # e.g. target?_without_feature is not a valid method name.
16
+ aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
17
+ yield(aliased_target, punctuation) if block_given?
18
+
19
+ with_method = "#{aliased_target}_with_#{feature}#{punctuation}"
20
+ without_method = "#{aliased_target}_without_#{feature}#{punctuation}"
21
+
22
+ alias_method without_method, target
23
+ alias_method target, with_method
24
+
25
+ case
26
+ when public_method_defined?(without_method)
27
+ public target
28
+ when protected_method_defined?(without_method)
29
+ protected target
30
+ when private_method_defined?(without_method)
31
+ private target
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,460 @@
1
+ require_relative 'aliasing'
2
+ require_relative 'helpers/bootstrap'
3
+
4
+ module BootstrapForm
5
+ class FormBuilder < ActionView::Helpers::FormBuilder
6
+ extend BootstrapForm::Aliasing
7
+ include BootstrapForm::Helpers::Bootstrap
8
+
9
+ attr_reader :layout, :label_col, :control_col, :has_error, :inline_errors, :label_errors, :acts_like_form_tag
10
+
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}
15
+
16
+ DATE_SELECT_HELPERS = %w{date_select time_select datetime_select}
17
+
18
+ delegate :content_tag, :capture, :concat, to: :@template
19
+
20
+ def initialize(object_name, object, template, options)
21
+ @layout = options[:layout]
22
+ @label_col = options[:label_col] || default_label_col
23
+ @control_col = options[:control_col] || default_control_col
24
+ @label_errors = options[:label_errors] || false
25
+ @inline_errors = if options[:inline_errors].nil?
26
+ @label_errors != true
27
+ else
28
+ options[:inline_errors] != false
29
+ end
30
+ @acts_like_form_tag = options[:acts_like_form_tag]
31
+
32
+ super
33
+ end
34
+
35
+ FIELD_HELPERS.each do |method_name|
36
+ with_method_name = "#{method_name}_with_bootstrap"
37
+ without_method_name = "#{method_name}_without_bootstrap"
38
+
39
+ define_method(with_method_name) do |name, options = {}|
40
+ form_group_builder(name, options) do
41
+ prepend_and_append_input(options) do
42
+ send(without_method_name, name, options)
43
+ end
44
+ end
45
+ end
46
+
47
+ bootstrap_method_alias method_name
48
+ end
49
+
50
+ DATE_SELECT_HELPERS.each do |method_name|
51
+ with_method_name = "#{method_name}_with_bootstrap"
52
+ without_method_name = "#{method_name}_without_bootstrap"
53
+
54
+ define_method(with_method_name) do |name, options = {}, html_options = {}|
55
+ form_group_builder(name, options, html_options) do
56
+ content_tag(:div, send(without_method_name, name, options, html_options), class: control_specific_class(method_name))
57
+ end
58
+ end
59
+
60
+ bootstrap_method_alias method_name
61
+ end
62
+
63
+ def file_field_with_bootstrap(name, options = {})
64
+ form_group_builder(name, options.reverse_merge(control_class: nil)) do
65
+ file_field_without_bootstrap(name, options)
66
+ end
67
+ end
68
+
69
+ bootstrap_method_alias :file_field
70
+
71
+ if Gem::Version.new(Rails::VERSION::STRING) >= Gem::Version.new("4.1.0")
72
+ def select_with_bootstrap(method, choices = nil, options = {}, html_options = {}, &block)
73
+ form_group_builder(method, options, html_options) do
74
+ prepend_and_append_input(options) do
75
+ select_without_bootstrap(method, choices, options, html_options, &block)
76
+ end
77
+ end
78
+ end
79
+ else
80
+ def select_with_bootstrap(method, choices, options = {}, html_options = {})
81
+ form_group_builder(method, options, html_options) do
82
+ prepend_and_append_input(options) do
83
+ select_without_bootstrap(method, choices, options, html_options)
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ bootstrap_method_alias :select
90
+
91
+ def collection_select_with_bootstrap(method, collection, value_method, text_method, options = {}, html_options = {})
92
+ form_group_builder(method, options, html_options) do
93
+ collection_select_without_bootstrap(method, collection, value_method, text_method, options, html_options)
94
+ end
95
+ end
96
+
97
+ bootstrap_method_alias :collection_select
98
+
99
+ def grouped_collection_select_with_bootstrap(method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
100
+ form_group_builder(method, options, html_options) do
101
+ grouped_collection_select_without_bootstrap(method, collection, group_method, group_label_method, option_key_method, option_value_method, options, html_options)
102
+ end
103
+ end
104
+
105
+ bootstrap_method_alias :grouped_collection_select
106
+
107
+ def time_zone_select_with_bootstrap(method, priority_zones = nil, options = {}, html_options = {})
108
+ form_group_builder(method, options, html_options) do
109
+ time_zone_select_without_bootstrap(method, priority_zones, options, html_options)
110
+ end
111
+ end
112
+
113
+ bootstrap_method_alias :time_zone_select
114
+
115
+ def check_box_with_bootstrap(name, options = {}, checked_value = "1", unchecked_value = "0", &block)
116
+ options = options.symbolize_keys!
117
+ check_box_options = options.except(:label, :label_class, :help, :inline)
118
+ check_box_options[:class] = ["form-check-input", check_box_options[:class]].compact.join(' ')
119
+
120
+ html = check_box_without_bootstrap(name, check_box_options, checked_value, unchecked_value)
121
+ label_content = block_given? ? capture(&block) : options[:label]
122
+ html.concat(" ").concat(label_content || (object && object.class.human_attribute_name(name)) || name.to_s.humanize)
123
+
124
+ label_name = name
125
+ # label's `for` attribute needs to match checkbox tag's id,
126
+ # IE sanitized value, IE
127
+ # https://github.com/rails/rails/blob/c57e7239a8b82957bcb07534cb7c1a3dcef71864/actionview/lib/action_view/helpers/tags/base.rb#L116-L118
128
+ if options[:multiple]
129
+ label_name =
130
+ "#{name}_#{checked_value.to_s.gsub(/\s/, "_").gsub(/[^-\w]/, "").downcase}"
131
+ end
132
+
133
+ disabled_class = " disabled" if options[:disabled]
134
+ label_class = options[:label_class]
135
+
136
+ if options[:inline]
137
+ label_class = " #{label_class}" if label_class
138
+ label(label_name, html, class: "form-check-inline#{disabled_class}#{label_class}")
139
+ else
140
+ content_tag(:div, class: "form-check#{disabled_class}") do
141
+ label(label_name, html, class: ["form-check-label", label_class].compact.join(" "))
142
+ end
143
+ end
144
+ end
145
+
146
+ bootstrap_method_alias :check_box
147
+
148
+ def radio_button_with_bootstrap(name, value, *args)
149
+ options = args.extract_options!.symbolize_keys!
150
+ args << options.except(:label, :label_class, :help, :inline)
151
+
152
+ html = radio_button_without_bootstrap(name, value, *args) + " " + options[:label]
153
+
154
+ disabled_class = " disabled" if options[:disabled]
155
+ label_class = options[:label_class]
156
+
157
+ if options[:inline]
158
+ label_class = " #{label_class}" if label_class
159
+ label(name, html, class: "radio-inline#{disabled_class}#{label_class}", value: value)
160
+ else
161
+ content_tag(:div, class: "radio#{disabled_class}") do
162
+ label(name, html, value: value, class: label_class)
163
+ end
164
+ end
165
+ end
166
+
167
+ bootstrap_method_alias :radio_button
168
+
169
+ def collection_check_boxes_with_bootstrap(*args)
170
+ html = inputs_collection(*args) do |name, value, options|
171
+ options[:multiple] = true
172
+ check_box(name, options, value, nil)
173
+ end
174
+ hidden_field(args.first,{value: "", multiple: true}).concat(html)
175
+ end
176
+
177
+ bootstrap_method_alias :collection_check_boxes
178
+
179
+ def collection_radio_buttons_with_bootstrap(*args)
180
+ inputs_collection(*args) do |name, value, options|
181
+ radio_button(name, value, options)
182
+ end
183
+ end
184
+
185
+ bootstrap_method_alias :collection_radio_buttons
186
+
187
+ def check_boxes_collection(*args)
188
+ warn "'BootstrapForm#check_boxes_collection' is deprecated, use 'BootstrapForm#collection_check_boxes' instead"
189
+ collection_check_boxes(*args)
190
+ end
191
+
192
+ def radio_buttons_collection(*args)
193
+ warn "'BootstrapForm#radio_buttons_collection' is deprecated, use 'BootstrapForm#collection_radio_buttons' instead"
194
+ collection_radio_buttons(*args)
195
+ end
196
+
197
+ def form_group(*args, &block)
198
+ options = args.extract_options!
199
+ name = args.first
200
+
201
+ options[:class] = ["form-group", options[:class]].compact.join(' ')
202
+ options[:class] << " row" if get_group_layout(options[:layout]) == :horizontal
203
+ options[:class] << " #{error_class}" if has_error?(name)
204
+ options[:class] << " #{feedback_class}" if options[:icon]
205
+
206
+ content_tag(:div, options.except(:id, :label, :help, :icon, :label_col, :control_col, :layout)) do
207
+ label = generate_label(options[:id], name, options[:label], options[:label_col], options[:layout]) if options[:label]
208
+ control = capture(&block).to_s
209
+ control.concat(generate_help(name, options[:help]).to_s)
210
+ control.concat(generate_icon(options[:icon])) if options[:icon]
211
+
212
+ if get_group_layout(options[:layout]) == :horizontal
213
+ control_class = options[:control_col] || control_col
214
+ unless options[:label]
215
+ control_offset = offset_col(options[:label_col] || @label_col)
216
+ control_class = "#{control_class} #{control_offset}"
217
+ end
218
+ control = content_tag(:div, control, class: control_class)
219
+ end
220
+
221
+ concat(label).concat(control)
222
+ end
223
+ end
224
+
225
+ def fields_for_with_bootstrap(record_name, record_object = nil, fields_options = {}, &block)
226
+ fields_options, record_object = record_object, nil if record_object.is_a?(Hash) && record_object.extractable_options?
227
+ fields_options[:layout] ||= options[:layout]
228
+ fields_options[:label_col] = fields_options[:label_col].present? ? "#{fields_options[:label_col]} #{label_class}" : options[:label_col]
229
+ fields_options[:control_col] ||= options[:control_col]
230
+ fields_options[:inline_errors] ||= options[:inline_errors]
231
+ fields_options[:label_errors] ||= options[:label_errors]
232
+ fields_for_without_bootstrap(record_name, record_object, fields_options, &block)
233
+ end
234
+
235
+ bootstrap_method_alias :fields_for
236
+
237
+ private
238
+
239
+ def horizontal?
240
+ layout == :horizontal
241
+ end
242
+
243
+ def get_group_layout(group_layout)
244
+ group_layout || layout
245
+ end
246
+
247
+ def default_label_col
248
+ "col-sm-2"
249
+ end
250
+
251
+ def offset_col(label_col)
252
+ label_col.sub(/^col-(\w+)-(\d)$/, 'col-\1-offset-\2')
253
+ end
254
+
255
+ def default_control_col
256
+ "col-sm-10"
257
+ end
258
+
259
+ def hide_class
260
+ "sr-only" # still accessible for screen readers
261
+ end
262
+
263
+ def control_class
264
+ "form-control"
265
+ end
266
+
267
+ def label_class
268
+ "form-control-label"
269
+ end
270
+
271
+ def error_class
272
+ "has-danger"
273
+ end
274
+
275
+ def feedback_class
276
+ "has-feedback"
277
+ end
278
+
279
+ def control_specific_class(method)
280
+ "rails-bootstrap-forms-#{method.gsub(/_/, "-")}"
281
+ end
282
+
283
+ def has_error?(name)
284
+ object.respond_to?(:errors) && !(name.nil? || object.errors[name].empty?)
285
+ end
286
+
287
+ def required_attribute?(obj, attribute)
288
+
289
+ return false unless obj and attribute
290
+
291
+ target = (obj.class == Class) ? obj : obj.class
292
+
293
+ target_validators = if target.respond_to? :validators_on
294
+ target.validators_on(attribute).map(&:class)
295
+ else
296
+ []
297
+ end
298
+
299
+ has_presence_validator = target_validators.include?(
300
+ ActiveModel::Validations::PresenceValidator)
301
+
302
+ if defined? ActiveRecord::Validations::PresenceValidator
303
+ has_presence_validator |= target_validators.include?(
304
+ ActiveRecord::Validations::PresenceValidator)
305
+ end
306
+
307
+ has_presence_validator
308
+ end
309
+
310
+ def form_group_builder(method, options, html_options = nil)
311
+ options.symbolize_keys!
312
+ html_options.symbolize_keys! if html_options
313
+
314
+ # Add control_class; allow it to be overridden by :control_class option
315
+ css_options = html_options || options
316
+ control_classes = css_options.delete(:control_class) { control_class }
317
+ css_options[:class] = [control_classes, css_options[:class]].compact.join(" ")
318
+ css_options[:class] << " is-invalid" if has_error?(method)
319
+
320
+ options = convert_form_tag_options(method, options) if acts_like_form_tag
321
+
322
+ wrapper_class = css_options.delete(:wrapper_class)
323
+ wrapper_options = css_options.delete(:wrapper)
324
+ help = options.delete(:help)
325
+ icon = options.delete(:icon)
326
+ label_col = options.delete(:label_col)
327
+ control_col = options.delete(:control_col)
328
+ layout = get_group_layout(options.delete(:layout))
329
+ form_group_options = {
330
+ id: options[:id],
331
+ help: help,
332
+ icon: icon,
333
+ label_col: label_col,
334
+ control_col: control_col,
335
+ layout: layout,
336
+ class: wrapper_class
337
+ }
338
+
339
+ if wrapper_options.is_a?(Hash)
340
+ form_group_options.merge!(wrapper_options)
341
+ end
342
+
343
+ unless options.delete(:skip_label)
344
+ if options[:label].is_a?(Hash)
345
+ label_text = options[:label].delete(:text)
346
+ label_class = options[:label].delete(:class)
347
+ options.delete(:label)
348
+ end
349
+ label_class ||= options.delete(:label_class)
350
+ label_class = hide_class if options.delete(:hide_label)
351
+
352
+ if options[:label].is_a?(String)
353
+ label_text ||= options.delete(:label)
354
+ end
355
+
356
+ form_group_options.merge!(label: {
357
+ text: label_text,
358
+ class: label_class,
359
+ skip_required: options.delete(:skip_required)
360
+ })
361
+ end
362
+
363
+ form_group(method, form_group_options) do
364
+ yield
365
+ end
366
+ end
367
+
368
+ def convert_form_tag_options(method, options = {})
369
+ options[:name] ||= method
370
+ options[:id] ||= method
371
+ options
372
+ end
373
+
374
+ def generate_label(id, name, options, custom_label_col, group_layout)
375
+ options[:for] = id if acts_like_form_tag
376
+ classes = [options[:class], label_class]
377
+ classes << (custom_label_col || label_col) if get_group_layout(group_layout) == :horizontal
378
+ unless options.delete(:skip_required)
379
+ classes << "required" if required_attribute?(object, name)
380
+ end
381
+
382
+ options[:class] = classes.compact.join(" ")
383
+
384
+ if label_errors && has_error?(name)
385
+ error_messages = get_error_messages(name)
386
+ label_text = (options[:text] || object.class.human_attribute_name(name)).to_s.concat(" #{error_messages}")
387
+ label(name, label_text, options.except(:text))
388
+ else
389
+ label(name, options[:text], options.except(:text))
390
+ end
391
+
392
+ end
393
+
394
+ def generate_help(name, help_text)
395
+ if has_error?(name) && inline_errors
396
+ help_text = get_error_messages(name)
397
+ help_klass = 'invalid-feedback'
398
+ end
399
+ return if help_text == false
400
+
401
+ help_klass ||= 'form-text text-muted'
402
+ help_text ||= get_help_text_by_i18n_key(name)
403
+
404
+ content_tag(:span, help_text, class: help_klass) if help_text.present?
405
+ end
406
+
407
+ def generate_icon(icon)
408
+ content_tag(:span, "", class: "glyphicon glyphicon-#{icon} form-control-feedback")
409
+ end
410
+
411
+ def get_error_messages(name)
412
+ object.errors[name].join(", ")
413
+ end
414
+
415
+ def inputs_collection(name, collection, value, text, options = {}, &block)
416
+ form_group_builder(name, options) do
417
+ inputs = ""
418
+
419
+ collection.each do |obj|
420
+ input_options = options.merge(label: text.respond_to?(:call) ? text.call(obj) : obj.send(text))
421
+
422
+ input_value = value.respond_to?(:call) ? value.call(obj) : obj.send(value)
423
+ if checked = input_options[:checked]
424
+ input_options[:checked] = checked == input_value ||
425
+ Array(checked).try(:include?, input_value) ||
426
+ checked == obj ||
427
+ Array(checked).try(:include?, obj)
428
+ end
429
+
430
+ input_options.delete(:class)
431
+ inputs << block.call(name, input_value, input_options)
432
+ end
433
+
434
+ inputs.html_safe
435
+ end
436
+ end
437
+
438
+ def get_help_text_by_i18n_key(name)
439
+ if object
440
+
441
+ if object.class.respond_to?(:model_name)
442
+ # ActiveModel::Naming 3.X.X does not support .name; it is supported as of 4.X.X
443
+ partial_scope = object.class.model_name.respond_to?(:name) ? object.class.model_name.name : object.class.model_name
444
+ else
445
+ partial_scope = object.class.name
446
+ end
447
+
448
+ underscored_scope = "activerecord.help.#{partial_scope.underscore}"
449
+ downcased_scope = "activerecord.help.#{partial_scope.downcase}"
450
+ help_text = I18n.t(name, scope: underscored_scope, default: '').presence
451
+ help_text ||= if text = I18n.t(name, scope: downcased_scope, default: '').presence
452
+ warn "I18n key '#{downcased_scope}.#{name}' is deprecated, use '#{underscored_scope}.#{name}' instead"
453
+ text
454
+ end
455
+ help_text
456
+ end
457
+ end
458
+
459
+ end
460
+ end