simple_form_awesome 2.2.0
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.
- data/CHANGELOG.md +327 -0
- data/MIT-LICENSE +20 -0
- data/README.md +25 -0
- data/lib/generators/simple_form/USAGE +3 -0
- data/lib/generators/simple_form/install_generator.rb +48 -0
- data/lib/generators/simple_form/templates/AUI_README +19 -0
- data/lib/generators/simple_form/templates/README +12 -0
- data/lib/generators/simple_form/templates/_form.html.erb +13 -0
- data/lib/generators/simple_form/templates/_form.html.haml +10 -0
- data/lib/generators/simple_form/templates/_form.html.slim +10 -0
- data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +142 -0
- data/lib/generators/simple_form/templates/config/initializers/simple_form_aui.rb +21 -0
- data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +45 -0
- data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +26 -0
- data/lib/generators/simple_form/templates/config/locales/simple_form.en.yml +26 -0
- data/lib/simple_form/action_view_extensions/builder.rb +340 -0
- data/lib/simple_form/action_view_extensions/form_helper.rb +72 -0
- data/lib/simple_form/components/errors.rb +35 -0
- data/lib/simple_form/components/hints.rb +18 -0
- data/lib/simple_form/components/html5.rb +26 -0
- data/lib/simple_form/components/label_input.rb +15 -0
- data/lib/simple_form/components/labels.rb +79 -0
- data/lib/simple_form/components/maxlength.rb +41 -0
- data/lib/simple_form/components/min_max.rb +50 -0
- data/lib/simple_form/components/pattern.rb +34 -0
- data/lib/simple_form/components/placeholders.rb +16 -0
- data/lib/simple_form/components/readonly.rb +22 -0
- data/lib/simple_form/components.rb +20 -0
- data/lib/simple_form/core_ext/hash.rb +16 -0
- data/lib/simple_form/error_notification.rb +48 -0
- data/lib/simple_form/form_builder.rb +482 -0
- data/lib/simple_form/helpers/autofocus.rb +11 -0
- data/lib/simple_form/helpers/disabled.rb +15 -0
- data/lib/simple_form/helpers/readonly.rb +15 -0
- data/lib/simple_form/helpers/required.rb +35 -0
- data/lib/simple_form/helpers/validators.rb +44 -0
- data/lib/simple_form/helpers.rb +12 -0
- data/lib/simple_form/i18n_cache.rb +22 -0
- data/lib/simple_form/inputs/aui_string_input.rb +10 -0
- data/lib/simple_form/inputs/base.rb +184 -0
- data/lib/simple_form/inputs/block_input.rb +14 -0
- data/lib/simple_form/inputs/boolean_input.rb +78 -0
- data/lib/simple_form/inputs/collection_check_boxes_input.rb +21 -0
- data/lib/simple_form/inputs/collection_input.rb +101 -0
- data/lib/simple_form/inputs/collection_radio_buttons_input.rb +63 -0
- data/lib/simple_form/inputs/collection_select_input.rb +14 -0
- data/lib/simple_form/inputs/date_time_input.rb +28 -0
- data/lib/simple_form/inputs/file_input.rb +9 -0
- data/lib/simple_form/inputs/grouped_collection_select_input.rb +41 -0
- data/lib/simple_form/inputs/hidden_input.rb +17 -0
- data/lib/simple_form/inputs/numeric_input.rb +24 -0
- data/lib/simple_form/inputs/password_input.rb +12 -0
- data/lib/simple_form/inputs/priority_input.rb +24 -0
- data/lib/simple_form/inputs/range_input.rb +14 -0
- data/lib/simple_form/inputs/string_input.rb +23 -0
- data/lib/simple_form/inputs/text_area_input.rb +12 -0
- data/lib/simple_form/inputs/text_input.rb +11 -0
- data/lib/simple_form/inputs.rb +23 -0
- data/lib/simple_form/map_type.rb +16 -0
- data/lib/simple_form/version.rb +3 -0
- data/lib/simple_form/wrappers/builder.rb +103 -0
- data/lib/simple_form/wrappers/many.rb +73 -0
- data/lib/simple_form/wrappers/root.rb +36 -0
- data/lib/simple_form/wrappers/single.rb +24 -0
- data/lib/simple_form/wrappers.rb +8 -0
- data/lib/simple_form.rb +221 -0
- data/test/action_view_extensions/builder_test.rb +583 -0
- data/test/action_view_extensions/form_helper_test.rb +143 -0
- data/test/components/label_test.rb +327 -0
- data/test/form_builder/association_test.rb +186 -0
- data/test/form_builder/button_test.rb +47 -0
- data/test/form_builder/error_notification_test.rb +79 -0
- data/test/form_builder/error_test.rb +121 -0
- data/test/form_builder/general_test.rb +402 -0
- data/test/form_builder/hint_test.rb +138 -0
- data/test/form_builder/input_field_test.rb +63 -0
- data/test/form_builder/label_test.rb +71 -0
- data/test/form_builder/wrapper_test.rb +203 -0
- data/test/generators/simple_form_generator_test.rb +42 -0
- data/test/inputs/boolean_input_test.rb +140 -0
- data/test/inputs/collection_check_boxes_input_test.rb +224 -0
- data/test/inputs/collection_radio_buttons_input_test.rb +326 -0
- data/test/inputs/collection_select_input_test.rb +241 -0
- data/test/inputs/datetime_input_test.rb +99 -0
- data/test/inputs/disabled_test.rb +78 -0
- data/test/inputs/discovery_test.rb +69 -0
- data/test/inputs/file_input_test.rb +16 -0
- data/test/inputs/general_test.rb +116 -0
- data/test/inputs/grouped_collection_select_input_test.rb +118 -0
- data/test/inputs/hidden_input_test.rb +30 -0
- data/test/inputs/numeric_input_test.rb +173 -0
- data/test/inputs/priority_input_test.rb +43 -0
- data/test/inputs/readonly_test.rb +101 -0
- data/test/inputs/required_test.rb +113 -0
- data/test/inputs/string_input_test.rb +146 -0
- data/test/inputs/text_input_test.rb +24 -0
- data/test/simple_form_test.rb +9 -0
- data/test/support/discovery_inputs.rb +27 -0
- data/test/support/misc_helpers.rb +138 -0
- data/test/support/mock_controller.rb +24 -0
- data/test/support/models.rb +216 -0
- data/test/test_helper.rb +95 -0
- metadata +217 -0
@@ -0,0 +1,146 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
class StringInputTest < ActionView::TestCase
|
5
|
+
test 'input should map text field to string attribute' do
|
6
|
+
with_input_for @user, :name, :string
|
7
|
+
assert_select "input#user_name[type=text][name='user[name]'][value=New in SimpleForm!]"
|
8
|
+
end
|
9
|
+
|
10
|
+
test 'input should generate a password field for password attributes' do
|
11
|
+
with_input_for @user, :password, :password
|
12
|
+
assert_select "input#user_password.password[type=password][name='user[password]']"
|
13
|
+
end
|
14
|
+
|
15
|
+
test 'input should not use size attribute for decimal attributes' do
|
16
|
+
with_input_for @user, :credit_limit, :decimal
|
17
|
+
assert_no_select 'input.decimal[size]'
|
18
|
+
end
|
19
|
+
|
20
|
+
test 'input should get maxlength from column definition for string attributes' do
|
21
|
+
with_input_for @user, :name, :string
|
22
|
+
assert_select 'input.string[maxlength=100]'
|
23
|
+
end
|
24
|
+
|
25
|
+
test 'input should not get maxlength from column without size definition for string attributes' do
|
26
|
+
with_input_for @user, :action, :string
|
27
|
+
assert_no_select 'input.string[maxlength]'
|
28
|
+
end
|
29
|
+
|
30
|
+
test 'input should get size from column definition for string attributes respecting maximum value' do
|
31
|
+
with_input_for @user, :name, :string
|
32
|
+
assert_select 'input.string[size=50]'
|
33
|
+
end
|
34
|
+
|
35
|
+
test 'input should use default text size for password attributes' do
|
36
|
+
with_input_for @user, :password, :password
|
37
|
+
assert_select 'input.password[type=password][size=50]'
|
38
|
+
end
|
39
|
+
|
40
|
+
test 'input should get maxlength from column definition for password attributes' do
|
41
|
+
with_input_for @user, :password, :password
|
42
|
+
assert_select 'input.password[type=password][maxlength=100]'
|
43
|
+
end
|
44
|
+
|
45
|
+
test 'input should infer maxlength column definition from validation when present' do
|
46
|
+
with_input_for @validating_user, :name, :string
|
47
|
+
assert_select 'input.string[maxlength=25]'
|
48
|
+
end
|
49
|
+
|
50
|
+
test 'input should not get maxlength from validation when tokenizer present' do
|
51
|
+
with_input_for @validating_user, :action, :string
|
52
|
+
assert_no_select 'input.string[maxlength]'
|
53
|
+
end
|
54
|
+
|
55
|
+
test 'input should get maxlength from validation when :is option present' do
|
56
|
+
with_input_for @validating_user, :home_picture, :string
|
57
|
+
assert_select 'input.string[maxlength=12]'
|
58
|
+
end
|
59
|
+
|
60
|
+
test 'input size and maxlength should be the column limit plus one to make room for decimal point' do
|
61
|
+
with_input_for @user, :credit_limit, :string
|
62
|
+
|
63
|
+
assert_select "input.string[maxlength=16][size=16]"
|
64
|
+
end
|
65
|
+
|
66
|
+
test 'input should not generate placeholder by default' do
|
67
|
+
with_input_for @user, :name, :string
|
68
|
+
assert_no_select 'input[placeholder]'
|
69
|
+
end
|
70
|
+
|
71
|
+
test 'input should accept the placeholder option' do
|
72
|
+
with_input_for @user, :name, :string, :placeholder => 'Put in some text'
|
73
|
+
assert_select 'input.string[placeholder=Put in some text]'
|
74
|
+
end
|
75
|
+
|
76
|
+
test 'input should generate a password field for password attributes that accept placeholder' do
|
77
|
+
with_input_for @user, :password, :password, :placeholder => 'Password Confirmation'
|
78
|
+
assert_select 'input[type=password].password[placeholder=Password Confirmation]#user_password'
|
79
|
+
end
|
80
|
+
|
81
|
+
test 'input should not infer pattern from attributes by default' do
|
82
|
+
with_input_for @other_validating_user, :country, :string
|
83
|
+
assert_no_select 'input[pattern="\w+"]'
|
84
|
+
end
|
85
|
+
|
86
|
+
test 'input should infer pattern from attributes' do
|
87
|
+
with_input_for @other_validating_user, :country, :string, :pattern => true
|
88
|
+
assert_select 'input[pattern="\w+"]'
|
89
|
+
end
|
90
|
+
|
91
|
+
test 'input should infer pattern from attributes using proc' do
|
92
|
+
with_input_for @other_validating_user, :name, :string, :pattern => true
|
93
|
+
assert_select 'input[pattern="\w+"]'
|
94
|
+
end
|
95
|
+
|
96
|
+
test 'input should not infer pattern from attributes if root default is false' do
|
97
|
+
swap_wrapper do
|
98
|
+
with_input_for @other_validating_user, :country, :string
|
99
|
+
assert_no_select 'input[pattern="\w+"]'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
test 'input should use given pattern from attributes' do
|
104
|
+
with_input_for @other_validating_user, :country, :string, :input_html => { :pattern => "\\d+" }
|
105
|
+
assert_select 'input[pattern="\d+"]'
|
106
|
+
end
|
107
|
+
|
108
|
+
test 'input should use i18n to translate placeholder text' do
|
109
|
+
store_translations(:en, :simple_form => { :placeholders => { :user => {
|
110
|
+
:name => 'Name goes here'
|
111
|
+
} } }) do
|
112
|
+
with_input_for @user, :name, :string
|
113
|
+
assert_select 'input.string[placeholder=Name goes here]'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
[:email, :url, :search, :tel].each do |type|
|
118
|
+
test "input should allow type #{type}" do
|
119
|
+
with_input_for @user, :name, type
|
120
|
+
assert_select "input.string.#{type}"
|
121
|
+
assert_select "input[type=#{type}]"
|
122
|
+
end
|
123
|
+
|
124
|
+
test "input should not allow type #{type} if HTML5 compatibility is disabled" do
|
125
|
+
swap_wrapper do
|
126
|
+
with_input_for @user, :name, type
|
127
|
+
assert_select "input[type=text]"
|
128
|
+
assert_no_select "input[type=#{type}]"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
test 'input strips extra spaces from class html attribute with default classes' do
|
134
|
+
with_input_for @user, :name, :string
|
135
|
+
assert_select "input[class='string required']"
|
136
|
+
assert_no_select "input[class='string required ']"
|
137
|
+
assert_no_select "input[class=' string required']"
|
138
|
+
end
|
139
|
+
|
140
|
+
test 'input strips extra spaces from class html attribute when giving a custom class' do
|
141
|
+
with_input_for @user, :name, :string, :input_html => { :class => "my_input" }
|
142
|
+
assert_select "input[class='string required my_input']"
|
143
|
+
assert_no_select "input[class='string required my_input ']"
|
144
|
+
assert_no_select "input[class=' string required my_input']"
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
class TextInputTest < ActionView::TestCase
|
5
|
+
test 'input should generate a text area for text attributes' do
|
6
|
+
with_input_for @user, :description, :text
|
7
|
+
assert_select 'textarea.text#user_description'
|
8
|
+
end
|
9
|
+
|
10
|
+
test 'input should generate a text area for text attributes that accept placeholder' do
|
11
|
+
with_input_for @user, :description, :text, :placeholder => 'Put in some text'
|
12
|
+
assert_select 'textarea.text[placeholder=Put in some text]'
|
13
|
+
end
|
14
|
+
|
15
|
+
test 'input should get maxlength from column definition for text attributes' do
|
16
|
+
with_input_for @user, :description, :text
|
17
|
+
assert_select 'textarea.text[maxlength=200]'
|
18
|
+
end
|
19
|
+
|
20
|
+
test 'input should infer maxlength column definition from validation when present for text attributes' do
|
21
|
+
with_input_for @validating_user, :description, :text
|
22
|
+
assert_select 'textarea.text[maxlength=50]'
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class StringInput < SimpleForm::Inputs::StringInput
|
2
|
+
def input
|
3
|
+
"<section>#{super}</section>".html_safe
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
class NumericInput < SimpleForm::Inputs::NumericInput
|
8
|
+
def input
|
9
|
+
"<section>#{super}</section>".html_safe
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class CustomizedInput < SimpleForm::Inputs::StringInput
|
14
|
+
def input
|
15
|
+
"<section>#{super}</section>".html_safe
|
16
|
+
end
|
17
|
+
|
18
|
+
def input_method
|
19
|
+
:text_field
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class CollectionSelectInput < SimpleForm::Inputs::CollectionSelectInput
|
24
|
+
def input_html_classes
|
25
|
+
super.push('chosen')
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module MiscHelpers
|
2
|
+
def store_translations(locale, translations, &block)
|
3
|
+
I18n.backend.store_translations locale, translations
|
4
|
+
yield
|
5
|
+
ensure
|
6
|
+
I18n.reload!
|
7
|
+
I18n.backend.send :init_translations
|
8
|
+
end
|
9
|
+
|
10
|
+
def assert_no_select(selector, value = nil)
|
11
|
+
assert_select(selector, :text => value, :count => 0)
|
12
|
+
end
|
13
|
+
|
14
|
+
def swap(object, new_values)
|
15
|
+
old_values = {}
|
16
|
+
new_values.each do |key, value|
|
17
|
+
old_values[key] = object.send key
|
18
|
+
object.send :"#{key}=", value
|
19
|
+
end
|
20
|
+
yield
|
21
|
+
ensure
|
22
|
+
old_values.each do |key, value|
|
23
|
+
object.send :"#{key}=", value
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def swap_wrapper(name=:default, wrapper=self.custom_wrapper)
|
28
|
+
old = SimpleForm.wrappers[name]
|
29
|
+
SimpleForm.wrappers[name] = wrapper
|
30
|
+
yield
|
31
|
+
ensure
|
32
|
+
SimpleForm.wrappers[name] = old
|
33
|
+
end
|
34
|
+
|
35
|
+
def custom_wrapper
|
36
|
+
SimpleForm.build :tag => :section, :class => "custom_wrapper", :pattern => false do |b|
|
37
|
+
b.use :pattern
|
38
|
+
b.wrapper :another, :class => "another_wrapper" do |ba|
|
39
|
+
ba.use :label
|
40
|
+
ba.use :input
|
41
|
+
end
|
42
|
+
b.wrapper :error_wrapper, :tag => :div, :class => "error_wrapper" do |be|
|
43
|
+
be.use :error, :wrap_with => { :tag => :span, :class => "omg_error" }
|
44
|
+
end
|
45
|
+
b.use :hint, :wrap_with => { :class => "omg_hint" }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def custom_wrapper_with_wrapped_input
|
50
|
+
SimpleForm.build :tag => :div, :class => "custom_wrapper" do |b|
|
51
|
+
b.wrapper :tag => :div, :class => 'elem' do |component|
|
52
|
+
component.use :label
|
53
|
+
component.use :input, :wrap_with => { :tag => :div, :class => 'input' }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def custom_wrapper_with_wrapped_label
|
59
|
+
SimpleForm.build :tag => :div, :class => "custom_wrapper" do |b|
|
60
|
+
b.wrapper :tag => :div, :class => 'elem' do |component|
|
61
|
+
component.use :label, :wrap_with => { :tag => :div, :class => 'label' }
|
62
|
+
component.use :input
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def custom_wrapper_without_top_level
|
68
|
+
SimpleForm.build :tag => false, :class => 'custom_wrapper_without_top_level' do |b|
|
69
|
+
b.use :label_input
|
70
|
+
b.use :hint, :wrap_with => { :tag => :span, :class => :hint }
|
71
|
+
b.use :error, :wrap_with => { :tag => :span, :class => :error }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def custom_wrapper_without_class
|
76
|
+
SimpleForm.build :tag => :div, :wrapper_html => { :id => 'custom_wrapper_without_class' } do |b|
|
77
|
+
b.use :label_input
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def custom_wrapper_with_label_html_option
|
82
|
+
SimpleForm.build :tag => :div, :class => "custom_wrapper", :label_html => { :class => 'extra-label-class' } do |b|
|
83
|
+
b.use :label_input
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def custom_wrapper_with_wrapped_label_input
|
88
|
+
SimpleForm.build :tag => :section, :class => "custom_wrapper", :pattern => false do |b|
|
89
|
+
b.use :label_input, :wrap_with => { :tag => :div, :class => :field }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def custom_form_for(object, *args, &block)
|
94
|
+
simple_form_for(object, *(args << { :builder => CustomFormBuilder }), &block)
|
95
|
+
end
|
96
|
+
|
97
|
+
def custom_mapping_form_for(object, *args, &block)
|
98
|
+
simple_form_for(object, *(args << { :builder => CustomMapTypeFormBuilder }), &block)
|
99
|
+
end
|
100
|
+
|
101
|
+
def with_concat_form_for(*args, &block)
|
102
|
+
concat simple_form_for(*args, &(block || proc {}))
|
103
|
+
end
|
104
|
+
|
105
|
+
def with_concat_fields_for(*args, &block)
|
106
|
+
concat simple_fields_for(*args, &block)
|
107
|
+
end
|
108
|
+
|
109
|
+
def with_concat_custom_form_for(*args, &block)
|
110
|
+
concat custom_form_for(*args, &block)
|
111
|
+
end
|
112
|
+
|
113
|
+
def with_concat_custom_mapping_form_for(*args, &block)
|
114
|
+
concat custom_mapping_form_for(*args, &block)
|
115
|
+
end
|
116
|
+
|
117
|
+
def with_form_for(object, *args, &block)
|
118
|
+
with_concat_form_for(object) do |f|
|
119
|
+
f.input(*args, &block)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def with_input_for(object, attribute_name, type, options={})
|
124
|
+
with_concat_form_for(object) do |f|
|
125
|
+
f.input(attribute_name, options.merge(:as => type))
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
class CustomFormBuilder < SimpleForm::FormBuilder
|
131
|
+
def input(attribute_name, *args, &block)
|
132
|
+
super(attribute_name, *(args << { :input_html => { :class => 'custom' } }), &block)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
class CustomMapTypeFormBuilder < SimpleForm::FormBuilder
|
137
|
+
map_type :custom_type, :to => SimpleForm::Inputs::StringInput
|
138
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class MockController
|
2
|
+
attr_writer :action_name
|
3
|
+
|
4
|
+
def _routes
|
5
|
+
self
|
6
|
+
end
|
7
|
+
|
8
|
+
def action_name
|
9
|
+
defined?(@action_name) ? @action_name : "edit"
|
10
|
+
end
|
11
|
+
|
12
|
+
def url_for(*args)
|
13
|
+
"http://example.com"
|
14
|
+
end
|
15
|
+
|
16
|
+
def url_helpers
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
def hash_for_user_path(*args); end
|
21
|
+
def hash_for_validating_user_path(*args); end
|
22
|
+
def hash_for_other_validating_user_path(*args); end
|
23
|
+
def hash_for_users_path(*args); end
|
24
|
+
end
|
@@ -0,0 +1,216 @@
|
|
1
|
+
Association = Struct.new(:klass, :name, :macro, :options)
|
2
|
+
|
3
|
+
class Column < Struct.new(:name, :type, :limit)
|
4
|
+
# Returns +true+ if the column is either of type integer, float or decimal.
|
5
|
+
def number?
|
6
|
+
type == :integer || type == :float || type == :decimal
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Company < Struct.new(:id, :name)
|
11
|
+
extend ActiveModel::Naming
|
12
|
+
include ActiveModel::Conversion
|
13
|
+
|
14
|
+
def self.all(options={})
|
15
|
+
all = (1..3).map{|i| Company.new(i, "Company #{i}")}
|
16
|
+
return [all.first] if options[:conditions].present?
|
17
|
+
return [all.last] if options[:order].present?
|
18
|
+
return all[0..1] if options[:include].present?
|
19
|
+
return all[1..2] if options[:joins].present?
|
20
|
+
all
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.merge_conditions(a, b)
|
24
|
+
(a || {}).merge(b || {})
|
25
|
+
end
|
26
|
+
|
27
|
+
def persisted?
|
28
|
+
true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Tag < Company
|
33
|
+
def self.all(options={})
|
34
|
+
(1..3).map{|i| Tag.new(i, "Tag #{i}")}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class TagGroup < Struct.new(:id, :name, :tags)
|
39
|
+
end
|
40
|
+
|
41
|
+
class User
|
42
|
+
extend ActiveModel::Naming
|
43
|
+
include ActiveModel::Conversion
|
44
|
+
|
45
|
+
attr_accessor :id, :name, :company, :company_id, :time_zone, :active, :age,
|
46
|
+
:description, :created_at, :updated_at, :credit_limit, :password, :url,
|
47
|
+
:delivery_time, :born_at, :special_company_id, :country, :tags, :tag_ids,
|
48
|
+
:avatar, :home_picture, :email, :status, :residence_country, :phone_number,
|
49
|
+
:post_count, :lock_version, :amount, :attempts, :action, :credit_card, :gender
|
50
|
+
|
51
|
+
def initialize(options={})
|
52
|
+
@new_record = false
|
53
|
+
options.each do |key, value|
|
54
|
+
send("#{key}=", value)
|
55
|
+
end if options
|
56
|
+
end
|
57
|
+
|
58
|
+
def new_record!
|
59
|
+
@new_record = true
|
60
|
+
end
|
61
|
+
|
62
|
+
def persisted?
|
63
|
+
!@new_record
|
64
|
+
end
|
65
|
+
|
66
|
+
def company_attributes=(*)
|
67
|
+
end
|
68
|
+
|
69
|
+
def tags_attributes=(*)
|
70
|
+
end
|
71
|
+
|
72
|
+
def column_for_attribute(attribute)
|
73
|
+
column_type, limit = case attribute.to_sym
|
74
|
+
when :name, :status, :password then [:string, 100]
|
75
|
+
when :description then [:text, 200]
|
76
|
+
when :age then :integer
|
77
|
+
when :credit_limit then [:decimal, 15]
|
78
|
+
when :active then :boolean
|
79
|
+
when :born_at then :date
|
80
|
+
when :delivery_time then :time
|
81
|
+
when :created_at then :datetime
|
82
|
+
when :updated_at then :timestamp
|
83
|
+
when :lock_version then :integer
|
84
|
+
when :home_picture then :string
|
85
|
+
when :amount then :integer
|
86
|
+
when :attempts then :integer
|
87
|
+
when :action then :string
|
88
|
+
when :credit_card then :string
|
89
|
+
end
|
90
|
+
Column.new(attribute, column_type, limit)
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.human_attribute_name(attribute)
|
94
|
+
case attribute
|
95
|
+
when 'name'
|
96
|
+
'Super User Name!'
|
97
|
+
when 'description'
|
98
|
+
'User Description!'
|
99
|
+
when 'company'
|
100
|
+
'Company Human Name!'
|
101
|
+
else
|
102
|
+
attribute.humanize
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.reflect_on_association(association)
|
107
|
+
case association
|
108
|
+
when :company
|
109
|
+
Association.new(Company, association, :belongs_to, {})
|
110
|
+
when :tags
|
111
|
+
Association.new(Tag, association, :has_many, {})
|
112
|
+
when :first_company
|
113
|
+
Association.new(Company, association, :has_one, {})
|
114
|
+
when :special_company
|
115
|
+
Association.new(Company, association, :belongs_to, { :conditions => { :id => 1 } })
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def errors
|
120
|
+
@errors ||= begin
|
121
|
+
hash = Hash.new { |h,k| h[k] = [] }
|
122
|
+
hash.merge!(
|
123
|
+
:name => ["can't be blank"],
|
124
|
+
:description => ["must be longer than 15 characters"],
|
125
|
+
:age => ["is not a number", "must be greater than 18"],
|
126
|
+
:company => ["company must be present"],
|
127
|
+
:company_id => ["must be valid"]
|
128
|
+
)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def self.readonly_attributes
|
133
|
+
["credit_card"]
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
class ValidatingUser < User
|
138
|
+
include ActiveModel::Validations
|
139
|
+
validates :name, :presence => true
|
140
|
+
validates :company, :presence => true
|
141
|
+
validates :age, :presence => true, :if => Proc.new { |user| user.name }
|
142
|
+
validates :amount, :presence => true, :unless => Proc.new { |user| user.age }
|
143
|
+
|
144
|
+
validates :action, :presence => true, :on => :create
|
145
|
+
validates :credit_limit, :presence => true, :on => :save
|
146
|
+
validates :phone_number, :presence => true, :on => :update
|
147
|
+
|
148
|
+
validates_numericality_of :age,
|
149
|
+
:greater_than_or_equal_to => 18,
|
150
|
+
:less_than_or_equal_to => 99,
|
151
|
+
:only_integer => true
|
152
|
+
validates_numericality_of :amount,
|
153
|
+
:greater_than => :min_amount,
|
154
|
+
:less_than => :max_amount,
|
155
|
+
:only_integer => true
|
156
|
+
validates_numericality_of :attempts,
|
157
|
+
:greater_than_or_equal_to => :min_attempts,
|
158
|
+
:less_than_or_equal_to => :max_attempts,
|
159
|
+
:only_integer => true
|
160
|
+
validates_length_of :name, :maximum => 25
|
161
|
+
validates_length_of :description, :maximum => 50
|
162
|
+
validates_length_of :action, :maximum => 10, :tokenizer => lambda { |str| str.scan(/\w+/) }
|
163
|
+
validates_length_of :home_picture, :is => 12
|
164
|
+
|
165
|
+
def min_amount
|
166
|
+
10
|
167
|
+
end
|
168
|
+
|
169
|
+
def max_amount
|
170
|
+
100
|
171
|
+
end
|
172
|
+
|
173
|
+
def min_attempts
|
174
|
+
1
|
175
|
+
end
|
176
|
+
|
177
|
+
def max_attempts
|
178
|
+
100
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
class OtherValidatingUser < User
|
183
|
+
include ActiveModel::Validations
|
184
|
+
validates_numericality_of :age,
|
185
|
+
:greater_than => 17,
|
186
|
+
:less_than => 100,
|
187
|
+
:only_integer => true
|
188
|
+
validates_numericality_of :amount,
|
189
|
+
:greater_than => Proc.new { |user| user.age },
|
190
|
+
:less_than => Proc.new { |user| user.age + 100},
|
191
|
+
:only_integer => true
|
192
|
+
validates_numericality_of :attempts,
|
193
|
+
:greater_than_or_equal_to => Proc.new { |user| user.age },
|
194
|
+
:less_than_or_equal_to => Proc.new { |user| user.age + 100},
|
195
|
+
:only_integer => true
|
196
|
+
|
197
|
+
validates_format_of :country, :with => /\w+/
|
198
|
+
|
199
|
+
# TODO: Remove this check when we drop Rails 3.0 support
|
200
|
+
if ActiveModel::VERSION::MAJOR == 3 && ActiveModel::VERSION::MINOR >= 1
|
201
|
+
validates_format_of :name, :with => Proc.new { /\w+/ }
|
202
|
+
else
|
203
|
+
validates_format_of :name, :with => /\w+/
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
class HashBackedAuthor < Hash
|
208
|
+
extend ActiveModel::Naming
|
209
|
+
include ActiveModel::Conversion
|
210
|
+
|
211
|
+
def persisted?; false; end
|
212
|
+
|
213
|
+
def name
|
214
|
+
'hash backed author'
|
215
|
+
end
|
216
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
|
4
|
+
require 'test/unit'
|
5
|
+
require 'mocha/setup'
|
6
|
+
|
7
|
+
require 'active_model'
|
8
|
+
require 'action_controller'
|
9
|
+
require 'action_view'
|
10
|
+
require 'action_view/template'
|
11
|
+
|
12
|
+
# Rails 3.0.4 is missing this "deprecation" require.
|
13
|
+
require 'active_support/core_ext/module/deprecation'
|
14
|
+
require 'action_view/test_case'
|
15
|
+
|
16
|
+
module Rails
|
17
|
+
def self.env
|
18
|
+
ActiveSupport::StringInquirer.new("test")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
$:.unshift File.expand_path("../../lib", __FILE__)
|
23
|
+
require 'simple_form'
|
24
|
+
|
25
|
+
require "rails/generators/test_case"
|
26
|
+
require 'generators/simple_form/install_generator'
|
27
|
+
|
28
|
+
Dir["#{File.dirname(__FILE__)}/support/*.rb"].each do |file|
|
29
|
+
require file unless file.end_with?('discovery_inputs.rb')
|
30
|
+
end
|
31
|
+
I18n.default_locale = :en
|
32
|
+
|
33
|
+
require 'country_select'
|
34
|
+
|
35
|
+
ActionDispatch::Assertions::NO_STRIP << "label"
|
36
|
+
|
37
|
+
class ActionView::TestCase
|
38
|
+
include MiscHelpers
|
39
|
+
include SimpleForm::ActionViewExtensions::FormHelper
|
40
|
+
|
41
|
+
setup :set_controller
|
42
|
+
setup :setup_new_user
|
43
|
+
|
44
|
+
def set_controller
|
45
|
+
@controller = MockController.new
|
46
|
+
end
|
47
|
+
|
48
|
+
def setup_new_user(options={})
|
49
|
+
@user = User.new({
|
50
|
+
:id => 1,
|
51
|
+
:name => 'New in SimpleForm!',
|
52
|
+
:description => 'Hello!',
|
53
|
+
:created_at => Time.now
|
54
|
+
}.merge(options))
|
55
|
+
|
56
|
+
@validating_user = ValidatingUser.new({
|
57
|
+
:id => 1,
|
58
|
+
:name => 'New in SimpleForm!',
|
59
|
+
:description => 'Hello!',
|
60
|
+
:home_picture => 'Home picture',
|
61
|
+
:created_at => Time.now,
|
62
|
+
:age => 19,
|
63
|
+
:amount => 15,
|
64
|
+
:attempts => 1,
|
65
|
+
:company => [1]
|
66
|
+
}.merge(options))
|
67
|
+
|
68
|
+
@other_validating_user = OtherValidatingUser.new({
|
69
|
+
:id => 1,
|
70
|
+
:name => 'New in SimpleForm!',
|
71
|
+
:description => 'Hello!',
|
72
|
+
:created_at => Time.now,
|
73
|
+
:age => 19,
|
74
|
+
:company => 1
|
75
|
+
}.merge(options))
|
76
|
+
end
|
77
|
+
|
78
|
+
def protect_against_forgery?
|
79
|
+
false
|
80
|
+
end
|
81
|
+
|
82
|
+
def user_path(*args)
|
83
|
+
'/users'
|
84
|
+
end
|
85
|
+
|
86
|
+
def company_user_path(*args)
|
87
|
+
'/company/users'
|
88
|
+
end
|
89
|
+
|
90
|
+
alias :users_path :user_path
|
91
|
+
alias :super_user_path :user_path
|
92
|
+
alias :validating_user_path :user_path
|
93
|
+
alias :validating_users_path :user_path
|
94
|
+
alias :other_validating_user_path :user_path
|
95
|
+
end
|