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.

Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -43
  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.rb +38 -6
  12. data/lib/simple_form/action_view_extensions/form_helper.rb +1 -1
  13. data/lib/simple_form/components/errors.rb +27 -5
  14. data/lib/simple_form/components/hints.rb +2 -2
  15. data/lib/simple_form/components/html5.rb +1 -1
  16. data/lib/simple_form/components/label_input.rb +20 -2
  17. data/lib/simple_form/components/labels.rb +9 -5
  18. data/lib/simple_form/components/maxlength.rb +1 -1
  19. data/lib/simple_form/components/min_max.rb +1 -1
  20. data/lib/simple_form/components/pattern.rb +1 -1
  21. data/lib/simple_form/components/placeholders.rb +2 -2
  22. data/lib/simple_form/components/readonly.rb +1 -1
  23. data/lib/simple_form/form_builder.rb +92 -59
  24. data/lib/simple_form/helpers.rb +5 -5
  25. data/lib/simple_form/inputs/base.rb +34 -12
  26. data/lib/simple_form/inputs/block_input.rb +1 -1
  27. data/lib/simple_form/inputs/boolean_input.rb +23 -13
  28. data/lib/simple_form/inputs/collection_input.rb +32 -9
  29. data/lib/simple_form/inputs/collection_radio_buttons_input.rb +6 -11
  30. data/lib/simple_form/inputs/collection_select_input.rb +4 -2
  31. data/lib/simple_form/inputs/date_time_input.rb +12 -2
  32. data/lib/simple_form/inputs/file_input.rb +4 -2
  33. data/lib/simple_form/inputs/grouped_collection_select_input.rb +15 -3
  34. data/lib/simple_form/inputs/hidden_input.rb +4 -2
  35. data/lib/simple_form/inputs/numeric_input.rb +5 -4
  36. data/lib/simple_form/inputs/password_input.rb +4 -2
  37. data/lib/simple_form/inputs/priority_input.rb +4 -2
  38. data/lib/simple_form/inputs/range_input.rb +1 -1
  39. data/lib/simple_form/inputs/string_input.rb +4 -2
  40. data/lib/simple_form/inputs/text_input.rb +4 -2
  41. data/lib/simple_form/railtie.rb +7 -0
  42. data/lib/simple_form/tags.rb +7 -0
  43. data/lib/simple_form/version.rb +1 -1
  44. data/lib/simple_form/wrappers.rb +1 -0
  45. data/lib/simple_form/wrappers/builder.rb +5 -5
  46. data/lib/simple_form/wrappers/leaf.rb +28 -0
  47. data/lib/simple_form/wrappers/many.rb +5 -6
  48. data/lib/simple_form/wrappers/root.rb +1 -1
  49. data/lib/simple_form/wrappers/single.rb +5 -3
  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 +21 -37
  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 +46 -8
  71. data/test/support/models.rb +49 -24
  72. metadata +7 -7
@@ -1,18 +1,69 @@
1
1
  # encoding: UTF-8
2
2
  require 'test_helper'
3
3
 
4
- # Tests for all different kinds of inputs.
5
- class DateTimeInputTest < ActionView::TestCase
6
- # DateTime input
7
- test 'input should generate a datetime select by default for datetime attributes' do
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
- 1.upto(5) do |i|
10
- assert_select "form select.datetime#user_created_at_#{i}i"
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
- with_input_for @user, :born_at, :date
26
- assert_select 'select.date#user_born_at_1i'
27
- assert_select 'select.date#user_born_at_2i'
28
- assert_select 'select.date#user_born_at_3i'
29
- assert_no_select 'select.date#user_born_at_4i'
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
- with_input_for @user, :delivery_time, :time
49
- assert_select 'input[type=hidden]#user_delivery_time_1i'
50
- assert_select 'input[type=hidden]#user_delivery_time_2i'
51
- assert_select 'input[type=hidden]#user_delivery_time_3i'
52
- assert_select 'select.time#user_delivery_time_4i'
53
- assert_select 'select.time#user_delivery_time_5i'
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
@@ -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=:default, wrapper=self.custom_wrapper)
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 custom_wrapper_with_html5_components
116
- SimpleForm.build tag: :span, class: 'custom_wrapper' do |b|
117
- b.use :label_text
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
@@ -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(:all) do
10
+ Relation = Struct.new(:records) do
11
+ delegate :each, to: :records
12
+
11
13
  def where(conditions = nil)
12
- self.class.new conditions ? all.first : all
14
+ self.class.new conditions ? records.first : records
13
15
  end
14
16
 
15
17
  def order(conditions = nil)
16
- self.class.new conditions ? all.last : all
18
+ self.class.new conditions ? records.last : records
17
19
  end
18
20
 
19
- alias_method :to_a, :all
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
- Relation.new(all)
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: 1 } } })
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
- hash = Hash.new { |h,k| h[k] = [] }
142
- hash.merge!(
143
- name: ["can't be blank"],
144
- description: ["must be longer than 15 characters"],
145
- age: ["is not a number", "must be greater than 18"],
146
- company: ["company must be present"],
147
- company_id: ["must be valid"]
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