simple_form 1.2.0 → 1.2.1
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.
- data/README.rdoc +30 -30
- data/lib/generators/simple_form/USAGE +1 -1
- data/lib/generators/simple_form/install_generator.rb +5 -6
- data/lib/generators/simple_form/templates/_form.html.haml +18 -0
- data/lib/generators/simple_form/templates/en.yml +14 -0
- data/lib/generators/simple_form/templates/simple_form.rb +21 -8
- data/lib/simple_form.rb +29 -8
- data/lib/simple_form/action_view_extensions/form_helper.rb +24 -1
- data/lib/simple_form/components.rb +5 -4
- data/lib/simple_form/components/errors.rb +13 -5
- data/lib/simple_form/components/hints.rb +1 -1
- data/lib/simple_form/components/label_input.rb +13 -0
- data/lib/simple_form/components/labels.rb +1 -1
- data/lib/simple_form/components/wrapper.rb +12 -2
- data/lib/simple_form/error_notification.rb +44 -0
- data/lib/simple_form/form_builder.rb +17 -1
- data/lib/simple_form/inputs.rb +1 -0
- data/lib/simple_form/inputs/base.rb +17 -9
- data/lib/simple_form/inputs/boolean_input.rb +22 -0
- data/lib/simple_form/inputs/collection_input.rb +6 -6
- data/lib/simple_form/inputs/date_time_input.rb +4 -4
- data/lib/simple_form/inputs/mapping_input.rb +0 -1
- data/lib/simple_form/inputs/numeric_input.rb +5 -1
- data/lib/simple_form/inputs/string_input.rb +5 -6
- data/lib/simple_form/version.rb +1 -1
- data/test/action_view_extensions/builder_test.rb +18 -18
- data/test/action_view_extensions/form_helper_test.rb +5 -5
- data/test/components/error_test.rb +14 -5
- data/test/components/hint_test.rb +1 -1
- data/test/components/label_test.rb +4 -3
- data/test/components/wrapper_test.rb +54 -0
- data/test/error_notification_test.rb +61 -0
- data/test/form_builder_test.rb +31 -11
- data/test/inputs_test.rb +55 -51
- data/test/support/mock_controller.rb +4 -4
- data/test/support/models.rb +11 -8
- data/test/test_helper.rb +8 -9
- metadata +30 -4
@@ -36,7 +36,7 @@ module SimpleForm
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def label_html_options
|
39
|
-
label_options = html_options_for(:label, input_type, required_class)
|
39
|
+
label_options = html_options_for(:label, [input_type, required_class])
|
40
40
|
label_options[:for] = options[:input_html][:id] if options.key?(:input_html)
|
41
41
|
label_options
|
42
42
|
end
|
@@ -13,9 +13,19 @@ module SimpleForm
|
|
13
13
|
options[:wrapper_tag] || SimpleForm.wrapper_tag
|
14
14
|
end
|
15
15
|
|
16
|
+
def wrapper_class
|
17
|
+
options[:wrapper_class] || SimpleForm.wrapper_class
|
18
|
+
end
|
19
|
+
|
20
|
+
def wrapper_error_class
|
21
|
+
options[:wrapper_error_class] || SimpleForm.wrapper_error_class
|
22
|
+
end
|
23
|
+
|
16
24
|
def wrapper_html_options
|
17
|
-
|
25
|
+
css_classes = input_html_classes.unshift(wrapper_class)
|
26
|
+
css_classes << wrapper_error_class if has_errors?
|
27
|
+
html_options_for(:wrapper, css_classes)
|
18
28
|
end
|
19
29
|
end
|
20
30
|
end
|
21
|
-
end
|
31
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module SimpleForm
|
2
|
+
class ErrorNotification
|
3
|
+
delegate :object, :object_name, :template, :to => :@builder
|
4
|
+
|
5
|
+
def initialize(builder, options)
|
6
|
+
@builder = builder
|
7
|
+
@message = options.delete(:message)
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def render
|
12
|
+
if has_errors?
|
13
|
+
template.content_tag(error_notification_tag, error_message, html_options)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def error_message
|
20
|
+
@message || translate_error_notification
|
21
|
+
end
|
22
|
+
|
23
|
+
def error_notification_tag
|
24
|
+
SimpleForm.error_notification_tag
|
25
|
+
end
|
26
|
+
|
27
|
+
def has_errors?
|
28
|
+
object && object.respond_to?(:errors) && object.errors.present?
|
29
|
+
end
|
30
|
+
|
31
|
+
def html_options
|
32
|
+
@options[:class] = "error_notification #{@options[:class]}".strip
|
33
|
+
@options
|
34
|
+
end
|
35
|
+
|
36
|
+
def translate_error_notification
|
37
|
+
lookups = []
|
38
|
+
lookups << :"#{object_name}"
|
39
|
+
lookups << :default_message
|
40
|
+
lookups << "Some errors were found, please take a look:"
|
41
|
+
I18n.t(lookups.shift, :scope => :"simple_form.error_notification", :default => lookups)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -6,12 +6,13 @@ module SimpleForm
|
|
6
6
|
extend MapType
|
7
7
|
include SimpleForm::Inputs
|
8
8
|
|
9
|
-
map_type :
|
9
|
+
map_type :password, :text, :file, :to => SimpleForm::Inputs::MappingInput
|
10
10
|
map_type :string, :email, :url, :to => SimpleForm::Inputs::StringInput
|
11
11
|
map_type :integer, :decimal, :float, :to => SimpleForm::Inputs::NumericInput
|
12
12
|
map_type :select, :radio, :check_boxes, :to => SimpleForm::Inputs::CollectionInput
|
13
13
|
map_type :date, :time, :datetime, :to => SimpleForm::Inputs::DateTimeInput
|
14
14
|
map_type :country, :time_zone, :to => SimpleForm::Inputs::PriorityInput
|
15
|
+
map_type :boolean, :to => SimpleForm::Inputs::BooleanInput
|
15
16
|
|
16
17
|
# Basic input helper, combines all components in the stack to generate
|
17
18
|
# input html based on options the user define and some guesses through
|
@@ -215,6 +216,21 @@ module SimpleForm
|
|
215
216
|
SimpleForm::Inputs::Base.new(self).label
|
216
217
|
end
|
217
218
|
|
219
|
+
# Creates an error notification message that only appears when the form object
|
220
|
+
# has some error. You can give a specific message with the :message option,
|
221
|
+
# otherwise it will look for a message using I18n. All other options given are
|
222
|
+
# passed straight as html options to the html tag.
|
223
|
+
#
|
224
|
+
# == Examples
|
225
|
+
#
|
226
|
+
# f.error_notification
|
227
|
+
# f.error_notification :message => 'Something went wrong'
|
228
|
+
# f.error_notification :id => 'user_error_message', :class => 'form_error'
|
229
|
+
#
|
230
|
+
def error_notification(options={})
|
231
|
+
SimpleForm::ErrorNotification.new(self, options).render
|
232
|
+
end
|
233
|
+
|
218
234
|
private
|
219
235
|
|
220
236
|
# Setup default simple form attributes.
|
data/lib/simple_form/inputs.rb
CHANGED
@@ -2,6 +2,7 @@ module SimpleForm
|
|
2
2
|
module Inputs
|
3
3
|
autoload :Base, 'simple_form/inputs/base'
|
4
4
|
autoload :BlockInput, 'simple_form/inputs/block_input'
|
5
|
+
autoload :BooleanInput, 'simple_form/inputs/boolean_input'
|
5
6
|
autoload :CollectionInput, 'simple_form/inputs/collection_input'
|
6
7
|
autoload :DateTimeInput, 'simple_form/inputs/date_time_input'
|
7
8
|
autoload :HiddenInput, 'simple_form/inputs/hidden_input'
|
@@ -11,7 +11,7 @@ module SimpleForm
|
|
11
11
|
|
12
12
|
include SimpleForm::Components::Errors
|
13
13
|
include SimpleForm::Components::Hints
|
14
|
-
include SimpleForm::Components::
|
14
|
+
include SimpleForm::Components::LabelInput
|
15
15
|
include SimpleForm::Components::Wrapper
|
16
16
|
|
17
17
|
delegate :template, :object, :object_name, :attribute_name, :column,
|
@@ -30,16 +30,20 @@ module SimpleForm
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def input_html_options
|
33
|
-
html_options_for(:input,
|
33
|
+
html_options_for(:input, input_html_classes)
|
34
|
+
end
|
35
|
+
|
36
|
+
def input_html_classes
|
37
|
+
[input_type, required_class]
|
34
38
|
end
|
35
39
|
|
36
40
|
def render
|
37
|
-
content =
|
41
|
+
content = "".html_safe
|
42
|
+
components_list.each do |component|
|
38
43
|
next if options[component] == false
|
39
|
-
send(component)
|
44
|
+
content.safe_concat send(component).to_s
|
40
45
|
end
|
41
|
-
content
|
42
|
-
wrap(content.join.html_safe)
|
46
|
+
wrap(content)
|
43
47
|
end
|
44
48
|
|
45
49
|
protected
|
@@ -51,13 +55,17 @@ module SimpleForm
|
|
51
55
|
def attribute_required?
|
52
56
|
if options.key?(:required)
|
53
57
|
options[:required]
|
54
|
-
elsif
|
58
|
+
elsif object.class.respond_to?(:validators_on)
|
55
59
|
object.class.validators_on(attribute_name).any? { |v| v.kind == :presence }
|
56
60
|
else
|
57
|
-
|
61
|
+
attribute_required_by_default?
|
58
62
|
end
|
59
63
|
end
|
60
64
|
|
65
|
+
def attribute_required_by_default?
|
66
|
+
SimpleForm.required_by_default
|
67
|
+
end
|
68
|
+
|
61
69
|
def required_class
|
62
70
|
attribute_required? ? :required : :optional
|
63
71
|
end
|
@@ -68,7 +76,7 @@ module SimpleForm
|
|
68
76
|
end
|
69
77
|
|
70
78
|
# Retrieve options for the given namespace from the options hash
|
71
|
-
def html_options_for(namespace,
|
79
|
+
def html_options_for(namespace, extra)
|
72
80
|
html_options = options[:"#{namespace}_html"] || {}
|
73
81
|
html_options[:class] = (extra << html_options[:class]).join(' ').strip if extra.present?
|
74
82
|
html_options
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module SimpleForm
|
2
|
+
module Inputs
|
3
|
+
class BooleanInput < Base
|
4
|
+
def input
|
5
|
+
@builder.check_box(attribute_name, input_html_options)
|
6
|
+
end
|
7
|
+
|
8
|
+
def label_input
|
9
|
+
input + (options[:label] == false ? "" : label)
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
# Booleans are not required by default because in most of the cases
|
15
|
+
# it makes no sense marking them as required. The only exception is
|
16
|
+
# Terms of Use usually presented at most sites sign up screen.
|
17
|
+
def attribute_required_by_default?
|
18
|
+
false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -42,12 +42,12 @@ module SimpleForm
|
|
42
42
|
sample = collection.first || collection.last
|
43
43
|
|
44
44
|
case sample
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
45
|
+
when Array
|
46
|
+
label, value = :first, :last
|
47
|
+
when Integer
|
48
|
+
label, value = :to_s, :to_i
|
49
|
+
when String, NilClass
|
50
|
+
label, value = :to_s, :to_s
|
51
51
|
end
|
52
52
|
|
53
53
|
options[:label_method] ||= label || SimpleForm.collection_label_methods.find { |m| sample.respond_to?(m) }
|
@@ -7,10 +7,10 @@ module SimpleForm
|
|
7
7
|
|
8
8
|
def label_target
|
9
9
|
case input_type
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
when :date, :datetime
|
11
|
+
"#{attribute_name}_1i"
|
12
|
+
when :time
|
13
|
+
"#{attribute_name}_4i"
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
@@ -7,10 +7,14 @@ module SimpleForm
|
|
7
7
|
|
8
8
|
def input_html_options
|
9
9
|
input_options = super
|
10
|
-
input_options[:
|
10
|
+
input_options[:type] ||= "number"
|
11
11
|
input_options[:size] ||= SimpleForm.default_input_size
|
12
12
|
input_options
|
13
13
|
end
|
14
|
+
|
15
|
+
def input_html_classes
|
16
|
+
super.unshift("numeric")
|
17
|
+
end
|
14
18
|
end
|
15
19
|
end
|
16
20
|
end
|
@@ -9,15 +9,14 @@ module SimpleForm
|
|
9
9
|
input_options = super
|
10
10
|
input_options[:size] ||= [limit, SimpleForm.default_input_size].compact.min
|
11
11
|
input_options[:maxlength] ||= limit if limit
|
12
|
-
|
13
|
-
unless input_type == :string
|
14
|
-
input_options[:type] ||= input_type
|
15
|
-
input_options[:class] = "string #{input_options[:class]}"
|
16
|
-
end
|
17
|
-
|
12
|
+
input_options[:type] ||= input_type unless input_type == :string
|
18
13
|
input_options
|
19
14
|
end
|
20
15
|
|
16
|
+
def input_html_classes
|
17
|
+
input_type == :string ? super : super.unshift("string")
|
18
|
+
end
|
19
|
+
|
21
20
|
protected
|
22
21
|
|
23
22
|
def limit
|
data/lib/simple_form/version.rb
CHANGED
@@ -3,7 +3,7 @@ require 'test_helper'
|
|
3
3
|
class BuilderTest < ActionView::TestCase
|
4
4
|
# COLLECTION RADIO
|
5
5
|
test 'collection radio accepts a collection and generate inputs from value method' do
|
6
|
-
concat(form_for
|
6
|
+
concat(form_for(@user) do |f|
|
7
7
|
concat f.collection_radio :active, [true, false], :to_s, :to_s
|
8
8
|
end)
|
9
9
|
|
@@ -12,7 +12,7 @@ class BuilderTest < ActionView::TestCase
|
|
12
12
|
end
|
13
13
|
|
14
14
|
test 'collection radio accepts a collection and generate inputs from label method' do
|
15
|
-
concat(form_for
|
15
|
+
concat(form_for(@user) do |f|
|
16
16
|
concat f.collection_radio :active, [true, false], :to_s, :to_s
|
17
17
|
end)
|
18
18
|
|
@@ -21,7 +21,7 @@ class BuilderTest < ActionView::TestCase
|
|
21
21
|
end
|
22
22
|
|
23
23
|
test 'collection radio accepts checked item' do
|
24
|
-
concat(form_for
|
24
|
+
concat(form_for(@user) do |f|
|
25
25
|
concat f.collection_radio :active, [[1, true], [0, false]], :last, :first, :checked => true
|
26
26
|
end)
|
27
27
|
|
@@ -31,7 +31,7 @@ class BuilderTest < ActionView::TestCase
|
|
31
31
|
|
32
32
|
test 'collection radio accepts multiple disabled items' do
|
33
33
|
collection = [[1, true], [0, false], [2, 'other']]
|
34
|
-
concat(form_for
|
34
|
+
concat(form_for(@user) do |f|
|
35
35
|
concat f.collection_radio :active, collection, :last, :first, :disabled => [true, false]
|
36
36
|
end)
|
37
37
|
|
@@ -42,7 +42,7 @@ class BuilderTest < ActionView::TestCase
|
|
42
42
|
|
43
43
|
test 'collection radio accepts single disable item' do
|
44
44
|
collection = [[1, true], [0, false]]
|
45
|
-
concat(form_for
|
45
|
+
concat(form_for(@user) do |f|
|
46
46
|
concat f.collection_radio :active, collection, :last, :first, :disabled => true
|
47
47
|
end)
|
48
48
|
|
@@ -51,7 +51,7 @@ class BuilderTest < ActionView::TestCase
|
|
51
51
|
end
|
52
52
|
|
53
53
|
test 'collection radio accepts html options as input' do
|
54
|
-
concat(form_for
|
54
|
+
concat(form_for(@user) do |f|
|
55
55
|
concat f.collection_radio :active, [[1, true], [0, false]], :last, :first, {}, :class => 'radio'
|
56
56
|
end)
|
57
57
|
|
@@ -62,7 +62,7 @@ class BuilderTest < ActionView::TestCase
|
|
62
62
|
# COLLECTION CHECK BOX
|
63
63
|
test 'collection check box accepts a collection and generate a serie of checkboxes for value method' do
|
64
64
|
collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
|
65
|
-
concat(form_for
|
65
|
+
concat(form_for(@user) do |f|
|
66
66
|
concat f.collection_check_boxes :tag_ids, collection, :id, :name
|
67
67
|
end)
|
68
68
|
|
@@ -73,7 +73,7 @@ class BuilderTest < ActionView::TestCase
|
|
73
73
|
|
74
74
|
test 'collection check box accepts a collection and generate a serie of checkboxes with labels for label method' do
|
75
75
|
collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
|
76
|
-
concat(form_for
|
76
|
+
concat(form_for(@user) do |f|
|
77
77
|
concat f.collection_check_boxes :tag_ids, collection, :id, :name
|
78
78
|
end)
|
79
79
|
|
@@ -83,7 +83,7 @@ class BuilderTest < ActionView::TestCase
|
|
83
83
|
|
84
84
|
test 'collection check box accepts selected values as :checked option' do
|
85
85
|
collection = (1..3).map{|i| [i, "Tag #{i}"] }
|
86
|
-
concat(form_for
|
86
|
+
concat(form_for(@user) do |f|
|
87
87
|
concat f.collection_check_boxes :tag_ids, collection, :first, :last, :checked => [1, 3]
|
88
88
|
end)
|
89
89
|
|
@@ -94,7 +94,7 @@ class BuilderTest < ActionView::TestCase
|
|
94
94
|
|
95
95
|
test 'collection check box accepts a single checked value' do
|
96
96
|
collection = (1..3).map{|i| [i, "Tag #{i}"] }
|
97
|
-
concat(form_for
|
97
|
+
concat(form_for(@user) do |f|
|
98
98
|
concat f.collection_check_boxes :tag_ids, collection, :first, :last, :checked => 3
|
99
99
|
end)
|
100
100
|
|
@@ -105,7 +105,7 @@ class BuilderTest < ActionView::TestCase
|
|
105
105
|
|
106
106
|
test 'collection check box accepts multiple disabled items' do
|
107
107
|
collection = (1..3).map{|i| [i, "Tag #{i}"] }
|
108
|
-
concat(form_for
|
108
|
+
concat(form_for(@user) do |f|
|
109
109
|
concat f.collection_check_boxes :tag_ids, collection, :first, :last, :disabled => [1, 3]
|
110
110
|
end)
|
111
111
|
|
@@ -116,7 +116,7 @@ class BuilderTest < ActionView::TestCase
|
|
116
116
|
|
117
117
|
test 'collection check box accepts single disable item' do
|
118
118
|
collection = (1..3).map{|i| [i, "Tag #{i}"] }
|
119
|
-
concat(form_for
|
119
|
+
concat(form_for(@user) do |f|
|
120
120
|
concat f.collection_check_boxes :tag_ids, collection, :first, :last, :disabled => 1
|
121
121
|
end)
|
122
122
|
|
@@ -127,7 +127,7 @@ class BuilderTest < ActionView::TestCase
|
|
127
127
|
|
128
128
|
test 'collection check box accepts a proc to disabled items' do
|
129
129
|
collection = (1..3).map{|i| [i, "Tag #{i}"] }
|
130
|
-
concat(form_for
|
130
|
+
concat(form_for(@user) do |f|
|
131
131
|
concat f.collection_check_boxes :tag_ids, collection, :first, :last, :disabled => proc { |i| i.first == 1 }
|
132
132
|
end)
|
133
133
|
|
@@ -138,7 +138,7 @@ class BuilderTest < ActionView::TestCase
|
|
138
138
|
|
139
139
|
test 'collection check box accepts html options' do
|
140
140
|
collection = [[1, 'Tag 1'], [2, 'Tag 2']]
|
141
|
-
concat(form_for
|
141
|
+
concat(form_for(@user) do |f|
|
142
142
|
concat f.collection_check_boxes :tag_ids, collection, :first, :last, {}, :class => 'check'
|
143
143
|
end)
|
144
144
|
|
@@ -148,8 +148,8 @@ class BuilderTest < ActionView::TestCase
|
|
148
148
|
|
149
149
|
test 'collection check box with fields for' do
|
150
150
|
collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
|
151
|
-
concat(form_for
|
152
|
-
concat(f.fields_for
|
151
|
+
concat(form_for(@user) do |f|
|
152
|
+
concat(f.fields_for(:post) do |p|
|
153
153
|
concat p.collection_check_boxes :tag_ids, collection, :id, :name
|
154
154
|
end)
|
155
155
|
end)
|
@@ -163,8 +163,8 @@ class BuilderTest < ActionView::TestCase
|
|
163
163
|
|
164
164
|
# SIMPLE FIELDS
|
165
165
|
test 'simple fields for is available and yields an instance of FormBuilder' do
|
166
|
-
concat(form_for
|
167
|
-
concat(f.simple_fields_for
|
166
|
+
concat(form_for(@user) do |f|
|
167
|
+
concat(f.simple_fields_for(:posts) do |posts_form|
|
168
168
|
assert posts_form.instance_of?(SimpleForm::FormBuilder)
|
169
169
|
end)
|
170
170
|
end)
|