simple_form 2.1.3 → 3.0.0.beta1

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 (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