simple_form 2.1.3 → 3.0.0.beta1

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.

Potentially problematic release.


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

Files changed (72) hide show
  1. data/CHANGELOG.md +6 -54
  2. data/README.md +129 -111
  3. data/lib/generators/simple_form/install_generator.rb +4 -4
  4. data/lib/generators/simple_form/templates/README +2 -2
  5. data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +8 -11
  6. data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +16 -16
  7. data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +3 -3
  8. data/lib/simple_form.rb +31 -47
  9. data/lib/simple_form/action_view_extensions/builder.rb +0 -319
  10. data/lib/simple_form/action_view_extensions/builder.rb.orig +247 -0
  11. data/lib/simple_form/action_view_extensions/form_helper.rb +1 -1
  12. data/lib/simple_form/components.rb +1 -1
  13. data/lib/simple_form/components/errors.rb +1 -7
  14. data/lib/simple_form/components/hints.rb +2 -7
  15. data/lib/simple_form/components/html5.rb +1 -1
  16. data/lib/simple_form/components/labels.rb +4 -4
  17. data/lib/simple_form/components/maxlength.rb +1 -8
  18. data/lib/simple_form/error_notification.rb +2 -2
  19. data/lib/simple_form/form_builder.rb +144 -46
  20. data/lib/simple_form/form_builder.rb.orig +486 -0
  21. data/lib/simple_form/helpers.rb +1 -1
  22. data/lib/simple_form/inputs/base.rb +3 -10
  23. data/lib/simple_form/inputs/block_input.rb +1 -1
  24. data/lib/simple_form/inputs/boolean_input.rb +6 -6
  25. data/lib/simple_form/inputs/collection_input.rb +7 -7
  26. data/lib/simple_form/inputs/numeric_input.rb +0 -6
  27. data/lib/simple_form/inputs/password_input.rb +0 -1
  28. data/lib/simple_form/inputs/string_input.rb +0 -1
  29. data/lib/simple_form/railtie.rb +7 -0
  30. data/lib/simple_form/tags.rb +61 -0
  31. data/lib/simple_form/version.rb +1 -1
  32. data/lib/simple_form/version.rb.orig +7 -0
  33. data/lib/simple_form/wrappers.rb +1 -1
  34. data/lib/simple_form/wrappers/builder.rb +5 -29
  35. data/lib/simple_form/wrappers/many.rb +1 -1
  36. data/lib/simple_form/wrappers/root.rb +1 -1
  37. data/test/action_view_extensions/builder_test.rb +67 -87
  38. data/test/action_view_extensions/form_helper_test.rb +16 -16
  39. data/test/components/label_test.rb +46 -46
  40. data/test/form_builder/association_test.rb +23 -23
  41. data/test/form_builder/button_test.rb +4 -4
  42. data/test/form_builder/error_notification_test.rb +8 -8
  43. data/test/form_builder/error_test.rb +18 -65
  44. data/test/form_builder/general_test.rb +45 -65
  45. data/test/form_builder/hint_test.rb +23 -29
  46. data/test/form_builder/input_field_test.rb +12 -12
  47. data/test/form_builder/label_test.rb +6 -16
  48. data/test/form_builder/wrapper_test.rb +21 -21
  49. data/test/inputs/boolean_input_test.rb +23 -35
  50. data/test/inputs/collection_check_boxes_input_test.rb +55 -55
  51. data/test/inputs/collection_radio_buttons_input_test.rb +70 -79
  52. data/test/inputs/collection_select_input_test.rb +45 -51
  53. data/test/inputs/datetime_input_test.rb +11 -11
  54. data/test/inputs/disabled_test.rb +10 -10
  55. data/test/inputs/discovery_test.rb +4 -4
  56. data/test/inputs/file_input_test.rb +1 -1
  57. data/test/inputs/general_test.rb +12 -12
  58. data/test/inputs/grouped_collection_select_input_test.rb +20 -20
  59. data/test/inputs/hidden_input_test.rb +1 -1
  60. data/test/inputs/numeric_input_test.rb +3 -3
  61. data/test/inputs/priority_input_test.rb +3 -3
  62. data/test/inputs/readonly_test.rb +12 -12
  63. data/test/inputs/required_test.rb +5 -5
  64. data/test/inputs/string_input_test.rb +10 -25
  65. data/test/inputs/text_input_test.rb +1 -1
  66. data/test/support/misc_helpers.rb +24 -24
  67. data/test/support/mock_controller.rb +6 -6
  68. data/test/support/models.rb +37 -46
  69. data/test/test_helper.rb +20 -20
  70. metadata +49 -24
  71. checksums.yaml +0 -7
  72. data/lib/simple_form/core_ext/hash.rb +0 -16
@@ -3,13 +3,13 @@ module SimpleForm
3
3
  class InstallGenerator < Rails::Generators::Base
4
4
  desc "Copy SimpleForm default files"
5
5
  source_root File.expand_path('../templates', __FILE__)
6
- class_option :template_engine, :desc => 'Template engine to be invoked (erb, haml or slim).'
7
- class_option :bootstrap, :type => :boolean, :desc => 'Add the Bootstrap wrappers to the SimpleForm initializer.'
8
- class_option :foundation, :type => :boolean, :desc => 'Add the Zurb Foundation 3 wrappers to the SimpleForm initializer.'
6
+ class_option :template_engine, desc: 'Template engine to be invoked (erb, haml or slim).'
7
+ class_option :bootstrap, type: :boolean, desc: 'Add the Twitter Bootstrap wrappers to the SimpleForm initializer.'
8
+ class_option :foundation, type: :boolean, desc: 'Add the Zurb Foundation 3 wrappers to the SimpleForm initializer.'
9
9
 
10
10
  def info_bootstrap
11
11
  return if options.bootstrap? || options.foundation?
12
- puts "SimpleForm 2 supports Bootstrap and Zurb Foundation 3. If you want "\
12
+ puts "SimpleForm 2 supports Twitter Bootstrap and Zurb Foundation 3. If you want "\
13
13
  "a configuration that is compatible with one of these frameworks, then please " \
14
14
  "re-run this generator with --bootstrap or --foundation as an option."
15
15
  end
@@ -1,12 +1,12 @@
1
1
  ===============================================================================
2
2
 
3
3
  Be sure to have a copy of the Bootstrap stylesheet available on your
4
- application, you can get it on http://getbootstrap.com/2.3.2/.
4
+ application, you can get it on http://twitter.github.com/bootstrap.
5
5
 
6
6
  Inside your views, use the 'simple_form_for' with one of the Bootstrap form
7
7
  classes, '.form-horizontal', '.form-inline', '.form-search' or
8
8
  '.form-vertical', as the following:
9
9
 
10
- = simple_form_for(@user, :html => {:class => 'form-horizontal' }) do |form|
10
+ = simple_form_for(@user, html: {class: 'form-horizontal' }) do |form|
11
11
 
12
12
  ===============================================================================
@@ -5,8 +5,8 @@ SimpleForm.setup do |config|
5
5
  # wrapper, change the order or even add your own to the
6
6
  # stack. The options given below are used to wrap the
7
7
  # whole input.
8
- config.wrappers :default, :class => :input,
9
- :hint_class => :field_with_hint, :error_class => :field_with_errors do |b|
8
+ config.wrappers :default, class: :input,
9
+ hint_class: :field_with_hint, error_class: :field_with_errors do |b|
10
10
  ## Extensions enabled by default
11
11
  # Any of these extensions can be disabled for a
12
12
  # given input by passing: `f.input EXTENSION_NAME => false`.
@@ -18,7 +18,7 @@ SimpleForm.setup do |config|
18
18
  b.use :html5
19
19
 
20
20
  # Calculates placeholders automatically from I18n
21
- # You can also pass a string as f.input :placeholder => "Placeholder"
21
+ # You can also pass a string as f.input placeholder: "Placeholder"
22
22
  b.use :placeholder
23
23
 
24
24
  ## Optional extensions
@@ -41,8 +41,8 @@ SimpleForm.setup do |config|
41
41
 
42
42
  ## Inputs
43
43
  b.use :label_input
44
- b.use :hint, :wrap_with => { :tag => :span, :class => :hint }
45
- b.use :error, :wrap_with => { :tag => :span, :class => :error }
44
+ b.use :hint, wrap_with: { tag: :span, class: :hint }
45
+ b.use :error, wrap_with: { tag: :span, class: :error }
46
46
  end
47
47
 
48
48
  # The default wrapper to be used by the FormBuilder.
@@ -50,8 +50,8 @@ SimpleForm.setup do |config|
50
50
 
51
51
  # Define the way to render check boxes / radio buttons with labels.
52
52
  # Defaults to :nested for bootstrap config.
53
- # :inline => input + label
54
- # :nested => label > input
53
+ # inline: input + label
54
+ # nested: label > input
55
55
  config.boolean_style = :nested
56
56
 
57
57
  # Default class for buttons
@@ -120,7 +120,7 @@ SimpleForm.setup do |config|
120
120
 
121
121
  # Custom wrappers for input types. This should be a hash containing an input
122
122
  # type as key and the wrapper that will be used for all inputs with specified type.
123
- # config.wrapper_mappings = { :string => :prepend }
123
+ # config.wrapper_mappings = { string: :prepend }
124
124
 
125
125
  # Default priority for time_zone inputs.
126
126
  # config.time_zone_priority = nil
@@ -128,9 +128,6 @@ SimpleForm.setup do |config|
128
128
  # Default priority for country inputs.
129
129
  # config.country_priority = nil
130
130
 
131
- # Default size for text inputs.
132
- # config.default_input_size = 50
133
-
134
131
  # When false, do not use translations for labels.
135
132
  # config.translate_labels = true
136
133
 
@@ -1,44 +1,44 @@
1
1
  # Use this setup block to configure all options available in SimpleForm.
2
2
  SimpleForm.setup do |config|
3
- config.wrappers :bootstrap, :tag => 'div', :class => 'control-group', :error_class => 'error' do |b|
3
+ config.wrappers :bootstrap, tag: 'div', class: 'control-group', error_class: 'error' do |b|
4
4
  b.use :html5
5
5
  b.use :placeholder
6
6
  b.use :label
7
- b.wrapper :tag => 'div', :class => 'controls' do |ba|
7
+ b.wrapper tag: 'div', class: 'controls' do |ba|
8
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' }
9
+ ba.use :error, wrap_with: { tag: 'span', class: 'help-inline' }
10
+ ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
11
11
  end
12
12
  end
13
13
 
14
- config.wrappers :prepend, :tag => 'div', :class => "control-group", :error_class => 'error' do |b|
14
+ config.wrappers :prepend, tag: 'div', class: "control-group", error_class: 'error' do |b|
15
15
  b.use :html5
16
16
  b.use :placeholder
17
17
  b.use :label
18
- b.wrapper :tag => 'div', :class => 'controls' do |input|
19
- input.wrapper :tag => 'div', :class => 'input-prepend' do |prepend|
18
+ b.wrapper tag: 'div', class: 'controls' do |input|
19
+ input.wrapper tag: 'div', class: 'input-prepend' do |prepend|
20
20
  prepend.use :input
21
21
  end
22
- input.use :hint, :wrap_with => { :tag => 'span', :class => 'help-block' }
23
- input.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
22
+ input.use :hint, wrap_with: { tag: 'span', class: 'help-block' }
23
+ input.use :error, wrap_with: { tag: 'span', class: 'help-inline' }
24
24
  end
25
25
  end
26
26
 
27
- config.wrappers :append, :tag => 'div', :class => "control-group", :error_class => 'error' do |b|
27
+ config.wrappers :append, tag: 'div', class: "control-group", error_class: 'error' do |b|
28
28
  b.use :html5
29
29
  b.use :placeholder
30
30
  b.use :label
31
- b.wrapper :tag => 'div', :class => 'controls' do |input|
32
- input.wrapper :tag => 'div', :class => 'input-append' do |append|
31
+ b.wrapper tag: 'div', class: 'controls' do |input|
32
+ input.wrapper tag: 'div', class: 'input-append' do |append|
33
33
  append.use :input
34
34
  end
35
- input.use :hint, :wrap_with => { :tag => 'span', :class => 'help-block' }
36
- input.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
35
+ input.use :hint, wrap_with: { tag: 'span', class: 'help-block' }
36
+ input.use :error, wrap_with: { tag: 'span', class: 'help-inline' }
37
37
  end
38
38
  end
39
39
 
40
- # Wrappers for forms and inputs using the Bootstrap toolkit.
41
- # Check the Bootstrap docs (http://getbootstrap.com/2.3.2/)
40
+ # Wrappers for forms and inputs using the Twitter Bootstrap toolkit.
41
+ # Check the Bootstrap docs (http://twitter.github.com/bootstrap)
42
42
  # to learn about the different styles for forms and inputs,
43
43
  # buttons and other elements.
44
44
  config.default_wrapper = :bootstrap
@@ -1,6 +1,6 @@
1
1
  # Use this setup block to configure all options available in SimpleForm.
2
2
  SimpleForm.setup do |config|
3
- config.wrappers :foundation, :class => :input, :hint_class => :field_with_hint, :error_class => :error do |b|
3
+ config.wrappers :foundation, class: :input, hint_class: :field_with_hint, error_class: :error do |b|
4
4
  b.use :html5
5
5
  b.use :placeholder
6
6
  b.optional :maxlength
@@ -8,11 +8,11 @@ SimpleForm.setup do |config|
8
8
  b.optional :min_max
9
9
  b.optional :readonly
10
10
  b.use :label_input
11
- b.use :error, :wrap_with => { :tag => :small }
11
+ b.use :error, wrap_with: { tag: :small }
12
12
 
13
13
  # Uncomment the following line to enable hints. The line is commented out by default since Foundation
14
14
  # does't provide styles for hints. You will need to provide your own CSS styles for hints.
15
- # b.use :hint, :wrap_with => { :tag => :span, :class => :hint }
15
+ # b.use :hint, wrap_with: { tag: :span, class: :hint }
16
16
  end
17
17
 
18
18
  # CSS class for buttons
@@ -18,6 +18,12 @@ module SimpleForm
18
18
  autoload :Inputs
19
19
  end
20
20
 
21
+ def self.eager_load!
22
+ super
23
+ SimpleForm::Inputs.eager_load!
24
+ SimpleForm::Components.eager_load!
25
+ end
26
+
21
27
  ## CONFIGURATION OPTIONS
22
28
 
23
29
  # Method used to tidy up errors.
@@ -34,11 +40,11 @@ module SimpleForm
34
40
 
35
41
  # Series of attemps to detect a default label method for collection.
36
42
  mattr_accessor :collection_label_methods
37
- @@collection_label_methods = [ :to_label, :name, :title, :to_s ]
43
+ @@collection_label_methods = [:to_label, :name, :title, :to_s]
38
44
 
39
45
  # Series of attemps to detect a default value method for collection.
40
46
  mattr_accessor :collection_value_methods
41
- @@collection_value_methods = [ :id, :to_s ]
47
+ @@collection_value_methods = [:id, :to_s]
42
48
 
43
49
  # You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
44
50
  mattr_accessor :collection_wrapper_tag
@@ -49,7 +55,7 @@ module SimpleForm
49
55
  @@collection_wrapper_class = nil
50
56
 
51
57
  # You can wrap each item in a collection of radio/check boxes with a tag,
52
- # defaulting to none. Please note that when using :boolean_style = :nested,
58
+ # defaulting to span. Please note that when using :boolean_style = :nested,
53
59
  # SimpleForm will force this option to be a :label.
54
60
  mattr_accessor :item_wrapper_tag
55
61
  @@item_wrapper_tag = :span
@@ -62,25 +68,25 @@ module SimpleForm
62
68
  mattr_accessor :label_text
63
69
  @@label_text = lambda { |label, required| "#{required} #{label}" }
64
70
 
65
- # You can define the class to use on all labels. Default is nil.
71
+ # You can define the class to be used on all labels. Defaults to none.
66
72
  mattr_accessor :label_class
67
73
  @@label_class = nil
68
74
 
69
75
  # Define the way to render check boxes / radio buttons with labels.
70
- # :inline => input + label (default)
71
- # :nested => label > input
76
+ # inline: input + label (default)
77
+ # nested: label > input
72
78
  mattr_accessor :boolean_style
73
79
  @@boolean_style = :inline
74
80
 
75
- # You can define the class to use on all forms. Default is simple_form.
81
+ # You can define the class to be used on all forms. Default is simple_form.
76
82
  mattr_accessor :form_class
77
83
  @@form_class = :simple_form
78
84
 
79
- # You can define which elements should obtain additional classes
85
+ # You can define which elements should obtain additional classes.
80
86
  mattr_accessor :generate_additional_classes_for
81
87
  @@generate_additional_classes_for = [:wrapper, :label, :input]
82
88
 
83
- # Whether attributes are required by default (or not).
89
+ # Whether attributes are required by default or not.
84
90
  mattr_accessor :required_by_default
85
91
  @@required_by_default = true
86
92
 
@@ -90,7 +96,7 @@ module SimpleForm
90
96
 
91
97
  # Collection of methods to detect if a file type was given.
92
98
  mattr_accessor :file_methods
93
- @@file_methods = [ :mounted_as, :file?, :public_filename ]
99
+ @@file_methods = [:mounted_as, :file?, :public_filename]
94
100
 
95
101
  # Custom mappings for input types. This should be a hash containing a regexp
96
102
  # to match as key, and the input type that will be used when the field name
@@ -100,7 +106,7 @@ module SimpleForm
100
106
 
101
107
  # Custom wrappers for input types. This should be a hash containing an input
102
108
  # type as key and the wrapper that will be used for all inputs with specified type.
103
- # e.g { :string => :string_wrapper, :boolean => :boolean_wrapper }
109
+ # e.g { string: :string_wrapper, boolean: :boolean_wrapper }
104
110
  mattr_accessor :wrapper_mappings
105
111
  @@wrapper_mappings = nil
106
112
 
@@ -112,9 +118,9 @@ module SimpleForm
112
118
  mattr_accessor :country_priority
113
119
  @@country_priority = nil
114
120
 
115
- # Maximum size allowed for inputs.
121
+ # DEPRECATED: Maximum size allowed for inputs.
116
122
  mattr_accessor :default_input_size
117
- @@default_input_size = 50
123
+ @@default_input_size = nil
118
124
 
119
125
  # When off, do not use translations in labels. Disabling translation in
120
126
  # hints and placeholders can be done manually in the wrapper API.
@@ -125,11 +131,11 @@ module SimpleForm
125
131
  mattr_accessor :inputs_discovery
126
132
  @@inputs_discovery = true
127
133
 
128
- # Cache SimpleForm inputs discovery
134
+ # Cache SimpleForm inputs discovery.
129
135
  mattr_accessor :cache_discovery
130
136
  @@cache_discovery = defined?(Rails) && !Rails.env.development?
131
137
 
132
- # Adds a class to each generated button, mostly for compatiblity
138
+ # Adds a class to each generated button, mostly for compatiblity.
133
139
  mattr_accessor :button_class
134
140
  @@button_class = 'button'
135
141
 
@@ -168,7 +174,7 @@ module SimpleForm
168
174
  SimpleForm::Wrappers::Root.new(builder.to_a, options)
169
175
  end
170
176
 
171
- wrappers :class => :input, :hint_class => :field_with_hint, :error_class => :field_with_errors do |b|
177
+ wrappers class: :input, hint_class: :field_with_hint, error_class: :field_with_errors do |b|
172
178
  b.use :html5
173
179
 
174
180
  b.use :min_max
@@ -178,47 +184,25 @@ module SimpleForm
178
184
  b.optional :readonly
179
185
 
180
186
  b.use :label_input
181
- b.use :hint, :wrap_with => { :tag => :span, :class => :hint }
182
- b.use :error, :wrap_with => { :tag => :span, :class => :error }
183
- end
184
-
185
- ## SETUP
186
-
187
- DEPRECATED = %w(hint_tag hint_class error_tag error_class error_notification_id wrapper_tag wrapper_class wrapper_error_class components html5)
188
- @@deprecated = []
189
-
190
- DEPRECATED.each do |method|
191
- class_eval "def self.#{method}=(*); @@deprecated << :#{method}=; end"
192
- class_eval "def self.#{method}; deprecation_warn 'SimpleForm.#{method} is deprecated and has no effect'; end"
193
- end
194
-
195
- def self.translate=(value)
196
- deprecation_warn "SimpleForm.translate= is disabled in favor of translate_labels="
197
- self.translate_labels = value
187
+ b.use :hint, wrap_with: { tag: :span, class: :hint }
188
+ b.use :error, wrap_with: { tag: :span, class: :error }
198
189
  end
199
190
 
200
- def self.translate
201
- deprecation_warn "SimpleForm.translate is disabled in favor of translate_labels"
202
- self.translate_labels
191
+ def self.additional_classes_for(component)
192
+ generate_additional_classes_for.include?(component) ? yield : []
203
193
  end
204
194
 
205
- def self.deprecation_warn(message)
206
- ActiveSupport::Deprecation.warn "[SIMPLE_FORM] #{message}", caller
207
- end
195
+ ## SETUP
208
196
 
209
- def self.additional_classes_for(component)
210
- generate_additional_classes_for.include?(component) ? yield : []
197
+ def self.default_input_size=(*)
198
+ ActiveSupport::Deprecation.warn "[SIMPLE_FORM] SimpleForm.default_input_size= is deprecated and has no effect", caller
211
199
  end
212
200
 
213
201
  # Default way to setup SimpleForm. Run rails generate simple_form:install
214
202
  # to create a fresh initializer with all configuration values.
215
203
  def self.setup
216
204
  yield self
217
-
218
- unless @@deprecated.empty?
219
- raise "[SIMPLE FORM] Your SimpleForm initializer file is using the following methods: #{@@deprecated.to_sentence}. " <<
220
- "Those methods are part of the outdated configuration API. Updating to the new API is easy and fast. " <<
221
- "Check for more info here: https://github.com/plataformatec/simple_form/wiki/Upgrading-to-Simple-Form-2.0"
222
- end
223
205
  end
224
206
  end
207
+
208
+ require 'simple_form/railtie' if defined?(Rails)
@@ -1,188 +1,8 @@
1
1
  module SimpleForm
2
2
  module ActionViewExtensions
3
- # Base builder to handle each instance of a collection of radio buttons / check boxes.
4
- # Based on (at this time upcoming) Rails 4 collection builders.
5
- class BuilderBase #:nodoc:
6
- attr_reader :object, :text, :value
7
-
8
- def initialize(form_builder, method_name, object, sanitized_attribute_name, text,
9
- value, input_html_options)
10
- @form_builder = form_builder
11
- @method_name = method_name
12
- @object = object
13
- @sanitized_attribute_name = sanitized_attribute_name
14
- @text = text
15
- @value = value
16
- @input_html_options = input_html_options
17
- end
18
-
19
- def label(label_html_options={}, &block)
20
- @form_builder.label(@sanitized_attribute_name, @text, label_html_options, &block)
21
- end
22
- end
23
-
24
- # Handles generating an instance of radio + label for collection_radio_buttons.
25
- class RadioButtonBuilder < BuilderBase #:nodoc:
26
- def radio_button(extra_html_options={})
27
- html_options = extra_html_options.merge(@input_html_options)
28
- @form_builder.radio_button(@method_name, @value, html_options)
29
- end
30
- end
31
-
32
- # Handles generating an instance of check box + label for collection_check_boxes.
33
- class CheckBoxBuilder < BuilderBase #:nodoc:
34
- def check_box(extra_html_options={})
35
- html_options = extra_html_options.merge(@input_html_options)
36
- @form_builder.check_box(@method_name, html_options, @value, nil)
37
- end
38
- end
39
-
40
3
  # A collection of methods required by simple_form but added to rails default form.
41
4
  # This means that you can use such methods outside simple_form context.
42
5
  module Builder
43
- # Create a collection of radio inputs for the attribute. Basically this
44
- # helper will create a radio input associated with a label for each
45
- # text/value option in the collection, using value_method and text_method
46
- # to convert these text/value. You can give a symbol or a proc to both
47
- # value_method and text_method, that will be evaluated for each item in
48
- # the collection.
49
- #
50
- # == Examples
51
- #
52
- # form_for @user do |f|
53
- # f.collection_radio_buttons :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
54
- # end
55
- #
56
- # <input id="user_options_true" name="user[options]" type="radio" value="true" />
57
- # <label class="collection_radio_buttons" for="user_options_true">Yes</label>
58
- # <input id="user_options_false" name="user[options]" type="radio" value="false" />
59
- # <label class="collection_radio_buttons" for="user_options_false">No</label>
60
- #
61
- # It is also possible to give a block that should generate the radio +
62
- # label. To wrap the radio with the label, for instance:
63
- #
64
- # form_for @user do |f|
65
- # f.collection_radio_buttons(
66
- # :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
67
- # ) do |b|
68
- # b.label { b.radio_button + b.text }
69
- # end
70
- # end
71
- #
72
- # == Options
73
- #
74
- # Collection radio accepts some extra options:
75
- #
76
- # * checked => the value that should be checked initially.
77
- #
78
- # * disabled => the value or values that should be disabled. Accepts a single
79
- # item or an array of items.
80
- #
81
- # * collection_wrapper_tag => the tag to wrap the entire collection.
82
- #
83
- # * collection_wrapper_class => the CSS class to use for collection_wrapper_tag
84
- #
85
- # * item_wrapper_tag => the tag to wrap each item in the collection.
86
- #
87
- # * item_wrapper_class => the CSS class to use for item_wrapper_tag
88
- #
89
- # * a block => to generate the label + radio or any other component.
90
- #
91
- def collection_radio_buttons(attribute, collection, value_method, text_method, options={}, html_options={})
92
- rendered_collection = render_collection(
93
- collection, value_method, text_method, options, html_options
94
- ) do |item, value, text, default_html_options|
95
- builder = instantiate_collection_builder(RadioButtonBuilder, attribute, item, value, text, default_html_options)
96
-
97
- if block_given?
98
- yield builder
99
- else
100
- builder.radio_button + builder.label(:class => "collection_radio_buttons")
101
- end
102
- end
103
-
104
- wrap_rendered_collection(rendered_collection, options)
105
- end
106
-
107
- # deprecated
108
- def collection_radio(*args, &block)
109
- SimpleForm.deprecation_warn "The `collection_radio` helper is deprecated, " \
110
- "please use `collection_radio_buttons` instead."
111
- collection_radio_buttons(*args, &block)
112
- end
113
-
114
- # Creates a collection of check boxes for each item in the collection,
115
- # associated with a clickable label. Use value_method and text_method to
116
- # convert items in the collection for use as text/value in check boxes.
117
- # You can give a symbol or a proc to both value_method and text_method,
118
- # that will be evaluated for each item in the collection.
119
- #
120
- # == Examples
121
- #
122
- # form_for @user do |f|
123
- # f.collection_check_boxes :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
124
- # end
125
- #
126
- # <input name="user[options][]" type="hidden" value="" />
127
- # <input id="user_options_true" name="user[options][]" type="checkbox" value="true" />
128
- # <label class="collection_check_boxes" for="user_options_true">Yes</label>
129
- # <input name="user[options][]" type="hidden" value="" />
130
- # <input id="user_options_false" name="user[options][]" type="checkbox" value="false" />
131
- # <label class="collection_check_boxes" for="user_options_false">No</label>
132
- #
133
- # It is also possible to give a block that should generate the check box +
134
- # label. To wrap the check box with the label, for instance:
135
- #
136
- # form_for @user do |f|
137
- # f.collection_check_boxes(
138
- # :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
139
- # ) do |b|
140
- # b.label { b.check_box + b.text }
141
- # end
142
- # end
143
- #
144
- # == Options
145
- #
146
- # Collection check box accepts some extra options:
147
- #
148
- # * checked => the value or values that should be checked initially. Accepts
149
- # a single item or an array of items. It overrides existing associations.
150
- #
151
- # * disabled => the value or values that should be disabled. Accepts a single
152
- # item or an array of items.
153
- #
154
- # * collection_wrapper_tag => the tag to wrap the entire collection.
155
- #
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.
158
- #
159
- # * item_wrapper_tag => the tag to wrap each item in the collection.
160
- #
161
- # * item_wrapper_class => the CSS class to use for item_wrapper_tag
162
- #
163
- # * a block => to generate the label + check box or any other component.
164
- #
165
- def collection_check_boxes(attribute, collection, value_method, text_method, options={}, html_options={})
166
- rendered_collection = render_collection(
167
- collection, value_method, text_method, options, html_options
168
- ) do |item, value, text, default_html_options|
169
- default_html_options[:multiple] = true
170
- builder = instantiate_collection_builder(CheckBoxBuilder, attribute, item, value, text, default_html_options)
171
-
172
- if block_given?
173
- yield builder
174
- else
175
- builder.check_box + builder.label(:class => "collection_check_boxes")
176
- end
177
- end
178
-
179
- # Append a hidden field to make sure something will be sent back to the
180
- # server if all checkboxes are unchecked.
181
- hidden_name = html_options[:name] || "#{object_name}[#{attribute}][]"
182
- hidden = @template.hidden_field_tag(hidden_name, "", :id => nil)
183
-
184
- wrap_rendered_collection(rendered_collection + hidden, options)
185
- end
186
6
 
187
7
  # Wrapper for using SimpleForm inside a default rails form.
188
8
  # Example:
@@ -205,72 +25,6 @@ module SimpleForm
205
25
  end
206
26
  fields_for(*(args << options), &block)
207
27
  end
208
-
209
- private
210
-
211
- def instantiate_collection_builder(builder_class, attribute, item, value, text, html_options)
212
- builder_class.new(self, attribute, item,
213
- sanitize_attribute_name(attribute, value), text, value, html_options)
214
- end
215
-
216
- # Generate default options for collection helpers, such as :checked and
217
- # :disabled.
218
- def default_html_options_for_collection(item, value, options, html_options) #:nodoc:
219
- html_options = html_options.dup
220
-
221
- [:checked, :selected, :disabled].each do |option|
222
- current_option = options[option]
223
- next if current_option.nil?
224
-
225
- accept = if current_option.respond_to?(:call)
226
- current_option.call(item)
227
- else
228
- Array(current_option).map(&:to_s).include?(value.to_s)
229
- end
230
-
231
- if accept
232
- html_options[option] = true
233
- elsif option == :checked
234
- html_options[option] = false
235
- end
236
- end
237
-
238
- html_options
239
- end
240
-
241
- def sanitize_attribute_name(attribute, value) #:nodoc:
242
- "#{attribute}_#{value.to_s.gsub(/\s/, "_").gsub(/[^-\w]/, "").downcase}"
243
- end
244
-
245
- def render_collection(collection, value_method, text_method, options={}, html_options={}) #:nodoc:
246
- item_wrapper_tag = options.fetch(:item_wrapper_tag, :span)
247
- item_wrapper_class = options[:item_wrapper_class]
248
-
249
- collection.map do |item|
250
- value = value_for_collection(item, value_method)
251
- text = value_for_collection(item, text_method)
252
- default_html_options = default_html_options_for_collection(item, value, options, html_options)
253
-
254
- rendered_item = yield item, value, text, default_html_options
255
-
256
- item_wrapper_tag ? @template.content_tag(item_wrapper_tag, rendered_item, :class => item_wrapper_class) : rendered_item
257
- end.join.html_safe
258
- end
259
-
260
- def value_for_collection(item, value) #:nodoc:
261
- value.respond_to?(:call) ? value.call(item) : item.send(value)
262
- end
263
-
264
- def wrap_rendered_collection(collection, options)
265
- wrapper_tag = options[:collection_wrapper_tag]
266
-
267
- if wrapper_tag
268
- wrapper_class = options[:collection_wrapper_class]
269
- @template.content_tag(wrapper_tag, collection, :class => wrapper_class)
270
- else
271
- collection
272
- end
273
- end
274
28
  end
275
29
  end
276
30
  end
@@ -279,77 +33,4 @@ module ActionView::Helpers
279
33
  class FormBuilder
280
34
  include SimpleForm::ActionViewExtensions::Builder
281
35
  end
282
-
283
- module FormOptionsHelper
284
- # Override Rails options_from_collection_for_select to handle lambdas/procs in
285
- # text and value methods, so it works the same way as collection_radio_buttons
286
- # and collection_check_boxes in SimpleForm. If none of text/value methods is a
287
- # callable object, then it just delegates back to original collection select.
288
- # FIXME: remove when support only Rails 4.0 forward
289
- # https://github.com/rails/rails/commit/9035324367526af0300477a58b6d3efc15d1a5a8
290
- alias :original_options_from_collection_for_select :options_from_collection_for_select
291
- def options_from_collection_for_select(collection, value_method, text_method, selected = nil)
292
- if value_method.respond_to?(:call) || text_method.respond_to?(:call)
293
- collection = collection.map do |item|
294
- value = value_for_collection(item, value_method)
295
- text = value_for_collection(item, text_method)
296
-
297
- [value, text]
298
- end
299
-
300
- value_method, text_method = :first, :last
301
- selected = extract_selected_and_disabled_and_call_procs selected, collection
302
- end
303
-
304
- original_options_from_collection_for_select collection, value_method, text_method, selected
305
- end
306
-
307
- private
308
-
309
- def extract_selected_and_disabled_and_call_procs(selected, collection)
310
- selected, disabled = extract_selected_and_disabled selected
311
- selected_disabled = { :selected => selected, :disabled => disabled }
312
-
313
- selected_disabled.each do |key, check|
314
- if check.is_a? Proc
315
- values = collection.map { |option| option.first if check.call(option.first) }
316
- selected_disabled[key] = values
317
- end
318
- end
319
- end
320
-
321
- def value_for_collection(item, value) #:nodoc:
322
- value.respond_to?(:call) ? value.call(item) : item.send(value)
323
- end
324
- end
325
-
326
- # Backport Rails fix to checkbox tag element, which does not generate the
327
- # hidden input when given nil as unchecked value. This is to make SimpleForm
328
- # collection check boxes helper to work fine with nested boolean style, when
329
- # they are wrapped in labels. Without that, clicking in the label would
330
- # actually change the hidden input, instead of the checkbox.
331
- # FIXME: remove when support only Rails >= 3.2.2.
332
- class InstanceTag
333
- def to_check_box_tag(options = {}, checked_value = "1", unchecked_value = "0")
334
- options = options.stringify_keys
335
- options["type"] = "checkbox"
336
- options["value"] = checked_value
337
- if options.has_key?("checked")
338
- cv = options.delete "checked"
339
- checked = cv == true || cv == "checked"
340
- else
341
- checked = self.class.check_box_checked?(value(object), checked_value)
342
- end
343
- options["checked"] = "checked" if checked
344
- if options["multiple"]
345
- add_default_name_and_id_for_value(checked_value, options)
346
- options.delete("multiple")
347
- else
348
- add_default_name_and_id(options)
349
- end
350
- hidden = unchecked_value ? tag("input", "name" => options["name"], "type" => "hidden", "value" => unchecked_value, "disabled" => options["disabled"]) : "".html_safe
351
- checkbox = tag("input", options)
352
- hidden + checkbox
353
- end
354
- end
355
36
  end