simple_form 3.0.4 → 3.1.0.rc1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +32 -43
- data/MIT-LICENSE +1 -1
- data/README.md +146 -71
- data/lib/generators/simple_form/install_generator.rb +2 -2
- data/lib/generators/simple_form/templates/README +3 -4
- data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +19 -3
- data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +83 -22
- data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +1 -1
- data/lib/generators/simple_form/templates/config/locales/simple_form.en.yml +7 -2
- data/lib/simple_form.rb +38 -6
- data/lib/simple_form/action_view_extensions/form_helper.rb +1 -1
- data/lib/simple_form/components/errors.rb +27 -5
- data/lib/simple_form/components/hints.rb +2 -2
- data/lib/simple_form/components/html5.rb +1 -1
- data/lib/simple_form/components/label_input.rb +20 -2
- data/lib/simple_form/components/labels.rb +9 -5
- data/lib/simple_form/components/maxlength.rb +1 -1
- data/lib/simple_form/components/min_max.rb +1 -1
- data/lib/simple_form/components/pattern.rb +1 -1
- data/lib/simple_form/components/placeholders.rb +2 -2
- data/lib/simple_form/components/readonly.rb +1 -1
- data/lib/simple_form/form_builder.rb +92 -59
- data/lib/simple_form/helpers.rb +5 -5
- data/lib/simple_form/inputs/base.rb +34 -12
- data/lib/simple_form/inputs/block_input.rb +1 -1
- data/lib/simple_form/inputs/boolean_input.rb +23 -13
- data/lib/simple_form/inputs/collection_input.rb +32 -9
- data/lib/simple_form/inputs/collection_radio_buttons_input.rb +6 -11
- data/lib/simple_form/inputs/collection_select_input.rb +4 -2
- data/lib/simple_form/inputs/date_time_input.rb +12 -2
- data/lib/simple_form/inputs/file_input.rb +4 -2
- data/lib/simple_form/inputs/grouped_collection_select_input.rb +15 -3
- data/lib/simple_form/inputs/hidden_input.rb +4 -2
- data/lib/simple_form/inputs/numeric_input.rb +5 -4
- data/lib/simple_form/inputs/password_input.rb +4 -2
- data/lib/simple_form/inputs/priority_input.rb +4 -2
- data/lib/simple_form/inputs/range_input.rb +1 -1
- data/lib/simple_form/inputs/string_input.rb +4 -2
- data/lib/simple_form/inputs/text_input.rb +4 -2
- data/lib/simple_form/railtie.rb +7 -0
- data/lib/simple_form/tags.rb +7 -0
- data/lib/simple_form/version.rb +1 -1
- data/lib/simple_form/wrappers.rb +1 -0
- data/lib/simple_form/wrappers/builder.rb +5 -5
- data/lib/simple_form/wrappers/leaf.rb +28 -0
- data/lib/simple_form/wrappers/many.rb +5 -6
- data/lib/simple_form/wrappers/root.rb +1 -1
- data/lib/simple_form/wrappers/single.rb +5 -3
- data/test/action_view_extensions/builder_test.rb +2 -2
- data/test/components/label_test.rb +1 -1
- data/test/form_builder/association_test.rb +17 -0
- data/test/form_builder/error_notification_test.rb +1 -1
- data/test/form_builder/error_test.rb +51 -32
- data/test/form_builder/general_test.rb +2 -2
- data/test/form_builder/input_field_test.rb +21 -37
- data/test/form_builder/label_test.rb +24 -1
- data/test/form_builder/wrapper_test.rb +67 -0
- data/test/generators/simple_form_generator_test.rb +2 -2
- data/test/inputs/boolean_input_test.rb +50 -2
- data/test/inputs/collection_check_boxes_input_test.rb +40 -11
- data/test/inputs/collection_radio_buttons_input_test.rb +76 -17
- data/test/inputs/collection_select_input_test.rb +108 -3
- data/test/inputs/datetime_input_test.rb +105 -38
- data/test/inputs/discovery_test.rb +12 -1
- data/test/inputs/grouped_collection_select_input_test.rb +36 -0
- data/test/inputs/string_input_test.rb +20 -0
- data/test/simple_form_test.rb +8 -0
- data/test/support/discovery_inputs.rb +12 -2
- data/test/support/misc_helpers.rb +46 -8
- data/test/support/models.rb +49 -24
- metadata +7 -7
@@ -1,18 +1,69 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
require 'test_helper'
|
3
3
|
|
4
|
-
# Tests for
|
5
|
-
class
|
6
|
-
|
7
|
-
|
4
|
+
# Tests for datetime, date and time inputs when HTML5 compatibility is enabled in the wrapper.
|
5
|
+
class DateTimeInputWithHtml5Test < ActionView::TestCase
|
6
|
+
test 'input should generate a datetime input for datetime attributes if HTML5 compatibility is explicitly enbled' do
|
7
|
+
with_input_for @user, :created_at, :datetime, html5: true
|
8
|
+
|
9
|
+
assert_select 'input[type="datetime"]'
|
10
|
+
end
|
11
|
+
|
12
|
+
test 'input should generate a datetime select for datetime attributes' do
|
8
13
|
with_input_for @user, :created_at, :datetime
|
9
|
-
|
10
|
-
|
14
|
+
|
15
|
+
assert_select 'select.datetime'
|
16
|
+
end
|
17
|
+
|
18
|
+
test 'input should generate a date input for date attributes if HTML5 compatibility is explicitly enbled' do
|
19
|
+
with_input_for @user, :born_at, :date, html5: true
|
20
|
+
|
21
|
+
assert_select 'input[type="date"]'
|
22
|
+
end
|
23
|
+
|
24
|
+
test 'input should generate a date select for date attributes' do
|
25
|
+
with_input_for @user, :born_at, :date
|
26
|
+
|
27
|
+
assert_select 'select.date'
|
28
|
+
end
|
29
|
+
|
30
|
+
test 'input should generate a time input for time attributes if HTML5 compatibility is explicitly enbled' do
|
31
|
+
with_input_for @user, :delivery_time, :time, html5: true
|
32
|
+
|
33
|
+
assert_select 'input[type="time"]'
|
34
|
+
end
|
35
|
+
|
36
|
+
test 'input should generate a time select for time attributes' do
|
37
|
+
with_input_for @user, :delivery_time, :time
|
38
|
+
|
39
|
+
assert_select 'select.time'
|
40
|
+
end
|
41
|
+
|
42
|
+
test 'input should generate required html attribute' do
|
43
|
+
with_input_for @user, :delivery_time, :time, required: true, html5: true
|
44
|
+
assert_select 'input.required'
|
45
|
+
assert_select 'input[required]'
|
46
|
+
end
|
47
|
+
|
48
|
+
test 'input should have an aria-required html attribute' do
|
49
|
+
with_input_for @user, :delivery_time, :time, required: true, html5: true
|
50
|
+
assert_select 'input[aria-required=true]'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Tests for datetime, date and time inputs when HTML5 compatibility is enabled in the wrapper.
|
55
|
+
class DateTimeInputWithoutHtml5Test < ActionView::TestCase
|
56
|
+
test 'input should generate a datetime select by default for datetime attributes' do
|
57
|
+
swap_wrapper do
|
58
|
+
with_input_for @user, :created_at, :datetime
|
59
|
+
1.upto(5) do |i|
|
60
|
+
assert_select "form select.datetime#user_created_at_#{i}i"
|
61
|
+
end
|
11
62
|
end
|
12
63
|
end
|
13
64
|
|
14
65
|
test 'input should be able to pass options to datetime select' do
|
15
|
-
with_input_for @user, :created_at, :datetime,
|
66
|
+
with_input_for @user, :created_at, :datetime, html5: false,
|
16
67
|
disabled: true, prompt: { year: 'ano', month: 'mês', day: 'dia' }
|
17
68
|
|
18
69
|
assert_select 'select.datetime[disabled=disabled]'
|
@@ -21,16 +72,26 @@ class DateTimeInputTest < ActionView::TestCase
|
|
21
72
|
assert_select 'select.datetime option', 'dia'
|
22
73
|
end
|
23
74
|
|
75
|
+
test 'input should generate a datetime input for datetime attributes if HTML5 compatibility is explicitly enabled' do
|
76
|
+
swap_wrapper do
|
77
|
+
with_input_for @user, :created_at, :datetime, html5: true
|
78
|
+
|
79
|
+
assert_select 'input[type="datetime"]'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
24
83
|
test 'input should generate a date select for date attributes' do
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
84
|
+
swap_wrapper do
|
85
|
+
with_input_for @user, :born_at, :date
|
86
|
+
assert_select 'select.date#user_born_at_1i'
|
87
|
+
assert_select 'select.date#user_born_at_2i'
|
88
|
+
assert_select 'select.date#user_born_at_3i'
|
89
|
+
assert_no_select 'select.date#user_born_at_4i'
|
90
|
+
end
|
30
91
|
end
|
31
92
|
|
32
93
|
test 'input should be able to pass options to date select' do
|
33
|
-
with_input_for @user, :born_at, :date, as: :date,
|
94
|
+
with_input_for @user, :born_at, :date, as: :date, html5: false,
|
34
95
|
disabled: true, prompt: { year: 'ano', month: 'mês', day: 'dia' }
|
35
96
|
|
36
97
|
assert_select 'select.date[disabled=disabled]'
|
@@ -40,21 +101,31 @@ class DateTimeInputTest < ActionView::TestCase
|
|
40
101
|
end
|
41
102
|
|
42
103
|
test 'input should be able to pass :default to date select' do
|
43
|
-
with_input_for @user, :born_at, :date, default: Date.today
|
104
|
+
with_input_for @user, :born_at, :date, default: Date.today, html5: false
|
44
105
|
assert_select "select.date option[value=#{Date.today.year}][selected=selected]"
|
45
106
|
end
|
46
107
|
|
108
|
+
test 'input should generate a date input for date attributes if HTML5 compatibility is explicitly enabled' do
|
109
|
+
swap_wrapper do
|
110
|
+
with_input_for @user, :born_at, :date, html5: true
|
111
|
+
|
112
|
+
assert_select 'input[type="date"]'
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
47
116
|
test 'input should generate a time select for time attributes' do
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
117
|
+
swap_wrapper do
|
118
|
+
with_input_for @user, :delivery_time, :time
|
119
|
+
assert_select 'input[type=hidden]#user_delivery_time_1i'
|
120
|
+
assert_select 'input[type=hidden]#user_delivery_time_2i'
|
121
|
+
assert_select 'input[type=hidden]#user_delivery_time_3i'
|
122
|
+
assert_select 'select.time#user_delivery_time_4i'
|
123
|
+
assert_select 'select.time#user_delivery_time_5i'
|
124
|
+
end
|
54
125
|
end
|
55
126
|
|
56
127
|
test 'input should be able to pass options to time select' do
|
57
|
-
with_input_for @user, :delivery_time, :time, required: true,
|
128
|
+
with_input_for @user, :delivery_time, :time, required: true, html5: false,
|
58
129
|
disabled: true, prompt: { hour: 'hora', minute: 'minuto' }
|
59
130
|
|
60
131
|
assert_select 'select.time[disabled=disabled]'
|
@@ -62,44 +133,40 @@ class DateTimeInputTest < ActionView::TestCase
|
|
62
133
|
assert_select 'select.time option', 'minuto'
|
63
134
|
end
|
64
135
|
|
136
|
+
test 'input should generate a time input for time attributes if HTML5 compatibility is explicitly enabled' do
|
137
|
+
swap_wrapper do
|
138
|
+
with_input_for @user, :delivery_time, :time, html5: true
|
139
|
+
|
140
|
+
assert_select 'input[type="time"]'
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
65
144
|
test 'label should use i18n to get target for date input type' do
|
66
145
|
store_translations(:en, date: { order: ['month', 'day', 'year'] }) do
|
67
|
-
with_input_for :project, :created_at, :date
|
146
|
+
with_input_for :project, :created_at, :date, html5: false
|
68
147
|
assert_select 'label[for=project_created_at_2i]'
|
69
148
|
end
|
70
149
|
end
|
71
150
|
|
72
151
|
test 'label should use i18n to get target for datetime input type' do
|
73
152
|
store_translations(:en, date: { order: ['month', 'day', 'year'] }) do
|
74
|
-
with_input_for :project, :created_at, :datetime
|
153
|
+
with_input_for :project, :created_at, :datetime, html5: false
|
75
154
|
assert_select 'label[for=project_created_at_2i]'
|
76
155
|
end
|
77
156
|
end
|
78
157
|
|
79
158
|
test 'label should use order to get target when date input type' do
|
80
|
-
with_input_for :project, :created_at, :date, order: ['month', 'year', 'day']
|
159
|
+
with_input_for :project, :created_at, :date, order: ['month', 'year', 'day'], html5: false
|
81
160
|
assert_select 'label[for=project_created_at_2i]'
|
82
161
|
end
|
83
162
|
|
84
163
|
test 'label should use order to get target when datetime input type' do
|
85
|
-
with_input_for :project, :created_at, :datetime, order: ['month', 'year', 'day']
|
164
|
+
with_input_for :project, :created_at, :datetime, order: ['month', 'year', 'day'], html5: false
|
86
165
|
assert_select 'label[for=project_created_at_2i]'
|
87
166
|
end
|
88
167
|
|
89
168
|
test 'label should point to first option when time input type' do
|
90
|
-
with_input_for :project, :created_at, :time
|
169
|
+
with_input_for :project, :created_at, :time, html5: false
|
91
170
|
assert_select 'label[for=project_created_at_4i]'
|
92
171
|
end
|
93
|
-
|
94
|
-
test 'date time input should generate required html attribute' do
|
95
|
-
with_input_for @user, :delivery_time, :time, required: true
|
96
|
-
assert_select 'select.required'
|
97
|
-
assert_select 'select[required]'
|
98
|
-
end
|
99
|
-
|
100
|
-
test 'date time input has an aria-required html attribute' do
|
101
|
-
with_input_for @user, :delivery_time, :time, required: true
|
102
|
-
assert_select 'select.required'
|
103
|
-
assert_select 'select[aria-required=true]'
|
104
|
-
end
|
105
172
|
end
|
@@ -2,7 +2,7 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class DiscoveryTest < ActionView::TestCase
|
4
4
|
# Setup new inputs and remove them after the test.
|
5
|
-
def discovery(value=false)
|
5
|
+
def discovery(value = false)
|
6
6
|
swap SimpleForm, cache_discovery: value do
|
7
7
|
begin
|
8
8
|
load "support/discovery_inputs.rb"
|
@@ -12,6 +12,7 @@ class DiscoveryTest < ActionView::TestCase
|
|
12
12
|
Object.send :remove_const, :StringInput
|
13
13
|
Object.send :remove_const, :NumericInput
|
14
14
|
Object.send :remove_const, :CustomizedInput
|
15
|
+
Object.send :remove_const, :DeprecatedInput
|
15
16
|
Object.send :remove_const, :CollectionSelectInput
|
16
17
|
end
|
17
18
|
end
|
@@ -66,4 +67,14 @@ class DiscoveryTest < ActionView::TestCase
|
|
66
67
|
assert_select 'form select#user_active.select.chosen'
|
67
68
|
end
|
68
69
|
end
|
70
|
+
|
71
|
+
test 'inputs method without wrapper_options are deprecated' do
|
72
|
+
discovery do
|
73
|
+
assert_deprecated do
|
74
|
+
with_form_for @user, :name, as: :deprecated
|
75
|
+
end
|
76
|
+
|
77
|
+
assert_select 'form section input#user_name.string'
|
78
|
+
end
|
79
|
+
end
|
69
80
|
end
|
@@ -79,6 +79,42 @@ class GroupedCollectionSelectInputTest < ActionView::TestCase
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
+
test 'grouped collection finds default label methods on the group objects' do
|
83
|
+
option_list = ['Jose', 'Carlos']
|
84
|
+
|
85
|
+
GroupedClass = Struct.new(:to_label, :options)
|
86
|
+
group = GroupedClass.new("Authors", option_list)
|
87
|
+
|
88
|
+
with_input_for @user, :tag_ids, :grouped_select,
|
89
|
+
collection: [group],
|
90
|
+
group_method: :options
|
91
|
+
|
92
|
+
assert_select 'select.grouped_select#user_tag_ids' do
|
93
|
+
assert_select 'optgroup[label=Authors]' do
|
94
|
+
assert_select 'option', 'Jose'
|
95
|
+
assert_select 'option', 'Carlos'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
test 'grouped collections finds the default label method from the first non-empty object' do
|
101
|
+
Agent = Struct.new(:id, :name)
|
102
|
+
agents = [["First", []], ["Second", [Agent.new(7, 'Bond'), Agent.new(47, 'Hitman')]]]
|
103
|
+
|
104
|
+
with_input_for @user, :tag_ids, :grouped_select,
|
105
|
+
collection: agents,
|
106
|
+
group_label_method: :first,
|
107
|
+
group_method: :last,
|
108
|
+
include_blank: false
|
109
|
+
|
110
|
+
assert_select 'select.grouped_select#user_tag_ids' do
|
111
|
+
assert_select 'optgroup[label=Second]' do
|
112
|
+
assert_select 'option[value=7]', 'Bond'
|
113
|
+
assert_select 'option[value=47]', 'Hitman'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
82
118
|
test 'grouped collection accepts label and value methods options' do
|
83
119
|
with_input_for @user, :tag_ids, :grouped_select,
|
84
120
|
collection: { 'Authors' => ['Jose', 'Carlos'] },
|
@@ -104,6 +104,26 @@ class StringInputTest < ActionView::TestCase
|
|
104
104
|
end
|
105
105
|
end
|
106
106
|
|
107
|
+
test 'input should use custom i18n scope to translate placeholder text' do
|
108
|
+
store_translations(:en, my_scope: { placeholders: { user: {
|
109
|
+
name: 'Name goes here'
|
110
|
+
} } }) do
|
111
|
+
swap SimpleForm, i18n_scope: :my_scope do
|
112
|
+
with_input_for @user, :name, :string
|
113
|
+
assert_select 'input.string[placeholder=Name goes here]'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
test 'input should translate a key prefixed with _html and return the html markup' do
|
119
|
+
store_translations(:en, simple_form: { labels: { user: {
|
120
|
+
name_html: '<b>Name</b>'
|
121
|
+
} } }) do
|
122
|
+
with_input_for @user, :name, :string
|
123
|
+
assert_select 'label b', 'Name'
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
107
127
|
[:email, :url, :search, :tel].each do |type|
|
108
128
|
test "input should allow type #{type}" do
|
109
129
|
with_input_for @user, :name, type
|
data/test/simple_form_test.rb
CHANGED
@@ -6,4 +6,12 @@ class SimpleFormTest < ActiveSupport::TestCase
|
|
6
6
|
assert_equal SimpleForm, config
|
7
7
|
end
|
8
8
|
end
|
9
|
+
|
10
|
+
test 'setup block configure Simple Form' do
|
11
|
+
SimpleForm.setup do |config|
|
12
|
+
assert_equal SimpleForm, config
|
13
|
+
end
|
14
|
+
|
15
|
+
assert_equal true, SimpleForm.configured?
|
16
|
+
end
|
9
17
|
end
|
@@ -1,16 +1,26 @@
|
|
1
1
|
class StringInput < SimpleForm::Inputs::StringInput
|
2
|
-
def input
|
2
|
+
def input(wrapper_options = nil)
|
3
3
|
"<section>#{super}</section>".html_safe
|
4
4
|
end
|
5
5
|
end
|
6
6
|
|
7
7
|
class NumericInput < SimpleForm::Inputs::NumericInput
|
8
|
-
def input
|
8
|
+
def input(wrapper_options = nil)
|
9
9
|
"<section>#{super}</section>".html_safe
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
13
|
class CustomizedInput < SimpleForm::Inputs::StringInput
|
14
|
+
def input(wrapper_options = nil)
|
15
|
+
"<section>#{super}</section>".html_safe
|
16
|
+
end
|
17
|
+
|
18
|
+
def input_method
|
19
|
+
:text_field
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class DeprecatedInput < SimpleForm::Inputs::StringInput
|
14
24
|
def input
|
15
25
|
"<section>#{super}</section>".html_safe
|
16
26
|
end
|
@@ -46,12 +46,12 @@ module MiscHelpers
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
def swap_wrapper(name
|
50
|
-
old = SimpleForm.wrappers[name]
|
51
|
-
SimpleForm.wrappers[name] = wrapper
|
49
|
+
def swap_wrapper(name = :default, wrapper = self.custom_wrapper)
|
50
|
+
old = SimpleForm.wrappers[name.to_s]
|
51
|
+
SimpleForm.wrappers[name.to_s] = wrapper
|
52
52
|
yield
|
53
53
|
ensure
|
54
|
-
SimpleForm.wrappers[name] = old
|
54
|
+
SimpleForm.wrappers[name.to_s] = old
|
55
55
|
end
|
56
56
|
|
57
57
|
def custom_wrapper
|
@@ -68,6 +68,32 @@ module MiscHelpers
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
+
def custom_wrapper_with_input_class
|
72
|
+
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
73
|
+
b.use :label
|
74
|
+
b.use :input, class: 'inline-class'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def custom_wrapper_with_label_class
|
79
|
+
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
80
|
+
b.use :label, class: 'inline-class'
|
81
|
+
b.use :input
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def custom_wrapper_with_input_attributes
|
86
|
+
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
87
|
+
b.use :input, data: { modal: true }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def custom_wrapper_with_label_input_class
|
92
|
+
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
93
|
+
b.use :label_input, class: 'inline-class'
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
71
97
|
def custom_wrapper_with_wrapped_input
|
72
98
|
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
73
99
|
b.wrapper tag: :div, class: 'elem' do |component|
|
@@ -112,9 +138,21 @@ module MiscHelpers
|
|
112
138
|
end
|
113
139
|
end
|
114
140
|
|
115
|
-
def
|
116
|
-
SimpleForm.build tag: :
|
117
|
-
b.use :
|
141
|
+
def custom_wrapper_with_additional_attributes
|
142
|
+
SimpleForm.build tag: :div, class: 'custom_wrapper', html: { data: { wrapper: :test }, title: 'some title' } do |b|
|
143
|
+
b.use :label_input
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def custom_wrapper_with_full_error
|
148
|
+
SimpleForm.build tag: :div, class: 'custom_wrapper' do |b|
|
149
|
+
b.use :full_error, wrap_with: { tag: :span, class: :error }
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def custom_wrapper_with_label_text
|
154
|
+
SimpleForm.build :label_text => proc { |label, required| "**#{label}**" } do |b|
|
155
|
+
b.use :label_input
|
118
156
|
end
|
119
157
|
end
|
120
158
|
|
@@ -148,7 +186,7 @@ module MiscHelpers
|
|
148
186
|
end
|
149
187
|
end
|
150
188
|
|
151
|
-
def with_input_for(object, attribute_name, type, options={})
|
189
|
+
def with_input_for(object, attribute_name, type, options = {})
|
152
190
|
with_concat_form_for(object) do |f|
|
153
191
|
f.input(attribute_name, options.merge(as: type))
|
154
192
|
end
|
data/test/support/models.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Association = Struct.new(:klass, :name, :macro, :options)
|
1
|
+
Association = Struct.new(:klass, :name, :macro, :scope, :options)
|
2
2
|
|
3
3
|
Column = Struct.new(:name, :type, :limit) do
|
4
4
|
# Returns +true+ if the column is either of type integer, float or decimal.
|
@@ -7,16 +7,36 @@ Column = Struct.new(:name, :type, :limit) do
|
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
-
Relation = Struct.new(:
|
10
|
+
Relation = Struct.new(:records) do
|
11
|
+
delegate :each, to: :records
|
12
|
+
|
11
13
|
def where(conditions = nil)
|
12
|
-
self.class.new conditions ?
|
14
|
+
self.class.new conditions ? records.first : records
|
13
15
|
end
|
14
16
|
|
15
17
|
def order(conditions = nil)
|
16
|
-
self.class.new conditions ?
|
18
|
+
self.class.new conditions ? records.last : records
|
17
19
|
end
|
18
20
|
|
19
|
-
alias_method :to_a,
|
21
|
+
alias_method :to_a, :records
|
22
|
+
alias_method :to_ary, :records
|
23
|
+
end
|
24
|
+
|
25
|
+
Picture = Struct.new(:id, :name) do
|
26
|
+
extend ActiveModel::Naming
|
27
|
+
include ActiveModel::Conversion
|
28
|
+
|
29
|
+
def self.where(conditions = nil)
|
30
|
+
if conditions.is_a?(Hash) && conditions[:name]
|
31
|
+
all.to_a.last
|
32
|
+
else
|
33
|
+
all
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.all
|
38
|
+
Relation.new((1..3).map { |i| new(i, "#{name} #{i}") })
|
39
|
+
end
|
20
40
|
end
|
21
41
|
|
22
42
|
Company = Struct.new(:id, :name) do
|
@@ -28,11 +48,11 @@ Company = Struct.new(:id, :name) do
|
|
28
48
|
end
|
29
49
|
|
30
50
|
def self._relation
|
31
|
-
|
51
|
+
all
|
32
52
|
end
|
33
53
|
|
34
54
|
def self.all
|
35
|
-
(1..3).map { |i| new(i, "#{name} #{i}") }
|
55
|
+
Relation.new((1..3).map { |i| new(i, "#{name} #{i}") })
|
36
56
|
end
|
37
57
|
|
38
58
|
def persisted?
|
@@ -53,7 +73,8 @@ class User
|
|
53
73
|
:delivery_time, :born_at, :special_company_id, :country, :tags, :tag_ids,
|
54
74
|
:avatar, :home_picture, :email, :status, :residence_country, :phone_number,
|
55
75
|
:post_count, :lock_version, :amount, :attempts, :action, :credit_card, :gender,
|
56
|
-
:extra_special_company_id
|
76
|
+
:extra_special_company_id, :pictures, :picture_ids, :special_pictures,
|
77
|
+
:special_picture_ids
|
57
78
|
|
58
79
|
def self.build(extra_attributes = {})
|
59
80
|
attributes = {
|
@@ -66,7 +87,7 @@ class User
|
|
66
87
|
new attributes
|
67
88
|
end
|
68
89
|
|
69
|
-
def initialize(options={})
|
90
|
+
def initialize(options = {})
|
70
91
|
@new_record = false
|
71
92
|
options.each do |key, value|
|
72
93
|
send("#{key}=", value)
|
@@ -108,7 +129,7 @@ class User
|
|
108
129
|
Column.new(attribute, column_type, limit)
|
109
130
|
end
|
110
131
|
|
111
|
-
def self.human_attribute_name(attribute)
|
132
|
+
def self.human_attribute_name(attribute, options = {})
|
112
133
|
case attribute
|
113
134
|
when 'name'
|
114
135
|
'Super User Name!'
|
@@ -117,35 +138,39 @@ class User
|
|
117
138
|
when 'company'
|
118
139
|
'Company Human Name!'
|
119
140
|
else
|
120
|
-
attribute.humanize
|
141
|
+
attribute.to_s.humanize
|
121
142
|
end
|
122
143
|
end
|
123
144
|
|
124
145
|
def self.reflect_on_association(association)
|
125
146
|
case association
|
126
147
|
when :company
|
127
|
-
Association.new(Company, association, :belongs_to, {})
|
148
|
+
Association.new(Company, association, :belongs_to, nil, {})
|
128
149
|
when :tags
|
129
|
-
Association.new(Tag, association, :has_many, {})
|
150
|
+
Association.new(Tag, association, :has_many, nil, {})
|
130
151
|
when :first_company
|
131
|
-
Association.new(Company, association, :has_one, {})
|
152
|
+
Association.new(Company, association, :has_one, nil, {})
|
132
153
|
when :special_company
|
133
|
-
Association.new(Company, association, :belongs_to, { conditions: { id: 1 } })
|
154
|
+
Association.new(Company, association, :belongs_to, nil, { conditions: { id: 1 } })
|
134
155
|
when :extra_special_company
|
135
|
-
Association.new(Company, association, :belongs_to, { conditions: proc { { id:
|
156
|
+
Association.new(Company, association, :belongs_to, nil, { conditions: proc { { id: self.id } } })
|
157
|
+
when :pictures
|
158
|
+
Association.new(Picture, association, :has_many, nil, {})
|
159
|
+
when :special_pictures
|
160
|
+
Association.new(Picture, association, :has_many, proc { where(name: self.name) }, {})
|
136
161
|
end
|
137
162
|
end
|
138
163
|
|
139
164
|
def errors
|
140
165
|
@errors ||= begin
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
166
|
+
errors = ActiveModel::Errors.new(self)
|
167
|
+
errors.add(:name, "can't be blank")
|
168
|
+
errors.add(:description, 'must be longer than 15 characters')
|
169
|
+
errors.add(:age, 'is not a number')
|
170
|
+
errors.add(:age, 'must be greater than 18')
|
171
|
+
errors.add(:company, 'company must be present')
|
172
|
+
errors.add(:company_id, 'must be valid')
|
173
|
+
errors
|
149
174
|
end
|
150
175
|
end
|
151
176
|
|