simple_form 1.5.2 → 2.0.0.rc

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.
Files changed (105) hide show
  1. data/CHANGELOG.md +224 -0
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +817 -0
  4. data/lib/generators/simple_form/install_generator.rb +15 -1
  5. data/lib/generators/simple_form/templates/README +12 -0
  6. data/lib/generators/simple_form/templates/config/initializers/simple_form.rb.tt +173 -0
  7. data/lib/simple_form.rb +109 -43
  8. data/lib/simple_form/action_view_extensions/builder.rb +158 -53
  9. data/lib/simple_form/action_view_extensions/form_helper.rb +29 -22
  10. data/lib/simple_form/components.rb +11 -1
  11. data/lib/simple_form/components/errors.rb +6 -24
  12. data/lib/simple_form/components/hints.rb +7 -21
  13. data/lib/simple_form/components/html5.rb +26 -0
  14. data/lib/simple_form/components/labels.rb +15 -13
  15. data/lib/simple_form/components/maxlength.rb +41 -0
  16. data/lib/simple_form/components/min_max.rb +49 -0
  17. data/lib/simple_form/components/pattern.rb +34 -0
  18. data/lib/simple_form/components/placeholders.rb +5 -17
  19. data/lib/simple_form/components/readonly.rb +22 -0
  20. data/lib/simple_form/core_ext/hash.rb +16 -0
  21. data/lib/simple_form/error_notification.rb +8 -1
  22. data/lib/simple_form/form_builder.rb +86 -22
  23. data/lib/simple_form/helpers.rb +7 -4
  24. data/lib/simple_form/helpers/autofocus.rb +11 -0
  25. data/lib/simple_form/helpers/disabled.rb +15 -0
  26. data/lib/simple_form/helpers/readonly.rb +15 -0
  27. data/lib/simple_form/helpers/required.rb +7 -10
  28. data/lib/simple_form/helpers/validators.rb +4 -4
  29. data/lib/simple_form/inputs.rb +17 -13
  30. data/lib/simple_form/inputs/base.rb +50 -81
  31. data/lib/simple_form/inputs/boolean_input.rb +43 -4
  32. data/lib/simple_form/inputs/collection_check_boxes_input.rb +21 -0
  33. data/lib/simple_form/inputs/collection_input.rb +27 -13
  34. data/lib/simple_form/inputs/collection_radio_buttons_input.rb +69 -0
  35. data/lib/simple_form/inputs/collection_select_input.rb +14 -0
  36. data/lib/simple_form/inputs/date_time_input.rb +2 -2
  37. data/lib/simple_form/inputs/grouped_collection_select_input.rb +41 -0
  38. data/lib/simple_form/inputs/hidden_input.rb +3 -6
  39. data/lib/simple_form/inputs/numeric_input.rb +3 -51
  40. data/lib/simple_form/inputs/password_input.rb +1 -2
  41. data/lib/simple_form/inputs/priority_input.rb +2 -2
  42. data/lib/simple_form/inputs/range_input.rb +1 -3
  43. data/lib/simple_form/inputs/string_input.rb +6 -8
  44. data/lib/simple_form/inputs/text_input.rb +1 -2
  45. data/lib/simple_form/version.rb +1 -1
  46. data/lib/simple_form/wrappers.rb +8 -0
  47. data/lib/simple_form/wrappers/builder.rb +75 -0
  48. data/lib/simple_form/wrappers/many.rb +68 -0
  49. data/lib/simple_form/wrappers/root.rb +34 -0
  50. data/lib/simple_form/wrappers/single.rb +18 -0
  51. data/test/action_view_extensions/builder_test.rb +195 -100
  52. data/test/action_view_extensions/form_helper_test.rb +24 -2
  53. data/test/components/label_test.rb +20 -5
  54. data/test/form_builder/association_test.rb +167 -0
  55. data/test/form_builder/button_test.rb +28 -0
  56. data/test/{error_notification_test.rb → form_builder/error_notification_test.rb} +2 -1
  57. data/test/form_builder/error_test.rb +101 -0
  58. data/test/form_builder/general_test.rb +348 -0
  59. data/test/form_builder/hint_test.rb +115 -0
  60. data/test/form_builder/input_field_test.rb +51 -0
  61. data/test/form_builder/label_test.rb +51 -0
  62. data/test/form_builder/wrapper_test.rb +140 -0
  63. data/test/generators/simple_form_generator_test.rb +32 -0
  64. data/test/inputs/boolean_input_test.rb +91 -0
  65. data/test/inputs/collection_check_boxes_input_test.rb +224 -0
  66. data/test/inputs/collection_radio_buttons_input_test.rb +326 -0
  67. data/test/inputs/collection_select_input_test.rb +241 -0
  68. data/test/inputs/datetime_input_test.rb +85 -0
  69. data/test/inputs/disabled_test.rb +38 -0
  70. data/test/inputs/discovery_test.rb +61 -0
  71. data/test/inputs/file_input_test.rb +16 -0
  72. data/test/inputs/general_test.rb +69 -0
  73. data/test/inputs/grouped_collection_select_input_test.rb +109 -0
  74. data/test/inputs/hidden_input_test.rb +30 -0
  75. data/test/inputs/numeric_input_test.rb +167 -0
  76. data/test/inputs/priority_input_test.rb +43 -0
  77. data/test/inputs/readonly_test.rb +61 -0
  78. data/test/inputs/required_test.rb +113 -0
  79. data/test/inputs/string_input_test.rb +140 -0
  80. data/test/inputs/text_input_test.rb +24 -0
  81. data/test/{discovery_inputs.rb → support/discovery_inputs.rb} +0 -0
  82. data/test/support/misc_helpers.rb +48 -6
  83. data/test/support/mock_controller.rb +2 -2
  84. data/test/support/models.rb +20 -5
  85. data/test/test_helper.rb +5 -8
  86. metadata +123 -98
  87. data/.gitignore +0 -3
  88. data/.gitmodules +0 -3
  89. data/.travis.yml +0 -15
  90. data/CHANGELOG.rdoc +0 -159
  91. data/Gemfile +0 -9
  92. data/README.rdoc +0 -466
  93. data/Rakefile +0 -27
  94. data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +0 -93
  95. data/lib/simple_form/components/wrapper.rb +0 -38
  96. data/lib/simple_form/helpers/has_errors.rb +0 -15
  97. data/lib/simple_form/helpers/maxlength.rb +0 -24
  98. data/lib/simple_form/helpers/pattern.rb +0 -28
  99. data/simple_form.gemspec +0 -25
  100. data/test/components/error_test.rb +0 -56
  101. data/test/components/hint_test.rb +0 -74
  102. data/test/components/wrapper_test.rb +0 -63
  103. data/test/custom_components.rb +0 -7
  104. data/test/form_builder_test.rb +0 -930
  105. data/test/inputs_test.rb +0 -995
@@ -1,20 +1,18 @@
1
1
  module SimpleForm
2
2
  module Inputs
3
3
  class StringInput < Base
4
- enable :placeholder
4
+ enable :placeholder, :maxlength, :pattern
5
5
 
6
6
  def input
7
- input_html_options[:type] ||= input_type if SimpleForm.html5 && !string?
8
- add_maxlength!
9
- add_pattern!
7
+ unless string?
8
+ input_html_classes.unshift("string")
9
+ input_html_options[:type] ||= input_type if html5?
10
+ end
11
+
10
12
  add_size!
11
13
  @builder.text_field(attribute_name, input_html_options)
12
14
  end
13
15
 
14
- def input_html_classes
15
- string? ? super : super.unshift("string")
16
- end
17
-
18
16
  private
19
17
 
20
18
  def string?
@@ -1,10 +1,9 @@
1
1
  module SimpleForm
2
2
  module Inputs
3
3
  class TextInput < Base
4
- enable :placeholder
4
+ enable :placeholder, :maxlength
5
5
 
6
6
  def input
7
- add_maxlength!
8
7
  @builder.text_area(attribute_name, input_html_options)
9
8
  end
10
9
  end
@@ -1,3 +1,3 @@
1
1
  module SimpleForm
2
- VERSION = "1.5.2".freeze
2
+ VERSION = "2.0.0.rc".freeze
3
3
  end
@@ -0,0 +1,8 @@
1
+ module SimpleForm
2
+ module Wrappers
3
+ autoload :Builder, 'simple_form/wrappers/builder'
4
+ autoload :Many, 'simple_form/wrappers/many'
5
+ autoload :Root, 'simple_form/wrappers/root'
6
+ autoload :Single, 'simple_form/wrappers/single'
7
+ end
8
+ end
@@ -0,0 +1,75 @@
1
+ module SimpleForm
2
+ module Wrappers
3
+ # Provides the builder syntax for components. The builder provides
4
+ # only one method (called `use`) and it allows the following invocations:
5
+ #
6
+ # config.wrappers do |b|
7
+ # # Use a single component
8
+ # b.use :placeholder
9
+ #
10
+ # # Use a component with specific wrapper options
11
+ # b.use :error, :tag => "span", :class => "error"
12
+ #
13
+ # # Use a set of components by wrapping them in a tag+class.
14
+ # b.use :tag => "div", :class => "another" do |ba|
15
+ # ba.use :label
16
+ # ba.use :input
17
+ # end
18
+ #
19
+ # # Use a set of components by wrapping them in a tag+class.
20
+ # # This wrapper is identified by :label_input, which means it can
21
+ # # be turned off on demand with `f.input :name, :label_input => false`
22
+ # b.use :label_input, :tag => "div", :class => "another" do |ba|
23
+ # ba.use :label
24
+ # ba.use :input
25
+ # end
26
+ # end
27
+ #
28
+ # The builder also accepts default options at the root level. This is usually
29
+ # used if you want a component to be disabled by default:
30
+ #
31
+ # config.wrappers :hint => false do |b|
32
+ # b.use :hint
33
+ # b.use :label_input
34
+ # end
35
+ #
36
+ # In the example above, hint defaults to false, which means it won't automatically
37
+ # do the lookup anymore. It will only be triggered when :hint is explicitly set.
38
+ class Builder
39
+ def initialize(options)
40
+ @options = options
41
+ @components = []
42
+ end
43
+
44
+ def use(name, options=nil, &block)
45
+ add(name, options, &block)
46
+ end
47
+
48
+ def optional(name, options=nil, &block)
49
+ @options[name] = false
50
+ add(name, options, &block)
51
+ end
52
+
53
+ def to_a
54
+ @components
55
+ end
56
+
57
+ private
58
+
59
+ def add(name, options)
60
+ if block_given?
61
+ name, options = nil, name if name.is_a?(Hash)
62
+ builder = self.class.new(@options)
63
+ options ||= {}
64
+ options[:tag] = :div if options[:tag].nil?
65
+ yield builder
66
+ @components << Many.new(name, builder.to_a, options)
67
+ elsif options
68
+ @components << Single.new(name, options)
69
+ else
70
+ @components << name
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,68 @@
1
+ module SimpleForm
2
+ module Wrappers
3
+ # A wrapper is an object that holds several components and render them.
4
+ # A component may either be a symbol or any object that responds to `render`.
5
+ # This API allows inputs/components to be easily wrapped, removing the
6
+ # need to modify the code only to wrap input in an extra tag.
7
+ #
8
+ # `Many` represents a wrapper around several components at the same time.
9
+ # It may optionally receive a namespace, allowing it to be configured
10
+ # on demand on input generation.
11
+ class Many
12
+ attr_reader :namespace, :defaults, :components
13
+ alias :to_sym :namespace
14
+
15
+ def initialize(namespace, components, defaults={})
16
+ @namespace = namespace
17
+ @components = components
18
+ @defaults = defaults
19
+ @defaults[:class] = Array.wrap(@defaults[:class])
20
+ end
21
+
22
+ def render(input)
23
+ content = "".html_safe
24
+ options = input.options
25
+
26
+ components.each do |component|
27
+ next if options[component] == false
28
+ rendered = component.respond_to?(:render) ? component.render(input) : input.send(component)
29
+ content.safe_concat rendered.to_s if rendered
30
+ end
31
+
32
+ wrap(input, options, content)
33
+ end
34
+
35
+ def find(name)
36
+ return self if namespace == name
37
+
38
+ @components.each do |c|
39
+ if c.is_a?(Symbol)
40
+ return nil if c == namespace
41
+ elsif value = c.find(name)
42
+ return value
43
+ end
44
+ end
45
+
46
+ nil
47
+ end
48
+
49
+ private
50
+
51
+ def wrap(input, options, content)
52
+ return content if options[namespace] == false
53
+
54
+ tag = (namespace && options[:"#{namespace}_tag"]) || @defaults[:tag]
55
+ return content unless tag
56
+
57
+ klass = html_classes(input, options)
58
+ opts = options[:"#{namespace}_html"] || {}
59
+ opts[:class] = (klass << opts[:class]).join(' ').strip unless klass.empty?
60
+ input.template.content_tag(tag, content, opts)
61
+ end
62
+
63
+ def html_classes(input, options)
64
+ @defaults[:class].dup
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,34 @@
1
+ module SimpleForm
2
+ module Wrappers
3
+ # `Root` is the root wrapper for all components. It is special cased to
4
+ # always have a namespace and to add special html classes.
5
+ class Root < Many
6
+ attr_reader :options
7
+
8
+ def initialize(*args)
9
+ super(:wrapper, *args)
10
+ @options = @defaults.except(:tag, :class, :error_class, :hint_class)
11
+ end
12
+
13
+ def render(input)
14
+ input.options.reverse_merge!(@options)
15
+ super
16
+ end
17
+
18
+ # Provide a fallback if name cannot be found.
19
+ def find(name)
20
+ super || SimpleForm::Wrappers::Many.new(name, [name])
21
+ end
22
+
23
+ private
24
+
25
+ def html_classes(input, options)
26
+ css = options[:wrapper_class] ? Array.wrap(options[:wrapper_class]) : @defaults[:class]
27
+ css += input.html_classes
28
+ css << (options[:wrapper_error_class] || @defaults[:error_class]) if input.has_errors?
29
+ css << (options[:wrapper_hint_class] || @defaults[:hint_class]) if input.has_hint?
30
+ css
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,18 @@
1
+ module SimpleForm
2
+ module Wrappers
3
+ # `Single` is an optimization for a wrapper that has only one component.
4
+ class Single < Many
5
+ def initialize(name, options={})
6
+ super(name, [name], options)
7
+ end
8
+
9
+ def render(input)
10
+ options = input.options
11
+ if options[namespace] != false
12
+ content = input.send(namespace)
13
+ wrap(input, options, content) if content
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -8,48 +8,48 @@ class BuilderTest < ActionView::TestCase
8
8
  end
9
9
  end
10
10
 
11
- def with_collection_radio(object, attribute, collection, value_method, text_method, options={}, html_options={})
11
+ def with_collection_radio_buttons(object, attribute, collection, value_method, text_method, options={}, html_options={}, &block)
12
12
  with_concat_form_for(object) do |f|
13
- f.collection_radio attribute, collection, value_method, text_method, options, html_options
13
+ f.collection_radio_buttons attribute, collection, value_method, text_method, options, html_options, &block
14
14
  end
15
15
  end
16
16
 
17
- def with_collection_check_boxes(object, attribute, collection, value_method, text_method, options={}, html_options={})
17
+ def with_collection_check_boxes(object, attribute, collection, value_method, text_method, options={}, html_options={}, &block)
18
18
  with_concat_form_for(object) do |f|
19
- f.collection_check_boxes attribute, collection, value_method, text_method, options, html_options
19
+ f.collection_check_boxes attribute, collection, value_method, text_method, options, html_options, &block
20
20
  end
21
21
  end
22
22
 
23
23
  # COLLECTION RADIO
24
24
  test 'collection radio accepts a collection and generate inputs from value method' do
25
- with_collection_radio @user, :active, [true, false], :to_s, :to_s
25
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s
26
26
 
27
27
  assert_select 'form input[type=radio][value=true]#user_active_true'
28
28
  assert_select 'form input[type=radio][value=false]#user_active_false'
29
29
  end
30
30
 
31
31
  test 'collection radio accepts a collection and generate inputs from label method' do
32
- with_collection_radio @user, :active, [true, false], :to_s, :to_s
32
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s
33
33
 
34
- assert_select 'form label.collection_radio[for=user_active_true]', 'true'
35
- assert_select 'form label.collection_radio[for=user_active_false]', 'false'
34
+ assert_select 'form label.collection_radio_buttons[for=user_active_true]', 'true'
35
+ assert_select 'form label.collection_radio_buttons[for=user_active_false]', 'false'
36
36
  end
37
37
 
38
38
  test 'collection radio handles camelized collection values for labels correctly' do
39
- with_collection_radio @user, :active, ['Yes', 'No'], :to_s, :to_s
39
+ with_collection_radio_buttons @user, :active, ['Yes', 'No'], :to_s, :to_s
40
40
 
41
- assert_select 'form label.collection_radio[for=user_active_yes]', 'Yes'
42
- assert_select 'form label.collection_radio[for=user_active_no]', 'No'
41
+ assert_select 'form label.collection_radio_buttons[for=user_active_yes]', 'Yes'
42
+ assert_select 'form label.collection_radio_buttons[for=user_active_no]', 'No'
43
43
  end
44
44
 
45
45
  test 'colection radio should sanitize collection values for labels correctly' do
46
- with_collection_radio @user, :name, ['$0.99', '$1.99'], :to_s, :to_s
47
- assert_select 'label.collection_radio[for=user_name_099]', '$0.99'
48
- assert_select 'label.collection_radio[for=user_name_199]', '$1.99'
46
+ with_collection_radio_buttons @user, :name, ['$0.99', '$1.99'], :to_s, :to_s
47
+ assert_select 'label.collection_radio_buttons[for=user_name_099]', '$0.99'
48
+ assert_select 'label.collection_radio_buttons[for=user_name_199]', '$1.99'
49
49
  end
50
50
 
51
51
  test 'collection radio accepts checked item' do
52
- with_collection_radio @user, :active, [[1, true], [0, false]], :last, :first, :checked => true
52
+ with_collection_radio_buttons @user, :active, [[1, true], [0, false]], :last, :first, :checked => true
53
53
 
54
54
  assert_select 'form input[type=radio][value=true][checked=checked]'
55
55
  assert_no_select 'form input[type=radio][value=false][checked=checked]'
@@ -57,7 +57,7 @@ class BuilderTest < ActionView::TestCase
57
57
 
58
58
  test 'collection radio accepts multiple disabled items' do
59
59
  collection = [[1, true], [0, false], [2, 'other']]
60
- with_collection_radio @user, :active, collection, :last, :first, :disabled => [true, false]
60
+ with_collection_radio_buttons @user, :active, collection, :last, :first, :disabled => [true, false]
61
61
 
62
62
  assert_select 'form input[type=radio][value=true][disabled=disabled]'
63
63
  assert_select 'form input[type=radio][value=false][disabled=disabled]'
@@ -66,7 +66,7 @@ class BuilderTest < ActionView::TestCase
66
66
 
67
67
  test 'collection radio accepts single disable item' do
68
68
  collection = [[1, true], [0, false]]
69
- with_collection_radio @user, :active, collection, :last, :first, :disabled => true
69
+ with_collection_radio_buttons @user, :active, collection, :last, :first, :disabled => true
70
70
 
71
71
  assert_select 'form input[type=radio][value=true][disabled=disabled]'
72
72
  assert_no_select 'form input[type=radio][value=false][disabled=disabled]'
@@ -74,105 +74,143 @@ class BuilderTest < ActionView::TestCase
74
74
 
75
75
  test 'collection radio accepts html options as input' do
76
76
  collection = [[1, true], [0, false]]
77
- with_collection_radio @user, :active, collection, :last, :first, {}, :class => 'radio'
77
+ with_collection_radio_buttons @user, :active, collection, :last, :first, {}, :class => 'special-radio'
78
78
 
79
- assert_select 'form input[type=radio][value=true].radio#user_active_true'
80
- assert_select 'form input[type=radio][value=false].radio#user_active_false'
79
+ assert_select 'form input[type=radio][value=true].special-radio#user_active_true'
80
+ assert_select 'form input[type=radio][value=false].special-radio#user_active_false'
81
81
  end
82
82
 
83
- test 'collection radio wraps the collection in the configured collection wrapper tag' do
84
- swap SimpleForm, :collection_wrapper_tag => :ul do
85
- with_collection_radio @user, :active, [true, false], :to_s, :to_s
83
+ test 'collection radio wraps the collection in the given collection wrapper tag' do
84
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => :ul
86
85
 
87
- assert_select 'form ul input[type=radio][value=true]#user_active_true'
88
- assert_select 'form ul input[type=radio][value=false]#user_active_false'
89
- end
86
+ assert_select 'form ul input[type=radio]', :count => 2
90
87
  end
91
88
 
92
- test 'collection radio wraps the collection in the given collection wrapper tag' do
93
- with_collection_radio @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => :ul
89
+ test 'collection radio does not render any wrapper tag by default' do
90
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s
94
91
 
95
- assert_select 'form ul input[type=radio][value=true]#user_active_true'
96
- assert_select 'form ul input[type=radio][value=false]#user_active_false'
92
+ assert_select 'form input[type=radio]', :count => 2
93
+ assert_no_select 'form ul'
97
94
  end
98
95
 
99
- test 'collection radio does not wrap the collection in the explicitly false collection wrapper tag' do
100
- swap SimpleForm, :collection_wrapper_tag => :ul do
101
- with_collection_radio @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => false
96
+ test 'collection radio does not wrap the collection when given falsy values' do
97
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => false
102
98
 
103
- assert_no_select 'form ul'
104
- assert_no_select 'form ul'
105
- end
99
+ assert_select 'form input[type=radio]', :count => 2
100
+ assert_no_select 'form ul'
106
101
  end
107
102
 
108
- test 'collection radio does not wrap the collection in the explicitly nil collection wrapper tag' do
109
- swap SimpleForm, :collection_wrapper_tag => :ul do
110
- with_collection_radio @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => nil
103
+ test 'collection radio uses the given class for collection wrapper tag' do
104
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s,
105
+ :collection_wrapper_tag => :ul, :collection_wrapper_class => "items-list"
111
106
 
112
- assert_no_select 'form ul'
113
- assert_no_select 'form ul'
114
- end
107
+ assert_select 'form ul.items-list input[type=radio]', :count => 2
115
108
  end
116
109
 
117
- test 'collection radio does not wrap the collection by default' do
118
- with_collection_radio @user, :active, [true, false], :to_s, :to_s
110
+ test 'collection radio uses no class for collection wrapper tag when no wrapper tag is given' do
111
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s,
112
+ :collection_wrapper_class => "items-list"
119
113
 
114
+ assert_select 'form input[type=radio]', :count => 2
120
115
  assert_no_select 'form ul'
116
+ assert_no_select '.items-list'
121
117
  end
122
118
 
123
- test 'collection radio wraps each label/radio in the configured item wrapper tag' do
124
- swap SimpleForm, :item_wrapper_tag => :li do
125
- with_collection_radio @user, :active, [true, false], :to_s, :to_s
119
+ test 'collection radio uses no class for collection wrapper tag by default' do
120
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => :ul
126
121
 
127
- assert_select 'form li input[type=radio][value=true]#user_active_true'
128
- assert_select 'form li input[type=radio][value=false]#user_active_false'
129
- end
122
+ assert_select 'form ul'
123
+ assert_no_select 'form ul[class]'
130
124
  end
131
125
 
132
- test 'collection radio wraps each label/radio in the given item wrapper tag' do
133
- with_collection_radio @user, :active, [true, false], :to_s, :to_s, :item_wrapper_tag => :li
126
+ test 'collection radio wrap items in a span tag by default' do
127
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s
134
128
 
135
- assert_select 'form li input[type=radio][value=true]#user_active_true'
136
- assert_select 'form li input[type=radio][value=false]#user_active_false'
129
+ assert_select 'form span input[type=radio][value=true]#user_active_true + label'
130
+ assert_select 'form span input[type=radio][value=false]#user_active_false + label'
137
131
  end
138
132
 
139
- test 'collection radio does not wrap each label/radio in the explicitly false item wrapper tag' do
140
- with_collection_radio @user, :active, [true, false], :to_s, :to_s, :item_wrapper_tag => false
133
+ test 'collection radio wraps each item in the given item wrapper tag' do
134
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s, :item_wrapper_tag => :li
141
135
 
142
- assert_no_select 'form span input[type=radio][value=true]#user_active_true'
143
- assert_no_select 'form span input[type=radio][value=false]#user_active_false'
136
+ assert_select 'form li input[type=radio]', :count => 2
144
137
  end
145
138
 
146
- test 'collection radio does not wrap each label/radio in the explicitly nil item wrapper tag' do
147
- with_collection_radio @user, :active, [true, false], :to_s, :to_s, :item_wrapper_tag => nil
139
+ test 'collection radio does not wrap each item when given explicitly falsy value' do
140
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s, :item_wrapper_tag => false
148
141
 
149
- assert_no_select 'form span input[type=radio][value=true]#user_active_true'
150
- assert_no_select 'form span input[type=radio][value=false]#user_active_false'
142
+ assert_select 'form input[type=radio]'
143
+ assert_no_select 'form span input[type=radio]'
151
144
  end
152
145
 
153
- test 'collection radio wrap items in a span tag by default' do
154
- with_collection_radio @user, :active, [true, false], :to_s, :to_s
146
+ test 'collection radio uses the given class for item wrapper tag' do
147
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s,
148
+ :item_wrapper_tag => :li, :item_wrapper_class => "inline"
155
149
 
156
- assert_select 'form span input[type=radio][value=true]#user_active_true + label'
157
- assert_select 'form span input[type=radio][value=false]#user_active_false + label'
150
+ assert_select "form li.inline input[type=radio]", :count => 2
151
+ end
152
+
153
+ test 'collection radio uses no class for item wrapper tag when no wrapper tag is given' do
154
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s,
155
+ :item_wrapper_tag => nil, :item_wrapper_class => "inline"
156
+
157
+ assert_select 'form input[type=radio]', :count => 2
158
+ assert_no_select 'form li'
159
+ assert_no_select '.inline'
160
+ end
161
+
162
+ test 'collection radio uses no class for item wrapper tag by default' do
163
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s,
164
+ :item_wrapper_tag => :li
165
+
166
+ assert_select "form li", :count => 2
167
+ assert_no_select "form li[class]"
158
168
  end
159
169
 
160
170
  test 'collection radio does not wrap input inside the label' do
161
- with_collection_radio @user, :active, [true, false], :to_s, :to_s
171
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s
162
172
 
173
+ assert_select 'form input[type=radio] + label'
163
174
  assert_no_select 'form label input'
164
175
  end
165
176
 
177
+ test 'collection radio accepts a block to render the radio and label as required' do
178
+ with_collection_radio_buttons @user, :active, [true, false], :to_s, :to_s do |label_for, text, value, html_options|
179
+ label(:user, label_for, text) { radio_button(:user, :active, value, html_options) }
180
+ end
181
+
182
+ assert_select 'form label[for=user_active_true] > input#user_active_true[type=radio]'
183
+ assert_select 'form label[for=user_active_false] > input#user_active_false[type=radio]'
184
+ end
185
+
186
+ test 'collection_radio helper is deprecated in favor of collection_radio_buttons' do
187
+ assert_deprecated "[SIMPLE_FORM] The `collection_radio` helper is deprecated, " \
188
+ "please use `collection_radio_buttons` instead" do
189
+ with_concat_form_for(@user) do |f|
190
+ f.collection_radio :active, [true, false], :to_s, :to_s
191
+ end
192
+ end
193
+
194
+ assert_select 'input[type=radio][value=true]'
195
+ assert_select 'input[type=radio][value=false]'
196
+ end
197
+
166
198
  # COLLECTION CHECK BOX
167
199
  test 'collection check box accepts a collection and generate a serie of checkboxes for value method' do
168
200
  collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
169
201
  with_collection_check_boxes @user, :tag_ids, collection, :id, :name
170
202
 
171
- assert_select "form input[type=hidden][name='user[tag_ids][]'][value=]"
172
203
  assert_select 'form input#user_tag_ids_1[type=checkbox][value=1]'
173
204
  assert_select 'form input#user_tag_ids_2[type=checkbox][value=2]'
174
205
  end
175
206
 
207
+ test 'collection check box generates only one hidden field for the entire collection, to ensure something will be sent back to the server when posting an empty collection' do
208
+ collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
209
+ with_collection_check_boxes @user, :tag_ids, collection, :id, :name
210
+
211
+ assert_select "form input[type=hidden][name='user[tag_ids][]'][value=]", :count => 1
212
+ end
213
+
176
214
  test 'collection check box accepts a collection and generate a serie of checkboxes with labels for label method' do
177
215
  collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
178
216
  with_collection_check_boxes @user, :tag_ids, collection, :id, :name
@@ -212,6 +250,16 @@ class BuilderTest < ActionView::TestCase
212
250
  assert_no_select 'form input[type=checkbox][value=2][checked=checked]'
213
251
  end
214
252
 
253
+ test 'collection check box accepts selected values as :checked option and override the model values' do
254
+ collection = (1..3).map{|i| [i, "Tag #{i}"] }
255
+ @user.tag_ids = [2]
256
+ with_collection_check_boxes @user, :tag_ids, collection, :first, :last, :checked => [1, 3]
257
+
258
+ assert_select 'form input[type=checkbox][value=1][checked=checked]'
259
+ assert_select 'form input[type=checkbox][value=3][checked=checked]'
260
+ assert_no_select 'form input[type=checkbox][value=2][checked=checked]'
261
+ end
262
+
215
263
  test 'collection check box accepts multiple disabled items' do
216
264
  collection = (1..3).map{|i| [i, "Tag #{i}"] }
217
265
  with_collection_check_boxes @user, :tag_ids, collection, :first, :last, :disabled => [1, 3]
@@ -262,71 +310,108 @@ class BuilderTest < ActionView::TestCase
262
310
  assert_select 'form label.collection_check_boxes[for=user_post_tag_ids_2]', 'Tag 2'
263
311
  end
264
312
 
265
- test 'collection check box wraps the collection in the configured collection wrapper tag' do
266
- swap SimpleForm, :collection_wrapper_tag => :ul do
267
- with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s
313
+ test 'collection check boxes wraps the collection in the given collection wrapper tag' do
314
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => :ul
268
315
 
269
- assert_select 'form ul input[type=checkbox][value=true]#user_active_true'
270
- assert_select 'form ul input[type=checkbox][value=false]#user_active_false'
271
- end
316
+ assert_select 'form ul input[type=checkbox]', :count => 2
272
317
  end
273
318
 
274
- test 'collection check box wraps the collection in the given collection wrapper tag' do
275
- with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => :ul
319
+ test 'collection check boxes does not render any wrapper tag by default' do
320
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s
276
321
 
277
- assert_select 'form ul input[type=checkbox][value=true]#user_active_true'
278
- assert_select 'form ul input[type=checkbox][value=false]#user_active_false'
322
+ assert_select 'form input[type=checkbox]', :count => 2
323
+ assert_no_select 'form ul'
279
324
  end
280
325
 
281
- test 'collection check box does not wrap the collection in the explicitly false collection wrapper tag' do
282
- with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => false, :item_wrapper_tag => false
326
+ test 'collection check boxes does not wrap the collection when given falsy values' do
327
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => false
283
328
 
284
- assert_select 'form > input[type=checkbox][value=true]#user_active_true'
285
- assert_select 'form > input[type=checkbox][value=false]#user_active_false'
329
+ assert_select 'form input[type=checkbox]', :count => 2
330
+ assert_no_select 'form ul'
286
331
  end
287
332
 
288
- test 'collection check box does not wrap the collection by default' do
289
- with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s
333
+ test 'collection check boxes uses the given class for collection wrapper tag' do
334
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s,
335
+ :collection_wrapper_tag => :ul, :collection_wrapper_class => "items-list"
336
+
337
+ assert_select 'form ul.items-list input[type=checkbox]', :count => 2
338
+ end
290
339
 
340
+ test 'collection check boxes uses no class for collection wrapper tag when no wrapper tag is given' do
341
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s,
342
+ :collection_wrapper_class => "items-list"
343
+
344
+ assert_select 'form input[type=checkbox]', :count => 2
291
345
  assert_no_select 'form ul'
346
+ assert_no_select '.items-list'
292
347
  end
293
348
 
294
- test 'collection check box wraps each label/radio in the configured item wrapper tag' do
295
- swap SimpleForm, :item_wrapper_tag => :li do
296
- with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s
349
+ test 'collection check boxes uses no class for collection wrapper tag by default' do
350
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, :collection_wrapper_tag => :ul
297
351
 
298
- assert_select 'form li input[type=checkbox][value=true]#user_active_true'
299
- assert_select 'form li input[type=checkbox][value=false]#user_active_false'
300
- end
352
+ assert_select 'form ul'
353
+ assert_no_select 'form ul[class]'
354
+ end
355
+
356
+ test 'collection check boxes wrap items in a span tag by default' do
357
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s
358
+
359
+ assert_select 'form span input[type=checkbox]', :count => 2
301
360
  end
302
361
 
303
- test 'collection check box wraps each label/radio in the given item wrapper tag' do
362
+ test 'collection check boxes wraps each item in the given item wrapper tag' do
304
363
  with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, :item_wrapper_tag => :li
305
364
 
306
- assert_select 'form li input[type=checkbox][value=true]#user_active_true'
307
- assert_select 'form li input[type=checkbox][value=false]#user_active_false'
365
+ assert_select 'form li input[type=checkbox]', :count => 2
308
366
  end
309
367
 
310
- test 'collection check box does not wrapp each label/radio in the explicitly false item wrapper tag' do
368
+ test 'collection check boxes does not wrap each item when given explicitly falsy value' do
311
369
  with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s, :item_wrapper_tag => false
312
370
 
313
- assert_select 'form > input[type=checkbox][value=true]#user_active_true'
314
- assert_select 'form > input[type=checkbox][value=false]#user_active_false'
371
+ assert_select 'form input[type=checkbox]'
372
+ assert_no_select 'form span input[type=checkbox]'
315
373
  end
316
374
 
317
- test 'collection check box wrap items in a span tag by default' do
318
- with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s
375
+ test 'collection check boxes uses the given class for item wrapper tag' do
376
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s,
377
+ :item_wrapper_tag => :li, :item_wrapper_class => "inline"
378
+
379
+ assert_select "form li.inline input[type=checkbox]", :count => 2
380
+ end
381
+
382
+ test 'collection check boxes uses no class for item wrapper tag when no wrapper tag is given' do
383
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s,
384
+ :item_wrapper_tag => nil, :item_wrapper_class => "inline"
385
+
386
+ assert_select 'form input[type=checkbox]', :count => 2
387
+ assert_no_select 'form li'
388
+ assert_no_select '.inline'
389
+ end
319
390
 
320
- assert_select 'form span input[type=checkbox][value=true]#user_active_true + label'
321
- assert_select 'form span input[type=checkbox][value=false]#user_active_false + label'
391
+ test 'collection check boxes uses no class for item wrapper tag by default' do
392
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s,
393
+ :item_wrapper_tag => :li
394
+
395
+ assert_select "form li", :count => 2
396
+ assert_no_select "form li[class]"
322
397
  end
323
398
 
324
399
  test 'collection check box does not wrap input inside the label' do
325
400
  with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s
326
401
 
402
+ assert_select 'form input[type=checkbox] + label'
327
403
  assert_no_select 'form label input'
328
404
  end
329
405
 
406
+ test 'collection check box accepts a block to render the radio and label as required' do
407
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s do |label_for, text, value, html_options|
408
+ label(:user, label_for, text) { check_box(:user, :active, html_options, value) }
409
+ end
410
+
411
+ assert_select 'form label[for=user_active_true] > input#user_active_true[type=checkbox]'
412
+ assert_select 'form label[for=user_active_false] > input#user_active_false[type=checkbox]'
413
+ end
414
+
330
415
  # SIMPLE FIELDS
331
416
  test 'simple fields for is available and yields an instance of FormBuilder' do
332
417
  with_concat_form_for(@user) do |f|
@@ -364,4 +449,14 @@ class BuilderTest < ActionView::TestCase
364
449
  end
365
450
  end
366
451
  end
452
+
453
+ test 'fields inherites wrapper option from the parent form' do
454
+ swap_wrapper :another do
455
+ simple_form_for(:user, :wrapper => :another) do |f|
456
+ f.simple_fields_for(:company) do |company|
457
+ assert_equal :another, company.options[:wrapper]
458
+ end
459
+ end
460
+ end
461
+ end
367
462
  end