bootstrap_form 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8742255adf9a08c30983097065574da44048f88e
4
- data.tar.gz: 3b301bdd5e3c144a89151bb8b8f7eafb7a3a31e3
3
+ metadata.gz: 319bdcb130ea16ed9c69b8765dacf04e1666a35c
4
+ data.tar.gz: ce99ec8cf9fd4235eb9bde58e3f88a44df5da0b1
5
5
  SHA512:
6
- metadata.gz: 22c55ab50ba7ca0e6e7e9c5cd836d2461817d7a97036d87d13d52aa1cb62148d5e163fd1c68ca88806b76dd927cd30e1528dcbad8fbca8e502b9de1306875870
7
- data.tar.gz: 2400158a438d1aed212116ccc6dc4c983b3ba0f8e5e02d0125e9971d747fafda44a38af10e2d6a9284eb4cb78bdab6d25330bccb62381c5e52820d1625a3f193
6
+ metadata.gz: 0a44aad58c31502e3cdd179b254ea3b705798223beae55fb996aeb1b84ec42beb85116ee01da593b34a0373c6f6246ed1f0137af964162f15570efb21c281076
7
+ data.tar.gz: ff91c59ec997473c5cf8ecb14d25ae4cc5a45c6406130bff044f3b1a72ea12880ca81e313636a4fc447df82adc3b2a3c15cc590cbce0fa2879184e3ad68d7412
data/README.md CHANGED
@@ -115,7 +115,7 @@ This gem wraps the following Rails form helpers:
115
115
  * time_zone_select
116
116
  * url_field
117
117
  * week_field
118
-
118
+
119
119
  These helpers accept the same options as the standard Rails form helpers, with
120
120
  a few extra options:
121
121
 
@@ -134,6 +134,30 @@ class, which keeps your labels accessible to those using screen readers.
134
134
  <%= f.text_area :comment, hide_label: :true, placeholder: "Leave a comment..." %>
135
135
  ```
136
136
 
137
+ To add custom classes to the field's label:
138
+
139
+ ```erb
140
+ <%= f.text_field :email, label_class: "custom-class" %>
141
+ ```
142
+
143
+ #### Required Fields
144
+
145
+ A label that is associated with a required field is automatically annotated with
146
+ a `required` CSS class. You are free to add any appropriate CSS to style
147
+ required fields as desired. One example would be to automatically add an
148
+ asterisk to the end of the label:
149
+
150
+ ```css
151
+ label.required:after {
152
+ content:" *";
153
+ }
154
+ ```
155
+
156
+ The label `required` class is determined based on the definition of a presence
157
+ validator with the associated model attribute. Presently this is one of:
158
+ ActiveRecord::Validations::PresenceValidator or
159
+ ActiveModel::Validations::PresenceValidator.
160
+
137
161
  ### Help Text
138
162
 
139
163
  To add help text, use the `help` option:
@@ -152,6 +176,9 @@ en:
152
176
  password: "A good password should be at least six characters long"
153
177
  ```
154
178
 
179
+ If your model name has multiple words (like `SuperUser`), the key on the
180
+ translation file should be underscored (`super_user`).
181
+
155
182
  You can override help translations for a particular field by passing the `help`
156
183
  option or turn them off completely by passing `help: false`.
157
184
 
@@ -257,7 +284,7 @@ To display checkboxes and radios inline, pass the `inline: true` option:
257
284
 
258
285
  #### Collections
259
286
 
260
- BootstrapForms also provideshelpers that automatically creates the
287
+ BootstrapForms also provides helpers that automatically creates the
261
288
  `form_group` and the `radio_button`s or `check_box`es for you:
262
289
 
263
290
  ```erb
@@ -316,7 +343,7 @@ buttons.
316
343
  ```
317
344
 
318
345
  You can also use the `primary` helper, which adds `btn btn-primary` to your
319
- submit button **(master branch only)**:
346
+ submit button:
320
347
 
321
348
  ```erb
322
349
  <%= f.primary "Optional Label" %>
@@ -357,6 +384,12 @@ using screen readers.
357
384
  <% end %>
358
385
  ```
359
386
 
387
+ To skip label rendering at all, use `skip_label: true` option.
388
+
389
+ ```erb
390
+ <%= f.password_field :password, skip_label: true %>
391
+ ```
392
+
360
393
  ### Horizontal Forms
361
394
 
362
395
  To use a horizontal-layout form with labels to the left of the control, use the
@@ -393,7 +426,7 @@ The `label_col` and `control_col` css classes can also be changed per control:
393
426
 
394
427
  ### Custom Field Layout
395
428
 
396
- The `layout` can be overriden per field:
429
+ The `layout` can be overridden per field:
397
430
 
398
431
  ```erb
399
432
  <%= bootstrap_form_for(@user, layout: :horizontal) do |f| %>
@@ -430,6 +463,26 @@ You can turn off inline errors for the entire form like this:
430
463
  <% end %>
431
464
  ```
432
465
 
466
+ ### Label Errors
467
+
468
+ You can also display validation errors in the field's label; just turn
469
+ on the `:label_errors` option. Here's an example:
470
+
471
+ ```
472
+ <%= bootstrap_form_for(@user, label_errors: true) do |f| %>
473
+ ...
474
+ <% end %>
475
+ ```
476
+
477
+ By default, turning on `:label_errors` will also turn off
478
+ `:inline_errors`. If you want both turned on, you can do that too:
479
+
480
+ ```
481
+ <%= bootstrap_form_for(@user, label_errors: true, inline_errors: true) do |f| %>
482
+ ...
483
+ <% end %>
484
+ ```
485
+
433
486
  ### Alert Messages
434
487
 
435
488
  To display an error message with an error summary, you can use the
@@ -515,8 +568,10 @@ We love pull requests! Here's a quick guide for contributing:
515
568
 
516
569
  2. Run the existing test suite:
517
570
 
518
- `$ cd test/dummy && bundle exec rake db:create db:migrate RAILS_ENV=test && cd ../../`
519
- `$ bundle exec rake`
571
+ ```
572
+ $ bundle exec rake -f test/dummy/Rakefile db:create db:migrate RAILS_ENV=test
573
+ $ bundle exec rake
574
+ ```
520
575
 
521
576
  3. Add tests for your change.
522
577
 
@@ -4,7 +4,7 @@ module BootstrapForm
4
4
  class FormBuilder < ActionView::Helpers::FormBuilder
5
5
  include BootstrapForm::Helpers::Bootstrap
6
6
 
7
- attr_reader :layout, :label_col, :control_col, :has_error, :inline_errors, :acts_like_form_tag
7
+ attr_reader :layout, :label_col, :control_col, :has_error, :inline_errors, :label_errors, :acts_like_form_tag
8
8
 
9
9
  FIELD_HELPERS = %w{color_field date_field datetime_field datetime_local_field
10
10
  email_field month_field number_field password_field phone_field
@@ -19,7 +19,12 @@ module BootstrapForm
19
19
  @layout = options[:layout]
20
20
  @label_col = options[:label_col] || default_label_col
21
21
  @control_col = options[:control_col] || default_control_col
22
- @inline_errors = options[:inline_errors] != false
22
+ @label_errors = options[:label_errors] || false
23
+ @inline_errors = if options[:inline_errors].nil?
24
+ @label_errors != true
25
+ else
26
+ options[:inline_errors] != false
27
+ end
23
28
  @acts_like_form_tag = options[:acts_like_form_tag]
24
29
 
25
30
  super
@@ -95,19 +100,24 @@ module BootstrapForm
95
100
 
96
101
  def check_box_with_bootstrap(name, options = {}, checked_value = "1", unchecked_value = "0", &block)
97
102
  options = options.symbolize_keys!
103
+ check_box_options = options.except(:label, :label_class, :help, :inline)
98
104
 
99
- html = check_box_without_bootstrap(name, options.except(:label, :help, :inline), checked_value, unchecked_value)
105
+ html = check_box_without_bootstrap(name, check_box_options, checked_value, unchecked_value)
100
106
  label_content = block_given? ? capture(&block) : options[:label]
101
107
  html.concat(" ").concat(label_content || (object && object.class.human_attribute_name(name)) || name.to_s.humanize)
102
108
 
103
109
  label_name = name
104
110
  label_name = "#{name}_#{checked_value}" if options[:multiple]
105
111
 
112
+ disabled_class = " disabled" if options[:disabled]
113
+ label_class = options[:label_class]
114
+
106
115
  if options[:inline]
107
- label(label_name, html, class: "checkbox-inline")
116
+ label_class = " #{label_class}" if label_class
117
+ label(label_name, html, class: "checkbox-inline#{disabled_class}#{label_class}")
108
118
  else
109
- content_tag(:div, class: "checkbox") do
110
- label(label_name, html)
119
+ content_tag(:div, class: "checkbox#{disabled_class}") do
120
+ label(label_name, html, class: label_class)
111
121
  end
112
122
  end
113
123
  end
@@ -116,15 +126,19 @@ module BootstrapForm
116
126
 
117
127
  def radio_button_with_bootstrap(name, value, *args)
118
128
  options = args.extract_options!.symbolize_keys!
119
- args << options.except(:label, :help, :inline)
129
+ args << options.except(:label, :label_class, :help, :inline)
120
130
 
121
131
  html = radio_button_without_bootstrap(name, value, *args) + " " + options[:label]
122
132
 
133
+ disabled_class = " disabled" if options[:disabled]
134
+ label_class = options[:label_class]
135
+
123
136
  if options[:inline]
124
- label(name, html, class: "radio-inline", value: value)
137
+ label_class = " #{label_class}" if label_class
138
+ label(name, html, class: "radio-inline#{disabled_class}#{label_class}", value: value)
125
139
  else
126
- content_tag(:div, class: "radio") do
127
- label(name, html, value: value)
140
+ content_tag(:div, class: "radio#{disabled_class}") do
141
+ label(name, html, value: value, class: label_class)
128
142
  end
129
143
  end
130
144
  end
@@ -164,16 +178,15 @@ module BootstrapForm
164
178
  options[:class] << " #{feedback_class}" if options[:icon]
165
179
 
166
180
  content_tag(:div, options.except(:id, :label, :help, :icon, :label_col, :control_col, :layout)) do
167
- label = generate_label(options[:id], name, options[:label], options[:label_col], options[:layout]) if options[:label]
181
+ label = generate_label(options[:id], name, options[:label], options[:label_col], options[:layout]) if options[:label]
168
182
  control = capture(&block).to_s
169
183
  control.concat(generate_help(name, options[:help]).to_s)
170
184
  control.concat(generate_icon(options[:icon])) if options[:icon]
171
185
 
172
186
  if get_group_layout(options[:layout]) == :horizontal
173
187
  control_class = (options[:control_col] || control_col.clone)
174
-
175
188
  unless options[:label]
176
- control_offset = offset_col(/([0-9]+)$/.match(options[:label_col] || default_label_col))
189
+ control_offset = offset_col(/([0-9]+)$/.match(options[:label_col] || @label_col))
177
190
  control_class.concat(" #{control_offset}")
178
191
  end
179
192
  control = content_tag(:div, control, class: control_class)
@@ -188,6 +201,8 @@ module BootstrapForm
188
201
  fields_options[:layout] ||= options[:layout]
189
202
  fields_options[:label_col] = fields_options[:label_col].present? ? "#{fields_options[:label_col]} #{label_class}" : options[:label_col]
190
203
  fields_options[:control_col] ||= options[:control_col]
204
+ fields_options[:inline_errors] ||= options[:inline_errors]
205
+ fields_options[:label_errors] ||= options[:label_errors]
191
206
  fields_for_without_bootstrap(record_name, record_object, fields_options, &block)
192
207
  end
193
208
 
@@ -243,6 +258,24 @@ module BootstrapForm
243
258
  object.respond_to?(:errors) && !(name.nil? || object.errors[name].empty?)
244
259
  end
245
260
 
261
+ def required_attribute?(obj, attribute)
262
+
263
+ return false unless obj and attribute
264
+
265
+ target = (obj.class == Class) ? obj : obj.class
266
+ target_validators = target.validators_on(attribute).map(&:class)
267
+
268
+ has_presence_validator = target_validators.include?(
269
+ ActiveModel::Validations::PresenceValidator)
270
+
271
+ if defined? ActiveRecord::Validations::PresenceValidator
272
+ has_presence_validator |= target_validators.include?(
273
+ ActiveRecord::Validations::PresenceValidator)
274
+ end
275
+
276
+ has_presence_validator
277
+ end
278
+
246
279
  def form_group_builder(method, options, html_options = nil)
247
280
  options.symbolize_keys!
248
281
  html_options.symbolize_keys! if html_options
@@ -254,10 +287,8 @@ module BootstrapForm
254
287
 
255
288
  options = convert_form_tag_options(method, options) if acts_like_form_tag
256
289
 
257
- label = options.delete(:label)
258
- label_class = hide_class if options.delete(:hide_label)
259
- wrapper_class = options.delete(:wrapper_class)
260
- wrapper_options = options.delete(:wrapper)
290
+ wrapper_class = css_options.delete(:wrapper_class)
291
+ wrapper_options = css_options.delete(:wrapper)
261
292
  help = options.delete(:help)
262
293
  icon = options.delete(:icon)
263
294
  label_col = options.delete(:label_col)
@@ -265,10 +296,6 @@ module BootstrapForm
265
296
  layout = get_group_layout(options.delete(:layout))
266
297
  form_group_options = {
267
298
  id: options[:id],
268
- label: {
269
- text: label,
270
- class: label_class
271
- },
272
299
  help: help,
273
300
  icon: icon,
274
301
  label_col: label_col,
@@ -278,7 +305,17 @@ module BootstrapForm
278
305
  }
279
306
 
280
307
  if wrapper_options.is_a?(Hash)
281
- form_group_options.reverse_merge!(wrapper_options)
308
+ form_group_options.merge!(wrapper_options)
309
+ end
310
+
311
+ unless options.delete(:skip_label)
312
+ label_class = hide_class if options.delete(:hide_label)
313
+ label_class ||= options.delete(:label_class)
314
+
315
+ form_group_options.reverse_merge!(label: {
316
+ text: options.delete(:label),
317
+ class: label_class
318
+ })
282
319
  end
283
320
 
284
321
  form_group(method, form_group_options) do
@@ -296,16 +333,26 @@ module BootstrapForm
296
333
  options[:for] = id if acts_like_form_tag
297
334
  classes = [options[:class], label_class]
298
335
  classes << (custom_label_col || label_col) if get_group_layout(group_layout) == :horizontal
336
+ classes << "required" if required_attribute?(object, name)
337
+
299
338
  options[:class] = classes.compact.join(" ")
300
339
 
301
- label(name, options[:text], options.except(:text))
340
+ if label_errors && has_error?(name)
341
+ error_messages = get_error_messages(name)
342
+ label_text = (options[:text] || object.class.human_attribute_name(name)).to_s.concat(" #{error_messages}")
343
+ label(name, label_text, options.except(:text))
344
+ else
345
+ label(name, options[:text], options.except(:text))
346
+ end
347
+
302
348
  end
303
349
 
304
350
  def generate_help(name, help_text)
305
- help_text = object.errors[name].join(", ") if has_error?(name) && inline_errors
351
+ help_text = get_error_messages(name) if has_error?(name) && inline_errors
306
352
  return if help_text === false
307
353
 
308
- help_text ||= I18n.t(name, scope: "activerecord.help.#{object.class.to_s.downcase}", default: '')
354
+ help_text ||= get_help_text_by_i18n_key(name)
355
+
309
356
  content_tag(:span, help_text, class: 'help-block') if help_text.present?
310
357
  end
311
358
 
@@ -313,26 +360,43 @@ module BootstrapForm
313
360
  content_tag(:span, "", class: "glyphicon glyphicon-#{icon} form-control-feedback")
314
361
  end
315
362
 
363
+ def get_error_messages(name)
364
+ object.errors[name].join(", ")
365
+ end
366
+
316
367
  def inputs_collection(name, collection, value, text, options = {}, &block)
317
368
  form_group_builder(name, options) do
318
369
  inputs = ""
319
370
 
320
371
  collection.each do |obj|
321
- input_options = options.merge(label: obj.send(text))
372
+ input_options = options.merge(label: text.respond_to?(:call) ? text.call(obj) : obj.send(text))
322
373
 
374
+ input_value = value.respond_to?(:call) ? value.call(obj) : obj.send(value)
323
375
  if checked = input_options[:checked]
324
- input_options[:checked] = checked == obj.send(value) ||
325
- checked.try(:include?, obj.send(value)) ||
326
- checked == obj ||
327
- checked.try(:include?, obj)
376
+ input_options[:checked] = checked == input_value ||
377
+ Array(checked).try(:include?, input_value) ||
378
+ checked == obj ||
379
+ Array(checked).try(:include?, obj)
328
380
  end
329
381
 
330
382
  input_options.delete(:class)
331
- inputs << block.call(name, obj.send(value), input_options)
383
+ inputs << block.call(name, input_value, input_options)
332
384
  end
333
385
 
334
386
  inputs.html_safe
335
387
  end
336
388
  end
389
+
390
+ def get_help_text_by_i18n_key(name)
391
+ underscored_scope = "activerecord.help.#{object.class.name.underscore}"
392
+ downcased_scope = "activerecord.help.#{object.class.name.downcase}"
393
+ help_text = I18n.t(name, scope: underscored_scope, default: '').presence
394
+ help_text ||= if text = I18n.t(name, scope: downcased_scope, default: '').presence
395
+ warn "I18n key '#{downcased_scope}.#{name}' is deprecated, use '#{underscored_scope}.#{name}' instead"
396
+ text
397
+ end
398
+
399
+ help_text
400
+ end
337
401
  end
338
402
  end
@@ -1,3 +1,3 @@
1
1
  module BootstrapForm
2
- VERSION = "2.2.0"
2
+ VERSION = "2.3.0"
3
3
  end
@@ -12,6 +12,11 @@ class BootstrapCheckboxTest < ActionView::TestCase
12
12
  assert_equal expected, @builder.check_box(:terms, label: 'I agree to the terms')
13
13
  end
14
14
 
15
+ test "disabled check_box has proper wrapper classes" do
16
+ expected = %{<div class="checkbox disabled"><label for="user_terms"><input disabled="disabled" name="user[terms]" type="hidden" value="0" /><input disabled="disabled" id="user_terms" name="user[terms]" type="checkbox" value="1" /> I agree to the terms</label></div>}
17
+ assert_equal expected, @builder.check_box(:terms, label: 'I agree to the terms', disabled: true)
18
+ end
19
+
15
20
  test "check_box label allows html" do
16
21
  expected = %{<div class="checkbox"><label for="user_terms"><input name="user[terms]" type="hidden" value="0" /><input id="user_terms" name="user[terms]" type="checkbox" value="1" /> I agree to the <a href="#">terms</a></label></div>}
17
22
  assert_equal expected, @builder.check_box(:terms, label: %{I agree to the <a href="#">terms</a>}.html_safe)
@@ -22,6 +27,11 @@ class BootstrapCheckboxTest < ActionView::TestCase
22
27
  assert_equal expected, @builder.check_box(:terms) { "I agree to the terms" }
23
28
  end
24
29
 
30
+ test "check_box accepts a custom label class" do
31
+ expected = %{<div class="checkbox"><label class="btn" for="user_terms"><input name="user[terms]" type="hidden" value="0" /><input id="user_terms" name="user[terms]" type="checkbox" value="1" /> Terms</label></div>}
32
+ assert_equal expected, @builder.check_box(:terms, label_class: 'btn')
33
+ end
34
+
25
35
  test "check_box responds to checked_value and unchecked_value arguments" do
26
36
  expected = %{<div class="checkbox"><label for="user_terms"><input name="user[terms]" type="hidden" value="no" /><input id="user_terms" name="user[terms]" type="checkbox" value="yes" /> I agree to the terms</label></div>}
27
37
  assert_equal expected, @builder.check_box(:terms, {label: 'I agree to the terms'}, 'yes', 'no')
@@ -32,6 +42,16 @@ class BootstrapCheckboxTest < ActionView::TestCase
32
42
  assert_equal expected, @builder.check_box(:terms, label: 'I agree to the terms', inline: true)
33
43
  end
34
44
 
45
+ test "disabled inline check_box" do
46
+ expected = %{<label class="checkbox-inline disabled" for="user_terms"><input disabled="disabled" name="user[terms]" type="hidden" value="0" /><input disabled="disabled" id="user_terms" name="user[terms]" type="checkbox" value="1" /> I agree to the terms</label>}
47
+ assert_equal expected, @builder.check_box(:terms, label: 'I agree to the terms', inline: true, disabled: true)
48
+ end
49
+
50
+ test "inline checkboxes with custom label class" do
51
+ expected = %{<label class="checkbox-inline btn" for="user_terms"><input name="user[terms]" type="hidden" value="0" /><input id="user_terms" name="user[terms]" type="checkbox" value="1" /> Terms</label>}
52
+ assert_equal expected, @builder.check_box(:terms, inline: true, label_class: 'btn')
53
+ end
54
+
35
55
  test 'collection_check_boxes renders the form_group correctly' do
36
56
  collection = [Address.new(id: 1, street: 'Foobar')]
37
57
  expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="control-label" for="user_misc">This is a checkbox collection</label><div class="checkbox"><label for="user_misc_1"><input id="user_misc_1" name="user[misc][]" type="checkbox" value="1" /> Foobar</label></div><span class="help-block">With a help!</span></div>}
@@ -68,4 +88,50 @@ class BootstrapCheckboxTest < ActionView::TestCase
68
88
  assert_equal expected, @builder.collection_check_boxes(:misc, collection, :id, :street, checked: [1, 2])
69
89
  assert_equal expected, @builder.collection_check_boxes(:misc, collection, :id, :street, checked: collection)
70
90
  end
91
+
92
+ test 'collection_check_boxes renders multiple checkboxes with labels defined by Proc :text_method correctly' do
93
+ collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')]
94
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="control-label" for="user_misc">Misc</label><div class="checkbox"><label for="user_misc_1"><input id="user_misc_1" name="user[misc][]" type="checkbox" value="1" /> ooF</label></div><div class="checkbox"><label for="user_misc_2"><input id="user_misc_2" name="user[misc][]" type="checkbox" value="2" /> raB</label></div></div>}
95
+
96
+ assert_equal expected, @builder.collection_check_boxes(:misc, collection, :id, Proc.new { |a| a.street.reverse })
97
+ end
98
+
99
+ test 'collection_check_boxes renders multiple checkboxes with values defined by Proc :value_method correctly' do
100
+ collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')]
101
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="control-label" for="user_misc">Misc</label><div class="checkbox"><label for="user_misc_address_1"><input id="user_misc_address_1" name="user[misc][]" type="checkbox" value="address_1" /> Foo</label></div><div class="checkbox"><label for="user_misc_address_2"><input id="user_misc_address_2" name="user[misc][]" type="checkbox" value="address_2" /> Bar</label></div></div>}
102
+
103
+ assert_equal expected, @builder.collection_check_boxes(:misc, collection, Proc.new { |a| "address_#{a.id}" }, :street)
104
+ end
105
+
106
+ test 'collection_check_boxes renders multiple checkboxes with labels defined by lambda :text_method correctly' do
107
+ collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')]
108
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="control-label" for="user_misc">Misc</label><div class="checkbox"><label for="user_misc_1"><input id="user_misc_1" name="user[misc][]" type="checkbox" value="1" /> ooF</label></div><div class="checkbox"><label for="user_misc_2"><input id="user_misc_2" name="user[misc][]" type="checkbox" value="2" /> raB</label></div></div>}
109
+
110
+ assert_equal expected, @builder.collection_check_boxes(:misc, collection, :id, lambda { |a| a.street.reverse })
111
+ end
112
+
113
+ test 'collection_check_boxes renders multiple checkboxes with values defined by lambda :value_method correctly' do
114
+ collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')]
115
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="control-label" for="user_misc">Misc</label><div class="checkbox"><label for="user_misc_address_1"><input id="user_misc_address_1" name="user[misc][]" type="checkbox" value="address_1" /> Foo</label></div><div class="checkbox"><label for="user_misc_address_2"><input id="user_misc_address_2" name="user[misc][]" type="checkbox" value="address_2" /> Bar</label></div></div>}
116
+
117
+ assert_equal expected, @builder.collection_check_boxes(:misc, collection, lambda { |a| "address_#{a.id}" }, :street)
118
+ end
119
+
120
+ test 'collection_check_boxes renders with checked option correctly with Proc :value_method' do
121
+ collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')]
122
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="control-label" for="user_misc">Misc</label><div class="checkbox"><label for="user_misc_address_1"><input checked="checked" id="user_misc_address_1" name="user[misc][]" type="checkbox" value="address_1" /> Foo</label></div><div class="checkbox"><label for="user_misc_address_2"><input id="user_misc_address_2" name="user[misc][]" type="checkbox" value="address_2" /> Bar</label></div></div>}
123
+
124
+ assert_equal expected, @builder.collection_check_boxes(:misc, collection, Proc.new { |a| "address_#{a.id}" }, :street, checked: "address_1")
125
+ assert_equal expected, @builder.collection_check_boxes(:misc, collection, Proc.new { |a| "address_#{a.id}" }, :street, checked: collection.first)
126
+ end
127
+
128
+ test 'collection_check_boxes renders with multiple checked options correctly with lambda :value_method' do
129
+ collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')]
130
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="control-label" for="user_misc">Misc</label><div class="checkbox"><label for="user_misc_address_1"><input checked="checked" id="user_misc_address_1" name="user[misc][]" type="checkbox" value="address_1" /> Foo</label></div><div class="checkbox"><label for="user_misc_address_2"><input checked="checked" id="user_misc_address_2" name="user[misc][]" type="checkbox" value="address_2" /> Bar</label></div></div>}
131
+
132
+ assert_equal expected, @builder.collection_check_boxes(:misc, collection, lambda { |a| "address_#{a.id}" }, :street, checked: ["address_1", "address_2"])
133
+ assert_equal expected, @builder.collection_check_boxes(:misc, collection, lambda { |a| "address_#{a.id}" }, :street, checked: collection)
134
+ end
135
+
136
+
71
137
  end