bootstrap_form 2.2.0 → 2.3.0

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