simple_form 3.0.3 → 3.1.0.rc1

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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -37
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +146 -71
  5. data/lib/generators/simple_form/install_generator.rb +2 -2
  6. data/lib/generators/simple_form/templates/README +3 -4
  7. data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +19 -3
  8. data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +83 -22
  9. data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +1 -1
  10. data/lib/generators/simple_form/templates/config/locales/simple_form.en.yml +7 -2
  11. data/lib/simple_form/action_view_extensions/form_helper.rb +1 -1
  12. data/lib/simple_form/components/errors.rb +27 -5
  13. data/lib/simple_form/components/hints.rb +2 -2
  14. data/lib/simple_form/components/html5.rb +1 -1
  15. data/lib/simple_form/components/label_input.rb +20 -2
  16. data/lib/simple_form/components/labels.rb +9 -5
  17. data/lib/simple_form/components/maxlength.rb +1 -1
  18. data/lib/simple_form/components/min_max.rb +1 -1
  19. data/lib/simple_form/components/pattern.rb +1 -1
  20. data/lib/simple_form/components/placeholders.rb +2 -2
  21. data/lib/simple_form/components/readonly.rb +1 -1
  22. data/lib/simple_form/form_builder.rb +92 -57
  23. data/lib/simple_form/helpers.rb +5 -5
  24. data/lib/simple_form/inputs/base.rb +34 -12
  25. data/lib/simple_form/inputs/block_input.rb +1 -1
  26. data/lib/simple_form/inputs/boolean_input.rb +23 -13
  27. data/lib/simple_form/inputs/collection_input.rb +32 -9
  28. data/lib/simple_form/inputs/collection_radio_buttons_input.rb +6 -11
  29. data/lib/simple_form/inputs/collection_select_input.rb +4 -2
  30. data/lib/simple_form/inputs/date_time_input.rb +12 -2
  31. data/lib/simple_form/inputs/file_input.rb +4 -2
  32. data/lib/simple_form/inputs/grouped_collection_select_input.rb +15 -3
  33. data/lib/simple_form/inputs/hidden_input.rb +4 -2
  34. data/lib/simple_form/inputs/numeric_input.rb +5 -4
  35. data/lib/simple_form/inputs/password_input.rb +4 -2
  36. data/lib/simple_form/inputs/priority_input.rb +4 -2
  37. data/lib/simple_form/inputs/range_input.rb +1 -1
  38. data/lib/simple_form/inputs/string_input.rb +4 -2
  39. data/lib/simple_form/inputs/text_input.rb +4 -2
  40. data/lib/simple_form/railtie.rb +7 -0
  41. data/lib/simple_form/tags.rb +7 -0
  42. data/lib/simple_form/version.rb +1 -1
  43. data/lib/simple_form/wrappers/builder.rb +5 -5
  44. data/lib/simple_form/wrappers/leaf.rb +28 -0
  45. data/lib/simple_form/wrappers/many.rb +5 -6
  46. data/lib/simple_form/wrappers/root.rb +1 -1
  47. data/lib/simple_form/wrappers/single.rb +5 -3
  48. data/lib/simple_form/wrappers.rb +1 -0
  49. data/lib/simple_form.rb +38 -6
  50. data/test/action_view_extensions/builder_test.rb +2 -2
  51. data/test/components/label_test.rb +1 -1
  52. data/test/form_builder/association_test.rb +17 -0
  53. data/test/form_builder/error_notification_test.rb +1 -1
  54. data/test/form_builder/error_test.rb +51 -32
  55. data/test/form_builder/general_test.rb +2 -2
  56. data/test/form_builder/input_field_test.rb +25 -1
  57. data/test/form_builder/label_test.rb +24 -1
  58. data/test/form_builder/wrapper_test.rb +67 -0
  59. data/test/generators/simple_form_generator_test.rb +2 -2
  60. data/test/inputs/boolean_input_test.rb +50 -2
  61. data/test/inputs/collection_check_boxes_input_test.rb +40 -11
  62. data/test/inputs/collection_radio_buttons_input_test.rb +76 -17
  63. data/test/inputs/collection_select_input_test.rb +108 -3
  64. data/test/inputs/datetime_input_test.rb +105 -38
  65. data/test/inputs/discovery_test.rb +12 -1
  66. data/test/inputs/grouped_collection_select_input_test.rb +36 -0
  67. data/test/inputs/string_input_test.rb +20 -0
  68. data/test/simple_form_test.rb +8 -0
  69. data/test/support/discovery_inputs.rb +12 -2
  70. data/test/support/misc_helpers.rb +49 -5
  71. data/test/support/models.rb +49 -24
  72. metadata +6 -5
@@ -1,45 +1,106 @@
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.button_class = 'btn btn-default'
4
+ config.boolean_label_class = nil
5
+
6
+ config.wrappers :vertical_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
4
7
  b.use :html5
5
8
  b.use :placeholder
6
- b.use :label
7
- b.wrapper tag: 'div', class: 'controls' do |ba|
9
+ b.use :label, class: 'control-label'
10
+
11
+ b.wrapper tag: 'div' do |ba|
12
+ ba.use :input, class: 'form-control'
13
+ ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
14
+ ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
15
+ end
16
+ end
17
+
18
+ config.wrappers :vertical_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
19
+ b.use :html5
20
+ b.use :placeholder
21
+ b.use :label, class: 'control-label'
22
+
23
+ b.wrapper tag: 'div' do |ba|
8
24
  ba.use :input
9
- ba.use :error, wrap_with: { tag: 'span', class: 'help-inline' }
25
+ ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
10
26
  ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
11
27
  end
12
28
  end
13
29
 
14
- config.wrappers :prepend, tag: 'div', class: "control-group", error_class: 'error' do |b|
30
+ config.wrappers :vertical_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
15
31
  b.use :html5
16
32
  b.use :placeholder
17
- b.use :label
18
- b.wrapper tag: 'div', class: 'controls' do |input|
19
- input.wrapper tag: 'div', class: 'input-prepend' do |prepend|
20
- prepend.use :input
21
- end
22
- input.use :hint, wrap_with: { tag: 'span', class: 'help-block' }
23
- input.use :error, wrap_with: { tag: 'span', class: 'help-inline' }
33
+
34
+ b.wrapper tag: 'div', class: 'checkbox' do |ba|
35
+ ba.use :label_input
36
+ end
37
+
38
+ b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
39
+ b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
40
+ end
41
+
42
+ config.wrappers :vertical_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
43
+ b.use :html5
44
+ b.use :placeholder
45
+ b.use :label_input
46
+ b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
47
+ b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
48
+ end
49
+
50
+ config.wrappers :horizontal_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
51
+ b.use :html5
52
+ b.use :placeholder
53
+ b.use :label, class: 'col-sm-3 control-label'
54
+
55
+ b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
56
+ ba.use :input, class: 'form-control'
57
+ ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
58
+ ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
24
59
  end
25
60
  end
26
61
 
27
- config.wrappers :append, tag: 'div', class: "control-group", error_class: 'error' do |b|
62
+ config.wrappers :horizontal_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
28
63
  b.use :html5
29
64
  b.use :placeholder
30
- b.use :label
31
- b.wrapper tag: 'div', class: 'controls' do |input|
32
- input.wrapper tag: 'div', class: 'input-append' do |append|
33
- append.use :input
65
+ b.use :label, class: 'col-sm-3 control-label'
66
+
67
+ b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
68
+ ba.use :input
69
+ ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
70
+ ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
71
+ end
72
+ end
73
+
74
+ config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
75
+ b.use :html5
76
+ b.use :placeholder
77
+
78
+ b.wrapper tag: 'div', class: 'col-sm-offset-3 col-sm-9' do |wr|
79
+ wr.wrapper tag: 'div', class: 'checkbox' do |ba|
80
+ ba.use :label_input, class: 'col-sm-9'
34
81
  end
35
- input.use :hint, wrap_with: { tag: 'span', class: 'help-block' }
36
- input.use :error, wrap_with: { tag: 'span', class: 'help-inline' }
82
+
83
+ wr.use :error, wrap_with: { tag: 'span', class: 'help-block' }
84
+ wr.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
85
+ end
86
+ end
87
+
88
+ config.wrappers :horizontal_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
89
+ b.use :html5
90
+ b.use :placeholder
91
+
92
+ b.use :label, class: 'col-sm-3 control-label'
93
+
94
+ b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
95
+ ba.use :input
96
+ ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
97
+ ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
37
98
  end
38
99
  end
39
100
 
40
- # Wrappers for forms and inputs using the Twitter Bootstrap toolkit.
41
- # Check the Bootstrap docs (http://twitter.github.com/bootstrap)
101
+ # Wrappers for forms and inputs using the Bootstrap toolkit.
102
+ # Check the Bootstrap docs (http://getbootstrap.com)
42
103
  # to learn about the different styles for forms and inputs,
43
104
  # buttons and other elements.
44
- config.default_wrapper = :bootstrap
105
+ config.default_wrapper = :vertical_form
45
106
  end
@@ -8,7 +8,7 @@ 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, class: :error }
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.
@@ -10,7 +10,7 @@ en:
10
10
  # html: '<abbr title="required">*</abbr>'
11
11
  error_notification:
12
12
  default_message: "Please review the problems below:"
13
- # Labels and hints examples
13
+ # Examples
14
14
  # labels:
15
15
  # defaults:
16
16
  # password: 'Password'
@@ -23,4 +23,9 @@ en:
23
23
  # defaults:
24
24
  # username: 'User name to sign in.'
25
25
  # password: 'No special characters, please.'
26
-
26
+ # include_blanks:
27
+ # defaults:
28
+ # age: 'Rather not say'
29
+ # prompts:
30
+ # defaults:
31
+ # age: 'Select your age'
@@ -10,7 +10,7 @@ module SimpleForm
10
10
  #
11
11
  module FormHelper
12
12
 
13
- def simple_form_for(record, options={}, &block)
13
+ def simple_form_for(record, options = {}, &block)
14
14
  options[:builder] ||= SimpleForm::FormBuilder
15
15
  options[:html] ||= {}
16
16
  unless options[:html].key?(:novalidate)
@@ -1,10 +1,14 @@
1
1
  module SimpleForm
2
2
  module Components
3
3
  module Errors
4
- def error
4
+ def error(wrapper_options = nil)
5
5
  error_text if has_errors?
6
6
  end
7
7
 
8
+ def full_error(wrapper_options = nil)
9
+ full_error_text if options[:error] != false && has_errors?
10
+ end
11
+
8
12
  def has_errors?
9
13
  object && object.respond_to?(:errors) && errors.present?
10
14
  end
@@ -12,9 +16,15 @@ module SimpleForm
12
16
  protected
13
17
 
14
18
  def error_text
15
- text = has_error_in_options? ? options[:error] : errors.send(error_method)
19
+ text = has_custom_error? ? options[:error] : errors.send(error_method)
20
+
21
+ "#{html_escape(options[:error_prefix])} #{text}".lstrip.html_safe
22
+ end
23
+
24
+ def full_error_text
25
+ text = has_custom_error? ? options[:error] : full_errors.send(error_method)
16
26
 
17
- "#{html_escape(options[:error_prefix])} #{html_escape(text)}".lstrip.html_safe
27
+ text.html_safe
18
28
  end
19
29
 
20
30
  def error_method
@@ -25,16 +35,28 @@ module SimpleForm
25
35
  @errors ||= (errors_on_attribute + errors_on_association).compact
26
36
  end
27
37
 
38
+ def full_errors
39
+ @full_errors ||= (full_errors_on_attribute + full_errors_on_association).compact
40
+ end
41
+
28
42
  def errors_on_attribute
29
43
  object.errors[attribute_name]
30
44
  end
31
45
 
46
+ def full_errors_on_attribute
47
+ object.errors.full_messages_for(attribute_name)
48
+ end
49
+
32
50
  def errors_on_association
33
51
  reflection ? object.errors[reflection.name] : []
34
52
  end
35
53
 
36
- def has_error_in_options?
37
- options[:error] && !options[:error].nil?
54
+ def full_errors_on_association
55
+ reflection ? object.full_messages_for(reflection.name) : []
56
+ end
57
+
58
+ def has_custom_error?
59
+ options[:error].is_a?(String)
38
60
  end
39
61
  end
40
62
  end
@@ -2,14 +2,14 @@ module SimpleForm
2
2
  module Components
3
3
  # Needs to be enabled in order to do automatic lookups.
4
4
  module Hints
5
- def hint
5
+ def hint(wrapper_options = nil)
6
6
  @hint ||= begin
7
7
  hint = options[:hint]
8
8
 
9
9
  if hint.is_a?(String)
10
10
  html_escape(hint)
11
11
  else
12
- content = translate(:hints)
12
+ content = translate_from_namespace(:hints)
13
13
  content.html_safe if content
14
14
  end
15
15
  end
@@ -5,7 +5,7 @@ module SimpleForm
5
5
  @html5 = false
6
6
  end
7
7
 
8
- def html5
8
+ def html5(wrapper_options = nil)
9
9
  @html5 = true
10
10
  if has_required?
11
11
  input_html_options[:required] = true
@@ -7,8 +7,26 @@ module SimpleForm
7
7
  include SimpleForm::Components::Labels
8
8
  end
9
9
 
10
- def label_input
11
- options[:label] == false ? input : (label + input)
10
+ def label_input(wrapper_options = nil)
11
+ if options[:label] == false
12
+ deprecated_component(:input, wrapper_options)
13
+ else
14
+ deprecated_component(:label, wrapper_options) + deprecated_component(:input, wrapper_options)
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def deprecated_component(namespace, wrapper_options)
21
+ method = method(namespace)
22
+
23
+ if method.arity == 0
24
+ ActiveSupport::Deprecation.warn(SimpleForm::CUSTOM_INPUT_DEPRECATION_WARN % { name: namespace })
25
+
26
+ method.call
27
+ else
28
+ method.call(wrapper_options)
29
+ end
12
30
  end
13
31
  end
14
32
  end
@@ -21,16 +21,19 @@ module SimpleForm
21
21
  end
22
22
  end
23
23
 
24
- def label
24
+ def label(wrapper_options = nil)
25
+ label_options = merge_wrapper_options(label_html_options, wrapper_options)
26
+
25
27
  if generate_label_for_attribute?
26
- @builder.label(label_target, label_text, label_html_options)
28
+ @builder.label(label_target, label_text, label_options)
27
29
  else
28
- template.label_tag(nil, label_text, label_html_options)
30
+ template.label_tag(nil, label_text, label_options)
29
31
  end
30
32
  end
31
33
 
32
34
  def label_text
33
- SimpleForm.label_text.call(html_escape(raw_label_text), required_label_text).strip.html_safe
35
+ label_text = options[:label_text] || SimpleForm.label_text
36
+ label_text.call(html_escape(raw_label_text), required_label_text, options[:label].present?).strip.html_safe
34
37
  end
35
38
 
36
39
  def label_target
@@ -46,6 +49,7 @@ module SimpleForm
46
49
  if options.key?(:input_html) && options[:input_html].key?(:id)
47
50
  label_options[:for] = options[:input_html][:id]
48
51
  end
52
+
49
53
  label_options
50
54
  end
51
55
 
@@ -62,7 +66,7 @@ module SimpleForm
62
66
 
63
67
  # First check labels translation and then human attribute name.
64
68
  def label_translation #:nodoc:
65
- if SimpleForm.translate_labels && (translated_label = translate(:labels))
69
+ if SimpleForm.translate_labels && (translated_label = translate_from_namespace(:labels))
66
70
  translated_label
67
71
  elsif object.class.respond_to?(:human_attribute_name)
68
72
  object.class.human_attribute_name(reflection_or_attribute_name.to_s)
@@ -2,7 +2,7 @@ module SimpleForm
2
2
  module Components
3
3
  # Needs to be enabled in order to do automatic lookups.
4
4
  module Maxlength
5
- def maxlength
5
+ def maxlength(wrapper_options = nil)
6
6
  input_html_options[:maxlength] ||= maximum_length_from_validation || limit
7
7
  nil
8
8
  end
@@ -1,7 +1,7 @@
1
1
  module SimpleForm
2
2
  module Components
3
3
  module MinMax
4
- def min_max
4
+ def min_max(wrapper_options = nil)
5
5
  if numeric_validator = find_numericality_validator
6
6
  validator_options = numeric_validator.options
7
7
  input_html_options[:min] ||= minimum_value(validator_options)
@@ -2,7 +2,7 @@ module SimpleForm
2
2
  module Components
3
3
  # Needs to be enabled in order to do automatic lookups.
4
4
  module Pattern
5
- def pattern
5
+ def pattern(wrapper_options = nil)
6
6
  input_html_options[:pattern] ||= pattern_source
7
7
  nil
8
8
  end
@@ -2,14 +2,14 @@ module SimpleForm
2
2
  module Components
3
3
  # Needs to be enabled in order to do automatic lookups.
4
4
  module Placeholders
5
- def placeholder
5
+ def placeholder(wrapper_options = nil)
6
6
  input_html_options[:placeholder] ||= placeholder_text
7
7
  nil
8
8
  end
9
9
 
10
10
  def placeholder_text
11
11
  placeholder = options[:placeholder]
12
- placeholder.is_a?(String) ? placeholder : translate(:placeholders)
12
+ placeholder.is_a?(String) ? placeholder : translate_from_namespace(:placeholders)
13
13
  end
14
14
  end
15
15
  end
@@ -2,7 +2,7 @@ module SimpleForm
2
2
  module Components
3
3
  # Needs to be enabled in order to do automatic lookups.
4
4
  module Readonly
5
- def readonly
5
+ def readonly(wrapper_options = nil)
6
6
  if readonly_attribute? && !has_readonly?
7
7
  input_html_options[:readonly] ||= true
8
8
  input_html_classes << :readonly