simple_form 2.0.2 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of simple_form might be problematic. Click here for more details.

Files changed (31) hide show
  1. data/CHANGELOG.md +33 -0
  2. data/README.md +49 -7
  3. data/lib/generators/simple_form/install_generator.rb +7 -1
  4. data/lib/generators/simple_form/templates/config/initializers/{simple_form.rb.tt → simple_form.rb} +5 -44
  5. data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +45 -0
  6. data/lib/simple_form.rb +6 -0
  7. data/lib/simple_form/action_view_extensions/builder.rb +4 -3
  8. data/lib/simple_form/action_view_extensions/form_helper.rb +7 -9
  9. data/lib/simple_form/components/readonly.rb +1 -1
  10. data/lib/simple_form/form_builder.rb +11 -4
  11. data/lib/simple_form/inputs/base.rb +6 -4
  12. data/lib/simple_form/inputs/boolean_input.rb +13 -4
  13. data/lib/simple_form/version.rb +1 -1
  14. data/lib/simple_form/wrappers/many.rb +5 -1
  15. data/lib/simple_form/wrappers/root.rb +2 -2
  16. data/lib/simple_form/wrappers/single.rb +6 -0
  17. data/test/action_view_extensions/builder_test.rb +11 -5
  18. data/test/action_view_extensions/form_helper_test.rb +37 -3
  19. data/test/components/label_test.rb +7 -0
  20. data/test/form_builder/association_test.rb +7 -1
  21. data/test/form_builder/general_test.rb +25 -0
  22. data/test/form_builder/hint_test.rb +4 -5
  23. data/test/form_builder/wrapper_test.rb +19 -0
  24. data/test/generators/simple_form_generator_test.rb +3 -1
  25. data/test/inputs/boolean_input_test.rb +25 -0
  26. data/test/inputs/disabled_test.rb +51 -11
  27. data/test/inputs/general_test.rb +58 -11
  28. data/test/inputs/readonly_test.rb +51 -11
  29. data/test/support/misc_helpers.rb +24 -0
  30. data/test/support/models.rb +1 -1
  31. metadata +4 -3
data/CHANGELOG.md CHANGED
@@ -1,3 +1,36 @@
1
+ ## 2.0.3
2
+
3
+ ### enhancements
4
+ * Allow to specify custom wrappers for input types.
5
+ ([@nashby](https://github.com/nashby))
6
+ Closes [#636](https://github.com/plataformatec/simple_form/issues/636)
7
+ * Use separate config file to do bootstrap specific configuration.
8
+ ([@nashby](https://github.com/nashby))
9
+
10
+ ### bug fix
11
+ * Allow to specify checked and uncked values for boolean input
12
+ ([@nashby](https://github.com/nashby)).
13
+ Closes [#643](https://github.com/plataformatec/simple_form/issues/643)
14
+ * Allow to add additional classes only for wrapper.
15
+ ([@nashby](https://github.com/nashby)).
16
+ Closes [#629](https://github.com/plataformatec/simple_form/issues/629)
17
+ * Boolean hidden field now respects `:name` attribute when nested.
18
+ ([@amiel](https://github.com/amiel)).
19
+ Closes [#619](https://github.com/plataformatec/simple_form/issues/619)
20
+ * Prevent generation of `class=""`. ([@pkmiec](https://github.com/pkmiec))
21
+ * Fix namespace html propagation to single wrapper of `label` and `input`
22
+ * Association creates blank select if `:collection` is `nil`.
23
+ ([@nashby](https://github.com/nashby)).
24
+ Closes [#595](https://github.com/plataformatec/simple_form/issues/595)
25
+ * Fix readonly attribute check. ([@retoo](https://github.com/retoo))
26
+ * Fix error when `collection_check_boxes` used with `form_for` instead of `simple_form_for`.
27
+ ([@RohanM](https://github.com/RohanM))
28
+ * Ensure ActionView::Base.field_error_proc is preserved when exceptions occur within
29
+ `with_simple_form_field_error_proc`.
30
+ ([@jim](https://github.com/jim))
31
+ * Handle array of strings in `:checked` option.
32
+ ([@nashby](https://github.com/nashby))
33
+
1
34
  ## 2.0.2
2
35
 
3
36
  ### enhancements
data/README.md CHANGED
@@ -53,7 +53,7 @@ For more information see the generator output, our
53
53
  are invoked to create a complete html input for you, which by default contains label, hints, errors
54
54
  and the input itself. It does not aim to create a lot of different logic from the default Rails
55
55
  form helpers, as they do a great work by themselves. Instead, **SimpleForm** acts as a DSL and just
56
- maps your input type (retrieved from the column definition in the database) to an specific helper method.
56
+ maps your input type (retrieved from the column definition in the database) to a specific helper method.
57
57
 
58
58
  To start using **SimpleForm** you just have to use the helper it provides:
59
59
 
@@ -69,13 +69,14 @@ This will generate an entire form with labels for user name and password as well
69
69
  by default when you render the form with invalid data (after submitting for example).
70
70
 
71
71
  You can overwrite the default label by passing it to the input method. You can also add a hint or
72
- even a placeholder:
72
+ even a placeholder. For boolean inputs, you can add an inline label as well:
73
73
 
74
74
  ```erb
75
75
  <%= simple_form_for @user do |f| %>
76
76
  <%= f.input :username, :label => 'Your username please' %>
77
77
  <%= f.input :password, :hint => 'No special characters.' %>
78
78
  <%= f.input :email, :placeholder => 'user@domain.com' %>
79
+ <%= f.input :remember_me, :inline_label => 'Yes, remember me' %>
79
80
  <%= f.button :submit %>
80
81
  <% end %>
81
82
  ```
@@ -129,8 +130,11 @@ any html attribute to that wrapper as well using the `:wrapper_html` option, lik
129
130
  <% end %>
130
131
  ```
131
132
 
132
- By default all inputs are required, which means an * is prepended to the label, but you can disable
133
- it in any input you want:
133
+ Required fields are marked with an * prepended to their labels.
134
+
135
+ By default all inputs are required. When the form object has `presence` validations attached to its fields, **SimpleForm** tells required and optional fields apart. For performance reasons, this detection is skipped on validations that make use of conditional options, such as `:if` and `:unless`.
136
+
137
+ And of course, the `required` property of any input can be overwritten as needed:
134
138
 
135
139
  ```erb
136
140
  <%= simple_form_for @user do |f| %>
@@ -314,6 +318,12 @@ the collection by hand, all together with the prompt:
314
318
  f.association :company, :collection => Company.active.all(:order => 'name'), :prompt => "Choose a Company"
315
319
  ```
316
320
 
321
+ In case you want to declare different labels and values:
322
+
323
+ ```ruby
324
+ f.association :company, :label_method => :company_name, :value_method => :id, :include_blank => false
325
+ ```
326
+
317
327
  ### Buttons
318
328
 
319
329
  All web forms need buttons, right? **SimpleForm** wraps them in the DSL, acting like a proxy:
@@ -463,7 +473,7 @@ instance, if you want to wrap date/time/datetime in a div, you can do:
463
473
  # app/inputs/date_time_input.rb
464
474
  class DateTimeInput < SimpleForm::Inputs::DateTimeInput
465
475
  def input
466
- "<div>#{super}</div>".html_safe
476
+ template.content_tag(:div, super)
467
477
  end
468
478
  end
469
479
  ```
@@ -567,7 +577,7 @@ en:
567
577
  ```
568
578
 
569
579
  **SimpleForm** will always look for a default attribute translation under the "defaults" key if no
570
- specific is found inside the model key.Note that this syntax is different from 1.x. To migrate to
580
+ specific is found inside the model key. Note that this syntax is different from 1.x. To migrate to
571
581
  the new syntax, just move "labels.#{attribute}" to "labels.defaults.#{attribute}".
572
582
 
573
583
  In addition, **SimpleForm** will fallback to default human_attribute_name from Rails when no other
@@ -592,7 +602,7 @@ en:
592
602
  user:
593
603
  gender:
594
604
  male: 'Male'
595
- female: "Female'
605
+ female: 'Female'
596
606
  ```
597
607
 
598
608
  You can also use the `defaults` key as you would do with labels, hints and placeholders. It is
@@ -614,6 +624,37 @@ There are other options that can be configured through I18n API, such as require
614
624
  Be sure to check our locale file or the one copied to your application after you run
615
625
  `rails generate simple_form:install`.
616
626
 
627
+ It should be noted that translations for labels, hints and placeholders for a namespaced model, e.g.
628
+ `Admin::User`, should be placed under `admin_user`, not under `admin/user`. This is different from
629
+ how translations for namespaced model and attribute names are defined:
630
+
631
+ ```yaml
632
+ en:
633
+ activerecord:
634
+ models:
635
+ admin/user: User
636
+ attributes:
637
+ admin/user:
638
+ name: Name
639
+ ```
640
+
641
+ They should be placed under `admin/user`. Form labels, hints and placeholders for those attributes,
642
+ though, should be placed under `admin_user`:
643
+
644
+ ```yaml
645
+ en:
646
+ simple_form:
647
+ labels:
648
+ admin_user:
649
+ name: Name
650
+ ```
651
+
652
+ This difference exists because **SimpleForm** relies on `object_name` provided by Rails'
653
+ FormBuilder to determine the translation path for a given object instead of `i18n_key` from the
654
+ object itself. Thus, similarly, if a form for an `Admin::User` object is defined by calling
655
+ `simple_form_for @admin_user, :as => :some_user`, **SimpleForm** will look for translations
656
+ under `some_user` instead of `admin_user`.
657
+
617
658
  ## Configuration
618
659
 
619
660
  **SimpleForm** has several configuration options. You can read and change them in the initializer
@@ -812,6 +853,7 @@ https://github.com/plataformatec/simple_form/issues
812
853
  * José Valim (https://github.com/josevalim)
813
854
  * Carlos Antonio da Silva (https://github.com/carlosantoniodasilva)
814
855
  * Rafael Mendonça França (https://github.com/rafaelfranca)
856
+ * Vasiliy Ermolovich (https://github.com/nashby)
815
857
 
816
858
  ## License
817
859
 
@@ -14,7 +14,13 @@ module SimpleForm
14
14
  end
15
15
 
16
16
  def copy_config
17
- directory 'config'
17
+ template "config/initializers/simple_form.rb"
18
+
19
+ if options[:bootstrap]
20
+ template "config/initializers/simple_form_bootstrap.rb"
21
+ end
22
+
23
+ directory 'config/locales'
18
24
  end
19
25
 
20
26
  def copy_scaffold_template
@@ -44,53 +44,10 @@ SimpleForm.setup do |config|
44
44
  b.use :hint, :wrap_with => { :tag => :span, :class => :hint }
45
45
  b.use :error, :wrap_with => { :tag => :span, :class => :error }
46
46
  end
47
- <% if options.bootstrap? %>
48
- config.wrappers :bootstrap, :tag => 'div', :class => 'control-group', :error_class => 'error' do |b|
49
- b.use :html5
50
- b.use :placeholder
51
- b.use :label
52
- b.wrapper :tag => 'div', :class => 'controls' do |ba|
53
- ba.use :input
54
- ba.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
55
- ba.use :hint, :wrap_with => { :tag => 'p', :class => 'help-block' }
56
- end
57
- end
58
-
59
- config.wrappers :prepend, :tag => 'div', :class => "control-group", :error_class => 'error' do |b|
60
- b.use :html5
61
- b.use :placeholder
62
- b.use :label
63
- b.wrapper :tag => 'div', :class => 'controls' do |input|
64
- input.wrapper :tag => 'div', :class => 'input-prepend' do |prepend|
65
- prepend.use :input
66
- end
67
- input.use :hint, :wrap_with => { :tag => 'span', :class => 'help-block' }
68
- input.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
69
- end
70
- end
71
47
 
72
- config.wrappers :append, :tag => 'div', :class => "control-group", :error_class => 'error' do |b|
73
- b.use :html5
74
- b.use :placeholder
75
- b.use :label
76
- b.wrapper :tag => 'div', :class => 'controls' do |input|
77
- input.wrapper :tag => 'div', :class => 'input-append' do |append|
78
- append.use :input
79
- end
80
- input.use :hint, :wrap_with => { :tag => 'span', :class => 'help-block' }
81
- input.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
82
- end
83
- end
84
-
85
- # Wrappers for forms and inputs using the Twitter Bootstrap toolkit.
86
- # Check the Bootstrap docs (http://twitter.github.com/bootstrap)
87
- # to learn about the different styles for forms and inputs,
88
- # buttons and other elements.
89
- config.default_wrapper = :bootstrap
90
- <% else %>
91
48
  # The default wrapper to be used by the FormBuilder.
92
49
  config.default_wrapper = :default
93
- <% end %>
50
+
94
51
  # Define the way to render check boxes / radio buttons with labels.
95
52
  # Defaults to :nested for bootstrap config.
96
53
  # :inline => input + label
@@ -161,6 +118,10 @@ SimpleForm.setup do |config|
161
118
  # matches the regexp as value.
162
119
  # config.input_mappings = { /count/ => :integer }
163
120
 
121
+ # Custom wrappers for input types. This should be a hash containing an input
122
+ # type as key and the wrapper that will be used for all inputs with specified type.
123
+ # config.wrapper_mappings = { :string => :prepend }
124
+
164
125
  # Default priority for time_zone inputs.
165
126
  # config.time_zone_priority = nil
166
127
 
@@ -0,0 +1,45 @@
1
+ # Use this setup block to configure all options available in SimpleForm.
2
+ SimpleForm.setup do |config|
3
+ config.wrappers :bootstrap, :tag => 'div', :class => 'control-group', :error_class => 'error' do |b|
4
+ b.use :html5
5
+ b.use :placeholder
6
+ b.use :label
7
+ b.wrapper :tag => 'div', :class => 'controls' do |ba|
8
+ ba.use :input
9
+ ba.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
10
+ ba.use :hint, :wrap_with => { :tag => 'p', :class => 'help-block' }
11
+ end
12
+ end
13
+
14
+ config.wrappers :prepend, :tag => 'div', :class => "control-group", :error_class => 'error' do |b|
15
+ b.use :html5
16
+ b.use :placeholder
17
+ b.use :label
18
+ b.wrapper :tag => 'div', :class => 'controls' do |input|
19
+ input.wrapper :tag => 'div', :class => 'input-prepend' do |prepend|
20
+ prepend.use :input
21
+ end
22
+ input.use :hint, :wrap_with => { :tag => 'span', :class => 'help-block' }
23
+ input.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
24
+ end
25
+ end
26
+
27
+ config.wrappers :append, :tag => 'div', :class => "control-group", :error_class => 'error' do |b|
28
+ b.use :html5
29
+ b.use :placeholder
30
+ b.use :label
31
+ b.wrapper :tag => 'div', :class => 'controls' do |input|
32
+ input.wrapper :tag => 'div', :class => 'input-append' do |append|
33
+ append.use :input
34
+ end
35
+ input.use :hint, :wrap_with => { :tag => 'span', :class => 'help-block' }
36
+ input.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
37
+ end
38
+ end
39
+
40
+ # Wrappers for forms and inputs using the Twitter Bootstrap toolkit.
41
+ # Check the Bootstrap docs (http://twitter.github.com/bootstrap)
42
+ # to learn about the different styles for forms and inputs,
43
+ # buttons and other elements.
44
+ config.default_wrapper = :bootstrap
45
+ end
data/lib/simple_form.rb CHANGED
@@ -95,6 +95,12 @@ module SimpleForm
95
95
  mattr_accessor :input_mappings
96
96
  @@input_mappings = nil
97
97
 
98
+ # Custom wrappers for input types. This should be a hash containing an input
99
+ # type as key and the wrapper that will be used for all inputs with specified type.
100
+ # e.g { :string => :string_wrapper, :boolean => :boolean_wrapper }
101
+ mattr_accessor :wrapper_mappings
102
+ @@wrapper_mappings = nil
103
+
98
104
  # Default priority for time_zone inputs.
99
105
  mattr_accessor :time_zone_priority
100
106
  @@time_zone_priority = nil
@@ -153,7 +153,8 @@ module SimpleForm
153
153
  #
154
154
  # * collection_wrapper_tag => the tag to wrap the entire collection.
155
155
  #
156
- # * collection_wrapper_class => the CSS class to use for collection_wrapper_tag
156
+ # * collection_wrapper_class => the CSS class to use for collection_wrapper_tag. This option
157
+ # is ignored if the :collection_wrapper_tag option is blank.
157
158
  #
158
159
  # * item_wrapper_tag => the tag to wrap each item in the collection.
159
160
  #
@@ -177,7 +178,7 @@ module SimpleForm
177
178
 
178
179
  # Append a hidden field to make sure something will be sent back to the
179
180
  # server if all checkboxes are unchecked.
180
- hidden = template.hidden_field_tag("#{object_name}[#{attribute}][]", "", :id => nil)
181
+ hidden = @template.hidden_field_tag("#{object_name}[#{attribute}][]", "", :id => nil)
181
182
 
182
183
  wrap_rendered_collection(rendered_collection + hidden, options)
183
184
  end
@@ -223,7 +224,7 @@ module SimpleForm
223
224
  accept = if current_option.respond_to?(:call)
224
225
  current_option.call(item)
225
226
  else
226
- Array(current_option).include?(value)
227
+ Array(current_option).map(&:to_s).include?(value.to_s)
227
228
  end
228
229
 
229
230
  if accept
@@ -9,10 +9,6 @@ module SimpleForm
9
9
  # end
10
10
  #
11
11
  module FormHelper
12
- # based on what is done in formtastic
13
- # http://github.com/justinfrench/formtastic/blob/master/lib/formtastic.rb#L1706
14
- @@default_field_error_proc = nil
15
-
16
12
  # Override the default ActiveRecordHelper behaviour of wrapping the input.
17
13
  # This gets taken care of semantically by adding an error class to the wrapper tag
18
14
  # containing the input.
@@ -46,11 +42,13 @@ module SimpleForm
46
42
  private
47
43
 
48
44
  def with_simple_form_field_error_proc
49
- @@default_field_error_proc = ::ActionView::Base.field_error_proc
50
- ::ActionView::Base.field_error_proc = FIELD_ERROR_PROC
51
- result = yield
52
- ::ActionView::Base.field_error_proc = @@default_field_error_proc
53
- result
45
+ default_field_error_proc = ::ActionView::Base.field_error_proc
46
+ begin
47
+ ::ActionView::Base.field_error_proc = FIELD_ERROR_PROC
48
+ yield
49
+ ensure
50
+ ::ActionView::Base.field_error_proc = default_field_error_proc
51
+ end
54
52
  end
55
53
 
56
54
  def simple_form_css_class(record, options)
@@ -15,7 +15,7 @@ module SimpleForm
15
15
  def readonly_attribute?
16
16
  object.class.respond_to?(:readonly_attributes) &&
17
17
  object.persisted? &&
18
- object.class.readonly_attributes.include?(attribute_name)
18
+ object.class.readonly_attributes.include?(attribute_name.to_s)
19
19
  end
20
20
  end
21
21
  end
@@ -104,15 +104,16 @@ module SimpleForm
104
104
  #
105
105
  def input(attribute_name, options={}, &block)
106
106
  options = @defaults.deep_dup.deep_merge(options) if @defaults
107
+ input = find_input(attribute_name, options, &block)
107
108
 
108
109
  chosen =
109
- if name = options[:wrapper]
110
+ if name = options[:wrapper] || find_wrapper_mapping(input.input_type)
110
111
  name.respond_to?(:render) ? name : SimpleForm.wrapper(name)
111
112
  else
112
113
  wrapper
113
114
  end
114
115
 
115
- chosen.render find_input(attribute_name, options, &block)
116
+ chosen.render input
116
117
  end
117
118
  alias :attribute :input
118
119
 
@@ -174,13 +175,15 @@ module SimpleForm
174
175
  raise "Association #{association.inspect} not found" unless reflection
175
176
 
176
177
  options[:as] ||= :select
177
- options[:collection] ||= reflection.klass.all(reflection.options.slice(:conditions, :order))
178
+ options[:collection] ||= options.fetch(:collection) {
179
+ reflection.klass.all(reflection.options.slice(:conditions, :order))
180
+ }
178
181
 
179
182
  attribute = case reflection.macro
180
183
  when :belongs_to
181
184
  (reflection.respond_to?(:options) && reflection.options[:foreign_key]) || :"#{reflection.name}_id"
182
185
  when :has_one
183
- raise ":has_one associations are not supported by f.association"
186
+ raise ArgumentError, ":has_one associations are not supported by f.association"
184
187
  else
185
188
  if options[:as] == :select
186
189
  html_options = options[:input_html] ||= {}
@@ -442,6 +445,10 @@ module SimpleForm
442
445
  end
443
446
  end
444
447
 
448
+ def find_wrapper_mapping(input_type)
449
+ SimpleForm.wrapper_mappings && SimpleForm.wrapper_mappings[input_type]
450
+ end
451
+
445
452
  # If cache_discovery is enabled, use the class level cache that persists
446
453
  # between requests, otherwise use the instance one.
447
454
  def discovery_cache #:nodoc:
@@ -60,9 +60,7 @@ module SimpleForm
60
60
  # Notice that html_options_for receives a reference to input_html_classes.
61
61
  # This means that classes added dynamically to input_html_classes will
62
62
  # still propagate to input_html_options.
63
- @html_classes = SimpleForm.additional_classes_for(:input) {
64
- [input_type, required_class, readonly_class, disabled_class].compact
65
- }
63
+ @html_classes = SimpleForm.additional_classes_for(:input) { additional_classes }
66
64
 
67
65
  @input_html_classes = @html_classes.dup
68
66
  @input_html_options = html_options_for(:input, input_html_classes).tap do |o|
@@ -80,6 +78,10 @@ module SimpleForm
80
78
  options
81
79
  end
82
80
 
81
+ def additional_classes
82
+ @additional_classes ||= [input_type, required_class, readonly_class, disabled_class].compact
83
+ end
84
+
83
85
  private
84
86
 
85
87
  def add_size!
@@ -119,7 +121,7 @@ module SimpleForm
119
121
  html_options = options[:"#{namespace}_html"]
120
122
  html_options = html_options ? html_options.dup : {}
121
123
  css_classes << html_options[:class] if html_options.key?(:class)
122
- html_options[:class] = css_classes
124
+ html_options[:class] = css_classes unless css_classes.empty?
123
125
  html_options
124
126
  end
125
127
 
@@ -34,8 +34,8 @@ module SimpleForm
34
34
  # reuse the method for nested boolean style, but with no unchecked value,
35
35
  # which won't generate the hidden checkbox. This is the default functionality
36
36
  # in Rails > 3.2.1, and is backported in SimpleForm AV helpers.
37
- def build_check_box(unchecked_value='0')
38
- @builder.check_box(attribute_name, input_html_options, '1', unchecked_value)
37
+ def build_check_box(unchecked_value = unchecked_value)
38
+ @builder.check_box(attribute_name, input_html_options, checked_value, unchecked_value)
39
39
  end
40
40
 
41
41
  # Build a checkbox without generating the hidden field. See
@@ -49,8 +49,9 @@ module SimpleForm
49
49
  # we need the hidden field to be *outside* the label (otherwise it
50
50
  # generates invalid html - html5 only).
51
51
  def build_hidden_field_for_checkbox
52
- @builder.hidden_field(attribute_name, :value => '0', :id => nil,
53
- :disabled => input_html_options[:disabled])
52
+ @builder.hidden_field(attribute_name, :value => unchecked_value, :id => nil,
53
+ :disabled => input_html_options[:disabled],
54
+ :name => input_html_options[:name])
54
55
  end
55
56
 
56
57
  def inline_label
@@ -64,6 +65,14 @@ module SimpleForm
64
65
  def required_by_default?
65
66
  false
66
67
  end
68
+
69
+ def checked_value
70
+ options.fetch(:checked_value, '1')
71
+ end
72
+
73
+ def unchecked_value
74
+ options.fetch(:unchecked_value, '0')
75
+ end
67
76
  end
68
77
  end
69
78
  end
@@ -1,3 +1,3 @@
1
1
  module SimpleForm
2
- VERSION = "2.0.2".freeze
2
+ VERSION = "2.0.3".freeze
3
3
  end
@@ -56,11 +56,15 @@ module SimpleForm
56
56
  return content unless tag
57
57
 
58
58
  klass = html_classes(input, options)
59
- opts = options[:"#{namespace}_html"] || {}
59
+ opts = html_options(options)
60
60
  opts[:class] = (klass << opts[:class]).join(' ').strip unless klass.empty?
61
61
  input.template.content_tag(tag, content, opts)
62
62
  end
63
63
 
64
+ def html_options(options)
65
+ options[:"#{namespace}_html"] || {}
66
+ end
67
+
64
68
  def html_classes(input, options)
65
69
  @defaults[:class].dup
66
70
  end
@@ -24,10 +24,10 @@ module SimpleForm
24
24
 
25
25
  def html_classes(input, options)
26
26
  css = options[:wrapper_class] ? Array.wrap(options[:wrapper_class]) : @defaults[:class]
27
- css += SimpleForm.additional_classes_for(:wrapper) { input.html_classes }
27
+ css += SimpleForm.additional_classes_for(:wrapper) { input.additional_classes }
28
28
  css << (options[:wrapper_error_class] || @defaults[:error_class]) if input.has_errors?
29
29
  css << (options[:wrapper_hint_class] || @defaults[:hint_class]) if input.has_hint?
30
- css
30
+ css.compact
31
31
  end
32
32
  end
33
33
  end
@@ -13,6 +13,12 @@ module SimpleForm
13
13
  wrap(input, options, content) if content
14
14
  end
15
15
  end
16
+
17
+ private
18
+
19
+ def html_options(options)
20
+ [:label, :input].include?(namespace) ? {} : super
21
+ end
16
22
  end
17
23
  end
18
24
  end
@@ -63,7 +63,7 @@ class BuilderTest < ActionView::TestCase
63
63
  assert_select 'form input[type=radio][value=true][checked=checked]'
64
64
  assert_no_select 'form input[type=radio][value=false][checked=checked]'
65
65
  end
66
-
66
+
67
67
  test 'collection radio accepts checked item which has a value of false' do
68
68
  with_collection_radio_buttons @user, :active, [[1, true], [0, false]], :last, :first, :checked => false
69
69
  assert_no_select 'form input[type=radio][value=true][checked=checked]'
@@ -302,7 +302,6 @@ class BuilderTest < ActionView::TestCase
302
302
  assert_no_select 'form input[type=checkbox][value=2][checked=checked]'
303
303
  end
304
304
 
305
-
306
305
  test 'collection check box accepts selected values as :checked option' do
307
306
  collection = (1..3).map{|i| [i, "Tag #{i}"] }
308
307
  with_collection_check_boxes @user, :tag_ids, collection, :first, :last, :checked => [1, 3]
@@ -312,6 +311,15 @@ class BuilderTest < ActionView::TestCase
312
311
  assert_no_select 'form input[type=checkbox][value=2][checked=checked]'
313
312
  end
314
313
 
314
+ test 'collection check boxes accepts selected string values as :checked option' do
315
+ collection = (1..3).map{|i| [i, "Category #{i}"] }
316
+ with_collection_check_boxes :user, :category_ids, collection, :first, :last, :checked => ['1', '3']
317
+
318
+ assert_select 'input[type=checkbox][value=1][checked=checked]'
319
+ assert_select 'input[type=checkbox][value=3][checked=checked]'
320
+ assert_no_select 'input[type=checkbox][value=2][checked=checked]'
321
+ end
322
+
315
323
  test 'collection check box accepts a single checked value' do
316
324
  collection = (1..3).map{|i| [i, "Tag #{i}"] }
317
325
  with_collection_check_boxes @user, :tag_ids, collection, :first, :last, :checked => 3
@@ -537,10 +545,8 @@ class BuilderTest < ActionView::TestCase
537
545
  end
538
546
 
539
547
  test 'fields for with a hash like model yeilds an instance of FormBuilder' do
540
- @hash_backed_author = HashBackedAuthor.new
541
-
542
548
  with_concat_form_for(:user) do |f|
543
- f.simple_fields_for(:author, @hash_backed_author) do |author|
549
+ f.simple_fields_for(:author, HashBackedAuthor.new) do |author|
544
550
  assert author.instance_of?(SimpleForm::FormBuilder)
545
551
  author.input :name
546
552
  end
@@ -92,13 +92,47 @@ class FormHelperTest < ActionView::TestCase
92
92
  end
93
93
 
94
94
  test 'fields for with a hash like model yeilds an instance of FormBuilder' do
95
- @hash_backed_author = HashBackedAuthor.new
96
-
97
- with_concat_fields_for(:author, @hash_backed_author) do |f|
95
+ with_concat_fields_for(:author, HashBackedAuthor.new) do |f|
98
96
  assert f.instance_of?(SimpleForm::FormBuilder)
99
97
  f.input :name
100
98
  end
101
99
 
102
100
  assert_select "input[name='author[name]'][value='hash backed author']"
103
101
  end
102
+
103
+ test 'custom error proc is not destructive' do
104
+ swap_field_error_proc do
105
+ result = nil
106
+ simple_form_for :user do |f|
107
+ result = simple_fields_for 'address' do
108
+ 'hello'
109
+ end
110
+ end
111
+
112
+ assert_equal 'hello', result
113
+ end
114
+ end
115
+
116
+ test 'custom error proc survives an exception' do
117
+ swap_field_error_proc do
118
+ begin
119
+ simple_form_for :user do |f|
120
+ simple_fields_for 'address' do
121
+ raise 'an exception'
122
+ end
123
+ end
124
+ rescue StandardError
125
+ end
126
+ end
127
+ end
128
+
129
+ private
130
+
131
+ def swap_field_error_proc(expected_error_proc = lambda {})
132
+ swap ActionView::Base, :field_error_proc => expected_error_proc do
133
+ yield
134
+
135
+ assert_equal expected_error_proc, ActionView::Base.field_error_proc
136
+ end
137
+ end
104
138
  end
@@ -181,6 +181,13 @@ class IsolatedLabelTest < ActionView::TestCase
181
181
  end
182
182
  end
183
183
 
184
+ test 'label should not generate empty css class' do
185
+ swap SimpleForm, :generate_additional_classes_for => [:wrapper, :input] do
186
+ with_label_for @user, :name, :string
187
+ assert_no_select 'label[class]'
188
+ end
189
+ end
190
+
184
191
  test 'label should obtain required from ActiveModel::Validations when it is included' do
185
192
  with_label_for @validating_user, :name, :string
186
193
  assert_select 'label.required'
@@ -79,6 +79,12 @@ class AssociationTest < ActionView::TestCase
79
79
  assert_select 'form select option[value=3]', 'Company 3'
80
80
  end
81
81
 
82
+ test 'builder creates blank select if collection is nil' do
83
+ with_association_for @user, :company, :collection => nil
84
+ assert_select 'form select.select#user_company_id'
85
+ assert_no_select 'form select option[value=1]', 'Company 1'
86
+ end
87
+
82
88
  test 'builder allows collection radio for belongs_to associations' do
83
89
  with_association_for @user, :company, :as => :radio_buttons
84
90
  assert_select 'form input.radio_buttons#user_company_id_1'
@@ -114,7 +120,7 @@ class AssociationTest < ActionView::TestCase
114
120
 
115
121
  # ASSOCIATIONS - has_*
116
122
  test 'builder does not allow has_one associations' do
117
- assert_raise RuntimeError do
123
+ assert_raise ArgumentError do
118
124
  with_association_for @user, :first_company, :as => :radio_buttons
119
125
  end
120
126
  end
@@ -46,6 +46,15 @@ class FormBuilderTest < ActionView::TestCase
46
46
  end
47
47
  end
48
48
 
49
+ test 'builder should allow to add additional classes only for wrapper' do
50
+ swap SimpleForm, :generate_additional_classes_for => [:wrapper] do
51
+ with_form_for @user, :post_count
52
+ assert_no_select "form input#user_post_count.string"
53
+ assert_no_select "form label#user_post_count.string"
54
+ assert_select "form div.input.string"
55
+ end
56
+ end
57
+
49
58
  test 'builder should allow adding custom input mappings for integer input types' do
50
59
  swap SimpleForm, :input_mappings => { /lock_version/ => :hidden } do
51
60
  with_form_for @user, :lock_version
@@ -202,6 +211,22 @@ class FormBuilderTest < ActionView::TestCase
202
211
  assert_select 'form input#my_input.my_input.string'
203
212
  end
204
213
 
214
+ test 'builder should not propagate input options to wrapper with custom wrapper' do
215
+ swap_wrapper :default, self.custom_wrapper_with_wrapped_input do
216
+ with_form_for @user, :name, :input_html => { :class => 'my_input' }
217
+ assert_no_select 'form div.input.my_input'
218
+ assert_select 'form input.my_input.string'
219
+ end
220
+ end
221
+
222
+ test 'builder should not propagate label options to wrapper with custom wrapper' do
223
+ swap_wrapper :default, self.custom_wrapper_with_wrapped_label do
224
+ with_form_for @user, :name, :label_html => { :class => 'my_label' }
225
+ assert_no_select 'form div.label.my_label'
226
+ assert_select 'form label.my_label.string'
227
+ end
228
+ end
229
+
205
230
  test 'builder should generate a input with label' do
206
231
  with_form_for @user, :name
207
232
  assert_select 'form label.string[for=user_name]', /Name/
@@ -41,12 +41,11 @@ class HintTest < ActionView::TestCase
41
41
  with_hint_for @user, :name, :hint => 'Yay!', :id => 'hint', :class => 'yay'
42
42
  assert_select 'span#hint.hint.yay'
43
43
  end
44
-
44
+
45
45
  test 'hint should be output as html_safe' do
46
46
  with_hint_for @user, :name, :hint => '<b>Bold</b> and not...'
47
- assert_select 'span.hint', 'Bold and not...'
47
+ assert_select 'span.hint', 'Bold and not...'
48
48
  end
49
-
50
49
 
51
50
  # Without attribute name
52
51
 
@@ -110,7 +109,7 @@ class HintTest < ActionView::TestCase
110
109
  assert_select 'span.hint', /My company!/
111
110
  end
112
111
  end
113
-
112
+
114
113
  test 'hint should output translations as html_safe' do
115
114
  store_translations(:en, :simple_form => { :hints => { :user => {
116
115
  :edit => { :name => '<b>This is bold</b> and this is not...' }
@@ -119,7 +118,7 @@ class HintTest < ActionView::TestCase
119
118
  assert_select 'span.hint', 'This is bold and this is not...'
120
119
  end
121
120
  end
122
-
121
+
123
122
 
124
123
  # No object
125
124
 
@@ -75,6 +75,15 @@ class WrapperTest < ActionView::TestCase
75
75
  end
76
76
  end
77
77
 
78
+ test 'wrapper should not generate empty css class' do
79
+ swap SimpleForm, :generate_additional_classes_for => [:input, :label] do
80
+ swap_wrapper :default, custom_wrapper_without_class do
81
+ with_form_for @user, :name
82
+ assert_no_select 'div#custom_wrapper_without_class[class]'
83
+ end
84
+ end
85
+ end
86
+
78
87
  # Custom wrapper test
79
88
 
80
89
  test 'custom wrappers works' do
@@ -159,4 +168,14 @@ class WrapperTest < ActionView::TestCase
159
168
  with_form_for @user, :name, :wrapper => :not_found
160
169
  end
161
170
  end
171
+
172
+ test 'use wrapper for specified in config mapping' do
173
+ swap_wrapper :another do
174
+ swap SimpleForm, :wrapper_mappings => { :string => :another } do
175
+ with_form_for @user, :name
176
+ assert_select "section.custom_wrapper div.another_wrapper label"
177
+ assert_select "section.custom_wrapper div.another_wrapper input.string"
178
+ end
179
+ end
180
+ end
162
181
  end
@@ -19,7 +19,9 @@ class SimpleFormGeneratorTest < Rails::Generators::TestCase
19
19
 
20
20
  test 'generates the simple_form initializer with the bootstrap wrappers' do
21
21
  run_generator %w(--bootstrap)
22
- assert_file 'config/initializers/simple_form.rb', /config\.wrappers :bootstrap/,
22
+ assert_file 'config/initializers/simple_form.rb',
23
+ /config\.default_wrapper = :default/, /config\.boolean_style = :nested/
24
+ assert_file 'config/initializers/simple_form_bootstrap.rb', /config\.wrappers :bootstrap/,
23
25
  /config\.default_wrapper = :bootstrap/
24
26
  end
25
27
 
@@ -14,6 +14,24 @@ class BooleanInputTest < ActionView::TestCase
14
14
  assert_no_select 'label'
15
15
  end
16
16
 
17
+ test 'input uses custom checked value' do
18
+ @user.action = 'on'
19
+ with_input_for @user, :action, :boolean, :checked_value => 'on', :unchecked_value => 'off'
20
+ assert_select 'input[type=checkbox][value=on][checked=checked]'
21
+ end
22
+
23
+ test 'input uses custom unchecked value' do
24
+ @user.action = 'off'
25
+ with_input_for @user, :action, :boolean, :checked_value => 'on', :unchecked_value => 'off'
26
+ assert_select 'input[type=checkbox][value=on]'
27
+ assert_no_select 'input[checked=checked][value=on]'
28
+ end
29
+
30
+ test 'input generates hidden input with custom unchecked value' do
31
+ with_input_for @user, :action, :boolean, :checked_value => 'on', :unchecked_value => 'off'
32
+ assert_select 'input[type=hidden][value=off]'
33
+ end
34
+
17
35
  test 'input uses inline boolean style by default' do
18
36
  with_input_for @user, :active, :boolean
19
37
  assert_select 'input.boolean + label.boolean.optional'
@@ -84,6 +102,13 @@ class BooleanInputTest < ActionView::TestCase
84
102
  end
85
103
  end
86
104
 
105
+ test 'input with nested style allows customizing input_html' do
106
+ swap SimpleForm, :boolean_style => :nested do
107
+ with_input_for @user, :active, :boolean, :input_html => { :name => 'active_user' }
108
+ assert_select "input[type=hidden][name=active_user] + label.boolean > input.boolean[name=active_user]"
109
+ end
110
+ end
111
+
87
112
  test 'input boolean works using :input only in wrapper config (no label_input)' do
88
113
  swap_wrapper do
89
114
  with_input_for @user, :active, :boolean
@@ -1,38 +1,78 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class DisabledTest < ActionView::TestCase
4
- test 'input should generate disabled elements based on the disabled option' do
4
+ test 'string input should be disabled when disabled option is true' do
5
5
  with_input_for @user, :name, :string, :disabled => true
6
6
  assert_select 'input.string.disabled[disabled]'
7
+ end
8
+
9
+ test 'text input should be disabled when disabled option is true' do
7
10
  with_input_for @user, :description, :text, :disabled => true
8
11
  assert_select 'textarea.text.disabled[disabled]'
12
+ end
13
+
14
+ test 'numeric input should be disabled when disabled option is true' do
9
15
  with_input_for @user, :age, :integer, :disabled => true
10
16
  assert_select 'input.integer.disabled[disabled]'
17
+ end
18
+
19
+ test 'date input should be disabled when disabled option is true' do
11
20
  with_input_for @user, :born_at, :date, :disabled => true
12
21
  assert_select 'select.date.disabled[disabled]'
22
+ end
23
+
24
+ test 'datetime input should be disabled when disabled option is true' do
13
25
  with_input_for @user, :created_at, :datetime, :disabled => true
14
26
  assert_select 'select.datetime.disabled[disabled]'
27
+ end
15
28
 
29
+ test 'string input should not be disabled when disabled option is false' do
16
30
  with_input_for @user, :name, :string, :disabled => false
17
- assert_select 'input.string:not(.disabled[disabled])'
31
+ assert_no_select 'input.string.disabled[disabled]'
32
+ end
33
+
34
+ test 'text input should not be disabled when disabled option is false' do
18
35
  with_input_for @user, :description, :text, :disabled => false
19
- assert_select 'textarea.text:not(.disabled[disabled])'
36
+ assert_no_select 'textarea.text.disabled[disabled]'
37
+ end
38
+
39
+ test 'numeric input should not be disabled when disabled option is false' do
20
40
  with_input_for @user, :age, :integer, :disabled => false
21
- assert_select 'input.integer:not(.disabled[disabled])'
41
+ assert_no_select 'input.integer.disabled[disabled]'
42
+ end
43
+
44
+ test 'date input should not be disabled when disabled option is false' do
22
45
  with_input_for @user, :born_at, :date, :disabled => false
23
- assert_select 'select.date:not(.disabled[disabled])'
46
+ assert_no_select 'select.date.disabled[disabled]'
47
+ end
48
+
49
+ test 'datetime input should not be disabled when disabled option is false' do
24
50
  with_input_for @user, :created_at, :datetime, :disabled => false
25
- assert_select 'select.datetime:not(.disabled[disabled])'
51
+ assert_no_select 'select.datetime.disabled[disabled]'
52
+ end
26
53
 
54
+ test 'string input should not be disabled when disabled option is not present' do
27
55
  with_input_for @user, :name, :string
28
- assert_select 'input.string:not(.disabled[disabled])'
56
+ assert_no_select 'input.string.disabled[disabled]'
57
+ end
58
+
59
+ test 'text input should not be disabled when disabled option is not present' do
29
60
  with_input_for @user, :description, :text
30
- assert_select 'textarea.text:not(.disabled[disabled])'
61
+ assert_no_select 'textarea.text.disabled[disabled]'
62
+ end
63
+
64
+ test 'numeric input should not be disabled when disabled option is not present' do
31
65
  with_input_for @user, :age, :integer
32
- assert_select 'input.integer:not(.disabled[disabled])'
66
+ assert_no_select 'input.integer.disabled[disabled]'
67
+ end
68
+
69
+ test 'date input should not be disabled when disabled option is not present' do
33
70
  with_input_for @user, :born_at, :date
34
- assert_select 'select.date:not(.disabled[disabled])'
71
+ assert_no_select 'select.date.disabled[disabled]'
72
+ end
73
+
74
+ test 'datetime input should not be disabled when disabled option is not present' do
35
75
  with_input_for @user, :created_at, :datetime
36
- assert_select 'select.datetime:not(.disabled[disabled])'
76
+ assert_no_select 'select.datetime.disabled[disabled]'
37
77
  end
38
78
  end
@@ -15,39 +15,79 @@ class InputTest < ActionView::TestCase
15
15
  assert_select 'select.datetime'
16
16
  end
17
17
 
18
- test 'input should generate autofocus attribute based on the autofocus option' do
18
+ test 'string input should generate autofocus attribute when autofocus option is true' do
19
19
  with_input_for @user, :name, :string, :autofocus => true
20
20
  assert_select 'input.string[autofocus]'
21
+ end
22
+
23
+ test 'text input should generate autofocus attribute when autofocus option is true' do
21
24
  with_input_for @user, :description, :text, :autofocus => true
22
25
  assert_select 'textarea.text[autofocus]'
26
+ end
27
+
28
+ test 'numeric input should generate autofocus attribute when autofocus option is true' do
23
29
  with_input_for @user, :age, :integer, :autofocus => true
24
30
  assert_select 'input.integer[autofocus]'
31
+ end
32
+
33
+ test 'date input should generate autofocus attribute when autofocus option is true' do
25
34
  with_input_for @user, :born_at, :date, :autofocus => true
26
35
  assert_select 'select.date[autofocus]'
36
+ end
37
+
38
+ test 'datetime input should generate autofocus attribute when autofocus option is true' do
27
39
  with_input_for @user, :created_at, :datetime, :autofocus => true
28
40
  assert_select 'select.datetime[autofocus]'
41
+ end
29
42
 
43
+ test 'string input should generate autofocus attribute when autofocus option is false' do
30
44
  with_input_for @user, :name, :string, :autofocus => false
31
- assert_select 'input.string:not([autofocus])'
45
+ assert_no_select 'input.string[autofocus]'
46
+ end
47
+
48
+ test 'text input should generate autofocus attribute when autofocus option is false' do
32
49
  with_input_for @user, :description, :text, :autofocus => false
33
- assert_select 'textarea.text:not([autofocus])'
50
+ assert_no_select 'textarea.text[autofocus]'
51
+ end
52
+
53
+ test 'numeric input should generate autofocus attribute when autofocus option is false' do
34
54
  with_input_for @user, :age, :integer, :autofocus => false
35
- assert_select 'input.integer:not([autofocus])'
55
+ assert_no_select 'input.integer[autofocus]'
56
+ end
57
+
58
+ test 'date input should generate autofocus attribute when autofocus option is false' do
36
59
  with_input_for @user, :born_at, :date, :autofocus => false
37
- assert_select 'select.date:not([autofocus])'
60
+ assert_no_select 'select.date[autofocus]'
61
+ end
62
+
63
+ test 'datetime input should generate autofocus attribute when autofocus option is false' do
38
64
  with_input_for @user, :created_at, :datetime, :autofocus => false
39
- assert_select 'select.datetime:not([autofocus])'
65
+ assert_no_select 'select.datetime[autofocus]'
66
+ end
40
67
 
68
+ test 'string input should generate autofocus attribute when autofocus option is not present' do
41
69
  with_input_for @user, :name, :string
42
- assert_select 'input.string:not([autofocus])'
70
+ assert_no_select 'input.string[autofocus]'
71
+ end
72
+
73
+ test 'text input should generate autofocus attribute when autofocus option is not present' do
43
74
  with_input_for @user, :description, :text
44
- assert_select 'textarea.text:not([autofocus])'
75
+ assert_no_select 'textarea.text[autofocus]'
76
+ end
77
+
78
+ test 'numeric input should generate autofocus attribute when autofocus option is not present' do
45
79
  with_input_for @user, :age, :integer
46
- assert_select 'input.integer:not([autofocus])'
80
+ assert_no_select 'input.integer[autofocus]'
81
+ end
82
+
83
+ test 'date input should generate autofocus attribute when autofocus option is not present' do
47
84
  with_input_for @user, :born_at, :date
48
- assert_select 'select.date:not([autofocus])'
85
+ assert_no_select 'select.date[autofocus]'
86
+ end
87
+
88
+ test 'datetime input should generate autofocus attribute when autofocus option is not present' do
49
89
  with_input_for @user, :created_at, :datetime
50
- assert_select 'select.datetime:not([autofocus])'
90
+ assert_no_select 'select.datetime[autofocus]'
51
91
  end
52
92
 
53
93
  # With no object
@@ -66,4 +106,11 @@ class InputTest < ActionView::TestCase
66
106
  with_input_for :project, :name, :select, :collection => ['Jose', 'Carlos']
67
107
  assert_select 'select.select#project_name'
68
108
  end
109
+
110
+ test 'input should not generate empty css class' do
111
+ swap SimpleForm, :generate_additional_classes_for => [:wrapper, :label] do
112
+ with_input_for :project, :name, :string
113
+ assert_no_select 'input#project_name[class]'
114
+ end
115
+ end
69
116
  end
@@ -1,39 +1,79 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class ReadonlyTest < ActionView::TestCase
4
- test 'input should generate readonly elements based on the readonly option' do
4
+ test 'string input should generate readonly elements when readonly option is true' do
5
5
  with_input_for @user, :name, :string, :readonly => true
6
6
  assert_select 'input.string.readonly[readonly]'
7
+ end
8
+
9
+ test 'text input should generate readonly elements when readonly option is true' do
7
10
  with_input_for @user, :description, :text, :readonly => true
8
11
  assert_select 'textarea.text.readonly[readonly]'
12
+ end
13
+
14
+ test 'numeric input should generate readonly elements when readonly option is true' do
9
15
  with_input_for @user, :age, :integer, :readonly => true
10
16
  assert_select 'input.integer.readonly[readonly]'
17
+ end
18
+
19
+ test 'date input should generate readonly elements when readonly option is true' do
11
20
  with_input_for @user, :born_at, :date, :readonly => true
12
21
  assert_select 'select.date.readonly[readonly]'
22
+ end
23
+
24
+ test 'datetime input should generate readonly elements when readonly option is true' do
13
25
  with_input_for @user, :created_at, :datetime, :readonly => true
14
26
  assert_select 'select.datetime.readonly[readonly]'
27
+ end
15
28
 
29
+ test 'string input should generate readonly elements when readonly option is false' do
16
30
  with_input_for @user, :name, :string, :readonly => false
17
- assert_select 'input.string:not(.readonly[readonly])'
31
+ assert_no_select 'input.string.readonly[readonly]'
32
+ end
33
+
34
+ test 'text input should generate readonly elements when readonly option is false' do
18
35
  with_input_for @user, :description, :text, :readonly => false
19
- assert_select 'textarea.text:not(.readonly[readonly])'
36
+ assert_no_select 'textarea.text.readonly[readonly]'
37
+ end
38
+
39
+ test 'numeric input should generate readonly elements when readonly option is false' do
20
40
  with_input_for @user, :age, :integer, :readonly => false
21
- assert_select 'input.integer:not(.readonly[readonly])'
41
+ assert_no_select 'input.integer.readonly[readonly]'
42
+ end
43
+
44
+ test 'date input should generate readonly elements when readonly option is false' do
22
45
  with_input_for @user, :born_at, :date, :readonly => false
23
- assert_select 'select.date:not(.readonly[readonly])'
46
+ assert_no_select 'select.date.readonly[readonly]'
47
+ end
48
+
49
+ test 'datetime input should generate readonly elements when readonly option is false' do
24
50
  with_input_for @user, :created_at, :datetime, :readonly => false
25
- assert_select 'select.datetime:not(.readonly[readonly])'
51
+ assert_no_select 'select.datetime.readonly[readonly]'
52
+ end
26
53
 
54
+ test 'string input should generate readonly elements when readonly option is not present' do
27
55
  with_input_for @user, :name, :string
28
- assert_select 'input.string:not(.readonly[readonly])'
56
+ assert_no_select 'input.string.readonly[readonly]'
57
+ end
58
+
59
+ test 'text input should generate readonly elements when readonly option is not present' do
29
60
  with_input_for @user, :description, :text
30
- assert_select 'textarea.text:not(.readonly[readonly])'
61
+ assert_no_select 'textarea.text.readonly[readonly]'
62
+ end
63
+
64
+ test 'numeric input should generate readonly elements when readonly option is not present' do
31
65
  with_input_for @user, :age, :integer
32
- assert_select 'input.integer:not(.readonly[readonly])'
66
+ assert_no_select 'input.integer.readonly[readonly]'
67
+ end
68
+
69
+ test 'date input should generate readonly elements when readonly option is not present' do
33
70
  with_input_for @user, :born_at, :date
34
- assert_select 'select.date:not(.readonly[readonly])'
71
+ assert_no_select 'select.date.readonly[readonly]'
72
+ end
73
+
74
+ test 'datetime input should generate readonly elements when readonly option is not present' do
35
75
  with_input_for @user, :created_at, :datetime
36
- assert_select 'select.datetime:not(.readonly[readonly])'
76
+ assert_no_select 'select.datetime.readonly[readonly]'
37
77
  end
38
78
 
39
79
  test 'input should generate readonly attribute when the field is readonly and the object is persisted' do
@@ -46,6 +46,24 @@ module MiscHelpers
46
46
  end
47
47
  end
48
48
 
49
+ def custom_wrapper_with_wrapped_input
50
+ SimpleForm.build :tag => :div, :class => "custom_wrapper" do |b|
51
+ b.wrapper :tag => :div, :class => 'elem' do |component|
52
+ component.use :label
53
+ component.use :input, :wrap_with => { :tag => :div, :class => 'input' }
54
+ end
55
+ end
56
+ end
57
+
58
+ def custom_wrapper_with_wrapped_label
59
+ SimpleForm.build :tag => :div, :class => "custom_wrapper" do |b|
60
+ b.wrapper :tag => :div, :class => 'elem' do |component|
61
+ component.use :label, :wrap_with => { :tag => :div, :class => 'label' }
62
+ component.use :input
63
+ end
64
+ end
65
+ end
66
+
49
67
  def custom_wrapper_without_top_level
50
68
  SimpleForm.build :tag => false, :class => 'custom_wrapper_without_top_level' do |b|
51
69
  b.use :label_input
@@ -54,6 +72,12 @@ module MiscHelpers
54
72
  end
55
73
  end
56
74
 
75
+ def custom_wrapper_without_class
76
+ SimpleForm.build :tag => :div, :wrapper_html => { :id => 'custom_wrapper_without_class' } do |b|
77
+ b.use :label_input
78
+ end
79
+ end
80
+
57
81
  def custom_wrapper_with_label_html_option
58
82
  SimpleForm.build :tag => :div, :class => "custom_wrapper", :label_html => { :class => 'extra-label-class' } do |b|
59
83
  b.use :label_input
@@ -130,7 +130,7 @@ class User
130
130
  end
131
131
 
132
132
  def self.readonly_attributes
133
- [:credit_card]
133
+ ["credit_card"]
134
134
  end
135
135
  end
136
136
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_form
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 2.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2012-04-30 00:00:00.000000000 Z
14
+ date: 2012-09-27 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: activemodel
@@ -58,7 +58,8 @@ files:
58
58
  - lib/generators/simple_form/templates/_form.html.erb
59
59
  - lib/generators/simple_form/templates/_form.html.haml
60
60
  - lib/generators/simple_form/templates/_form.html.slim
61
- - lib/generators/simple_form/templates/config/initializers/simple_form.rb.tt
61
+ - lib/generators/simple_form/templates/config/initializers/simple_form.rb
62
+ - lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb
62
63
  - lib/generators/simple_form/templates/config/locales/simple_form.en.yml
63
64
  - lib/generators/simple_form/templates/README
64
65
  - lib/generators/simple_form/USAGE