simple_form 5.1.0 → 5.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/MIT-LICENSE +1 -1
- data/README.md +64 -16
- data/lib/generators/simple_form/install_generator.rb +2 -2
- data/lib/generators/simple_form/templates/README +1 -1
- data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +1 -1
- data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +126 -194
- data/lib/simple_form/components/label_input.rb +1 -1
- data/lib/simple_form/form_builder.rb +2 -6
- data/lib/simple_form/inputs/boolean_input.rb +6 -2
- data/lib/simple_form/inputs/grouped_collection_select_input.rb +1 -1
- data/lib/simple_form/inputs/priority_input.rb +16 -2
- data/lib/simple_form/railtie.rb +4 -0
- data/lib/simple_form/version.rb +1 -1
- data/lib/simple_form/wrappers/leaf.rb +1 -1
- data/lib/simple_form.rb +9 -5
- metadata +11 -83
- data/test/action_view_extensions/builder_test.rb +0 -634
- data/test/action_view_extensions/form_helper_test.rb +0 -172
- data/test/components/custom_components_test.rb +0 -62
- data/test/components/label_test.rb +0 -352
- data/test/form_builder/association_test.rb +0 -252
- data/test/form_builder/button_test.rb +0 -48
- data/test/form_builder/error_notification_test.rb +0 -80
- data/test/form_builder/error_test.rb +0 -281
- data/test/form_builder/general_test.rb +0 -539
- data/test/form_builder/hint_test.rb +0 -150
- data/test/form_builder/input_field_test.rb +0 -195
- data/test/form_builder/label_test.rb +0 -136
- data/test/form_builder/wrapper_test.rb +0 -378
- data/test/generators/simple_form_generator_test.rb +0 -43
- data/test/inputs/boolean_input_test.rb +0 -243
- data/test/inputs/collection_check_boxes_input_test.rb +0 -323
- data/test/inputs/collection_radio_buttons_input_test.rb +0 -446
- data/test/inputs/collection_select_input_test.rb +0 -380
- data/test/inputs/color_input_test.rb +0 -10
- data/test/inputs/datetime_input_test.rb +0 -176
- data/test/inputs/disabled_test.rb +0 -92
- data/test/inputs/discovery_test.rb +0 -142
- data/test/inputs/file_input_test.rb +0 -17
- data/test/inputs/general_test.rb +0 -133
- data/test/inputs/grouped_collection_select_input_test.rb +0 -183
- data/test/inputs/hidden_input_test.rb +0 -32
- data/test/inputs/numeric_input_test.rb +0 -177
- data/test/inputs/priority_input_test.rb +0 -50
- data/test/inputs/readonly_test.rb +0 -102
- data/test/inputs/required_test.rb +0 -158
- data/test/inputs/rich_text_area_input_test.rb +0 -15
- data/test/inputs/string_input_test.rb +0 -158
- data/test/inputs/text_input_test.rb +0 -37
- data/test/simple_form_test.rb +0 -18
- data/test/support/discovery_inputs.rb +0 -65
- data/test/support/misc_helpers.rb +0 -274
- data/test/support/mock_controller.rb +0 -30
- data/test/support/models.rb +0 -357
- data/test/test_helper.rb +0 -95
@@ -1,274 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module MiscHelpers
|
3
|
-
def store_translations(locale, translations, &block)
|
4
|
-
I18n.backend.store_translations locale, translations
|
5
|
-
yield
|
6
|
-
ensure
|
7
|
-
I18n.reload!
|
8
|
-
I18n.backend.send :init_translations
|
9
|
-
end
|
10
|
-
|
11
|
-
def assert_no_select(selector, value = nil)
|
12
|
-
assert_select(selector, text: value, count: 0)
|
13
|
-
end
|
14
|
-
|
15
|
-
def swap(object, new_values)
|
16
|
-
old_values = {}
|
17
|
-
new_values.each do |key, value|
|
18
|
-
old_values[key] = object.send key
|
19
|
-
object.send :"#{key}=", value
|
20
|
-
end
|
21
|
-
yield
|
22
|
-
ensure
|
23
|
-
old_values.each do |key, value|
|
24
|
-
object.send :"#{key}=", value
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def stub_any_instance(klass, method, value)
|
29
|
-
klass.class_eval do
|
30
|
-
alias_method :"new_#{method}", method
|
31
|
-
|
32
|
-
define_method(method) do
|
33
|
-
if value.respond_to?(:call)
|
34
|
-
value.call
|
35
|
-
else
|
36
|
-
value
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
yield
|
42
|
-
ensure
|
43
|
-
klass.class_eval do
|
44
|
-
undef_method method
|
45
|
-
alias_method method, :"new_#{method}"
|
46
|
-
undef_method :"new_#{method}"
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def swap_wrapper(name = :default, wrapper = custom_wrapper)
|
51
|
-
old = SimpleForm.wrappers[name.to_s]
|
52
|
-
SimpleForm.wrappers[name.to_s] = wrapper
|
53
|
-
yield
|
54
|
-
ensure
|
55
|
-
SimpleForm.wrappers[name.to_s] = old
|
56
|
-
end
|
57
|
-
|
58
|
-
def custom_wrapper
|
59
|
-
SimpleForm.build tag: :section, class: "custom_wrapper", pattern: false do |b|
|
60
|
-
b.use :pattern
|
61
|
-
b.wrapper :another, class: "another_wrapper" do |ba|
|
62
|
-
ba.use :label
|
63
|
-
ba.use :input
|
64
|
-
end
|
65
|
-
b.wrapper :error_wrapper, tag: :div, class: "error_wrapper" do |be|
|
66
|
-
be.use :error, wrap_with: { tag: :span, class: "omg_error" }
|
67
|
-
end
|
68
|
-
b.use :hint, wrap_with: { class: "omg_hint" }
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def custom_wrapper_with_wrapped_optional_component
|
73
|
-
SimpleForm.build tag: :section, class: "custom_wrapper" do |b|
|
74
|
-
b.wrapper tag: :div, class: 'no_output_wrapper' do |ba|
|
75
|
-
ba.optional :hint, wrap_with: { tag: :p, class: 'omg_hint' }
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def custom_wrapper_with_unless_blank
|
81
|
-
SimpleForm.build tag: :section, class: "custom_wrapper" do |b|
|
82
|
-
b.wrapper tag: :div, class: 'no_output_wrapper', unless_blank: true do |ba|
|
83
|
-
ba.optional :hint, wrap_with: { tag: :p, class: 'omg_hint' }
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def custom_wrapper_with_input_class
|
89
|
-
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
90
|
-
b.use :label
|
91
|
-
b.use :input, class: 'inline-class'
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def custom_wrapper_with_input_data_modal
|
96
|
-
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
97
|
-
b.use :label
|
98
|
-
b.use :input, data: { modal: 'data-modal', wrapper: 'data-wrapper' }
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
def custom_wrapper_with_input_aria_modal
|
103
|
-
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
104
|
-
b.use :label
|
105
|
-
b.use :input, aria: { modal: 'aria-modal', wrapper: 'aria-wrapper' }
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
def custom_wrapper_with_label_class
|
110
|
-
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
111
|
-
b.use :label, class: 'inline-class'
|
112
|
-
b.use :input
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def custom_wrapper_with_input_attributes
|
117
|
-
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
118
|
-
b.use :input, data: { modal: true }
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
def custom_wrapper_with_label_input_class
|
123
|
-
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
124
|
-
b.use :label_input, class: 'inline-class'
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
def custom_wrapper_with_wrapped_input
|
129
|
-
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
130
|
-
b.wrapper tag: :div, class: 'elem' do |component|
|
131
|
-
component.use :label
|
132
|
-
component.use :input, wrap_with: { tag: :div, class: 'input' }
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
def custom_wrapper_with_wrapped_label
|
138
|
-
SimpleForm.build tag: :div, class: "custom_wrapper" do |b|
|
139
|
-
b.wrapper tag: :div, class: 'elem' do |component|
|
140
|
-
component.use :label, wrap_with: { tag: :div, class: 'label' }
|
141
|
-
component.use :input
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
def custom_wrapper_without_top_level
|
147
|
-
SimpleForm.build tag: false, class: 'custom_wrapper_without_top_level' do |b|
|
148
|
-
b.use :label_input
|
149
|
-
b.use :hint, wrap_with: { tag: :span, class: :hint }
|
150
|
-
b.use :error, wrap_with: { tag: :span, class: :error }
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
def custom_wrapper_without_class
|
155
|
-
SimpleForm.build tag: :div, wrapper_html: { id: 'custom_wrapper_without_class' } do |b|
|
156
|
-
b.use :label_input
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
def custom_wrapper_with_label_html_option
|
161
|
-
SimpleForm.build tag: :div, class: "custom_wrapper", label_html: { class: 'extra-label-class' } do |b|
|
162
|
-
b.use :label_input
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
def custom_wrapper_with_wrapped_label_input
|
167
|
-
SimpleForm.build tag: :section, class: "custom_wrapper", pattern: false do |b|
|
168
|
-
b.use :label_input, wrap_with: { tag: :div, class: :field }
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
def custom_wrapper_with_additional_attributes
|
173
|
-
SimpleForm.build tag: :div, class: 'custom_wrapper', html: { data: { wrapper: :test }, title: 'some title' } do |b|
|
174
|
-
b.use :label_input
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
def custom_wrapper_with_full_error
|
179
|
-
SimpleForm.build tag: :div, class: 'custom_wrapper' do |b|
|
180
|
-
b.use :full_error, wrap_with: { tag: :span, class: :error }
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
def custom_wrapper_with_label_text
|
185
|
-
SimpleForm.build label_text: proc { |label, required| "**#{label}**" } do |b|
|
186
|
-
b.use :label_input
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
def custom_wrapper_with_custom_label_component
|
191
|
-
SimpleForm.build tag: :span, class: 'custom_wrapper' do |b|
|
192
|
-
b.use :label_text
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
def custom_wrapper_with_html5_components
|
197
|
-
SimpleForm.build tag: :span, class: 'custom_wrapper' do |b|
|
198
|
-
b.use :label_text
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
def custom_wrapper_with_required_input
|
203
|
-
SimpleForm.build tag: :span, class: 'custom_wrapper' do |b|
|
204
|
-
b.use :html5
|
205
|
-
b.use :input, required: true
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
def custom_wrapper_with_input_error_class
|
210
|
-
SimpleForm.build tag: :div, class: "custom_wrapper", error_class: :field_with_errors do |b|
|
211
|
-
b.use :label
|
212
|
-
b.use :input, class: 'inline-class', error_class: 'is-invalid'
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
def custom_wrapper_with_input_valid_class(valid_class: :field_without_errors)
|
217
|
-
SimpleForm.build tag: :div, class: "custom_wrapper", valid_class: valid_class do |b|
|
218
|
-
b.use :label
|
219
|
-
b.use :input, class: 'inline-class', valid_class: 'is-valid'
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
def custom_form_for(object, *args, &block)
|
224
|
-
simple_form_for(object, *args, { builder: CustomFormBuilder }, &block)
|
225
|
-
end
|
226
|
-
|
227
|
-
def custom_mapping_form_for(object, *args, &block)
|
228
|
-
simple_form_for(object, *args, { builder: CustomMapTypeFormBuilder }, &block)
|
229
|
-
end
|
230
|
-
|
231
|
-
def with_concat_form_for(*args, &block)
|
232
|
-
concat simple_form_for(*args, &(block || proc {}))
|
233
|
-
end
|
234
|
-
|
235
|
-
def with_concat_fields_for(*args, &block)
|
236
|
-
concat simple_fields_for(*args, &block)
|
237
|
-
end
|
238
|
-
|
239
|
-
def with_concat_custom_form_for(*args, &block)
|
240
|
-
concat custom_form_for(*args, &block)
|
241
|
-
end
|
242
|
-
|
243
|
-
def with_concat_custom_mapping_form_for(*args, &block)
|
244
|
-
concat custom_mapping_form_for(*args, &block)
|
245
|
-
end
|
246
|
-
|
247
|
-
def with_form_for(object, *args, &block)
|
248
|
-
with_concat_form_for(object) do |f|
|
249
|
-
f.input(*args, &block)
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
def with_input_for(object, attribute_name, type, options = {})
|
254
|
-
with_concat_form_for(object) do |f|
|
255
|
-
f.input(attribute_name, options.merge(as: type))
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
def with_input_field_for(object, *args)
|
260
|
-
with_concat_form_for(object) do |f|
|
261
|
-
f.input_field(*args)
|
262
|
-
end
|
263
|
-
end
|
264
|
-
end
|
265
|
-
|
266
|
-
class CustomFormBuilder < SimpleForm::FormBuilder
|
267
|
-
def input(attribute_name, *args, &block)
|
268
|
-
super(attribute_name, *args, { input_html: { class: 'custom' } }, &block)
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
class CustomMapTypeFormBuilder < SimpleForm::FormBuilder
|
273
|
-
map_type :custom_type, to: SimpleForm::Inputs::StringInput
|
274
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
class MockController
|
3
|
-
attr_writer :action_name
|
4
|
-
|
5
|
-
def _routes
|
6
|
-
self
|
7
|
-
end
|
8
|
-
|
9
|
-
def action_name
|
10
|
-
defined?(@action_name) ? @action_name : "edit"
|
11
|
-
end
|
12
|
-
|
13
|
-
def url_for(*)
|
14
|
-
"http://example.com"
|
15
|
-
end
|
16
|
-
|
17
|
-
def url_options
|
18
|
-
{}
|
19
|
-
end
|
20
|
-
|
21
|
-
def polymorphic_mappings(*); {}; end
|
22
|
-
|
23
|
-
def hash_for_user_path(*); end
|
24
|
-
|
25
|
-
def hash_for_validating_user_path(*); end
|
26
|
-
|
27
|
-
def hash_for_other_validating_user_path(*); end
|
28
|
-
|
29
|
-
def hash_for_users_path(*); end
|
30
|
-
end
|
data/test/support/models.rb
DELETED
@@ -1,357 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
Association = Struct.new(:klass, :name, :macro, :scope, :options)
|
3
|
-
|
4
|
-
Column = Struct.new(:name, :type, :limit) do
|
5
|
-
end
|
6
|
-
|
7
|
-
Relation = Struct.new(:records) do
|
8
|
-
delegate :each, to: :records
|
9
|
-
|
10
|
-
def where(conditions = nil)
|
11
|
-
self.class.new conditions ? [records.first] : records
|
12
|
-
end
|
13
|
-
|
14
|
-
def order(conditions = nil)
|
15
|
-
self.class.new conditions ? records.last : records
|
16
|
-
end
|
17
|
-
|
18
|
-
alias_method :to_a, :records
|
19
|
-
alias_method :to_ary, :records
|
20
|
-
end
|
21
|
-
|
22
|
-
Decorator = Struct.new(:object) do
|
23
|
-
def to_model
|
24
|
-
object
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
Picture = Struct.new(:id, :name) do
|
29
|
-
extend ActiveModel::Naming
|
30
|
-
include ActiveModel::Conversion
|
31
|
-
|
32
|
-
def self.where(conditions = nil)
|
33
|
-
if conditions.is_a?(Hash) && conditions[:name]
|
34
|
-
all.to_a.last
|
35
|
-
else
|
36
|
-
all
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def self.all
|
41
|
-
Relation.new((1..3).map { |i| new(i, "#{name} #{i}") })
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
Company = Struct.new(:id, :name) do
|
46
|
-
extend ActiveModel::Naming
|
47
|
-
include ActiveModel::Conversion
|
48
|
-
|
49
|
-
class << self
|
50
|
-
delegate :order, :where, to: :_relation
|
51
|
-
end
|
52
|
-
|
53
|
-
def self._relation
|
54
|
-
all
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.all
|
58
|
-
Relation.new((1..3).map { |i| new(i, "#{name} #{i}") })
|
59
|
-
end
|
60
|
-
|
61
|
-
def persisted?
|
62
|
-
true
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
Friend = Struct.new(:id, :name) do
|
67
|
-
extend ActiveModel::Naming
|
68
|
-
include ActiveModel::Conversion
|
69
|
-
|
70
|
-
def self.all
|
71
|
-
(1..3).map { |i| new(i, "#{name} #{i}") }
|
72
|
-
end
|
73
|
-
|
74
|
-
def persisted?
|
75
|
-
true
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
class Tag < Company
|
80
|
-
def group_method
|
81
|
-
["category-1"]
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
TagGroup = Struct.new(:id, :name, :tags)
|
86
|
-
|
87
|
-
class User
|
88
|
-
extend ActiveModel::Naming
|
89
|
-
include ActiveModel::Conversion
|
90
|
-
|
91
|
-
attr_accessor :id, :name, :company, :company_id, :time_zone, :active, :age,
|
92
|
-
:description, :created_at, :updated_at, :credit_limit, :password, :url,
|
93
|
-
:delivery_time, :born_at, :special_company_id, :country, :tags, :tag_ids,
|
94
|
-
:avatar, :home_picture, :email, :status, :residence_country, :phone_number,
|
95
|
-
:post_count, :lock_version, :amount, :attempts, :action, :credit_card, :gender,
|
96
|
-
:extra_special_company_id, :pictures, :picture_ids, :special_pictures,
|
97
|
-
:special_picture_ids, :uuid, :friends, :friend_ids, :special_tags, :special_tag_ids,
|
98
|
-
:citext, :hstore, :json, :jsonb, :hourly, :favorite_color
|
99
|
-
|
100
|
-
def self.build(extra_attributes = {})
|
101
|
-
attributes = {
|
102
|
-
id: 1,
|
103
|
-
name: 'New in SimpleForm!',
|
104
|
-
description: 'Hello!',
|
105
|
-
created_at: Time.now
|
106
|
-
}.merge! extra_attributes
|
107
|
-
|
108
|
-
new attributes
|
109
|
-
end
|
110
|
-
|
111
|
-
def initialize(options = {})
|
112
|
-
@new_record = false
|
113
|
-
options.each do |key, value|
|
114
|
-
send("#{key}=", value)
|
115
|
-
end if options
|
116
|
-
end
|
117
|
-
|
118
|
-
def new_record!
|
119
|
-
@new_record = true
|
120
|
-
end
|
121
|
-
|
122
|
-
def persisted?
|
123
|
-
!@new_record
|
124
|
-
end
|
125
|
-
|
126
|
-
def company_attributes=(*)
|
127
|
-
end
|
128
|
-
|
129
|
-
def tags_attributes=(*)
|
130
|
-
end
|
131
|
-
|
132
|
-
def column_for_attribute(attribute)
|
133
|
-
column_type, limit = case attribute.to_sym
|
134
|
-
when :name, :status, :password then [:string, 100]
|
135
|
-
when :description then [:text, 200]
|
136
|
-
when :age then :integer
|
137
|
-
when :credit_limit then [:decimal, 15]
|
138
|
-
when :active then :boolean
|
139
|
-
when :born_at then :date
|
140
|
-
when :delivery_time then :time
|
141
|
-
when :created_at then :datetime
|
142
|
-
when :updated_at then :timestamp
|
143
|
-
when :lock_version then :integer
|
144
|
-
when :home_picture then :string
|
145
|
-
when :amount then :integer
|
146
|
-
when :attempts then :integer
|
147
|
-
when :action then :string
|
148
|
-
when :credit_card then :string
|
149
|
-
else attribute.to_sym
|
150
|
-
end
|
151
|
-
Column.new(attribute, column_type, limit)
|
152
|
-
end
|
153
|
-
|
154
|
-
begin
|
155
|
-
require 'active_model/type'
|
156
|
-
begin
|
157
|
-
ActiveModel::Type.lookup(:text)
|
158
|
-
rescue ArgumentError # :text is no longer an ActiveModel::Type
|
159
|
-
# But we don't want our tests to depend on ActiveRecord
|
160
|
-
class ::ActiveModel::Type::Text < ActiveModel::Type::String
|
161
|
-
def type; :text; end
|
162
|
-
end
|
163
|
-
ActiveModel::Type.register(:text, ActiveModel::Type::Text)
|
164
|
-
end
|
165
|
-
def type_for_attribute(attribute)
|
166
|
-
column_type, limit = case attribute
|
167
|
-
when 'name', 'status', 'password' then [:string, 100]
|
168
|
-
when 'description' then [:text, 200]
|
169
|
-
when 'age' then :integer
|
170
|
-
when 'credit_limit' then [:decimal, 15]
|
171
|
-
when 'active' then :boolean
|
172
|
-
when 'born_at' then :date
|
173
|
-
when 'delivery_time' then :time
|
174
|
-
when 'created_at' then :datetime
|
175
|
-
when 'updated_at' then :datetime
|
176
|
-
when 'lock_version' then :integer
|
177
|
-
when 'home_picture' then :string
|
178
|
-
when 'amount' then :integer
|
179
|
-
when 'attempts' then :integer
|
180
|
-
when 'action' then :string
|
181
|
-
when 'credit_card' then :string
|
182
|
-
when 'uuid' then :string
|
183
|
-
when 'citext' then :string
|
184
|
-
when 'hstore' then [:text, 200]
|
185
|
-
when 'json' then [:text, 200]
|
186
|
-
when 'jsonb' then [:text, 200]
|
187
|
-
end
|
188
|
-
|
189
|
-
ActiveModel::Type.lookup(column_type, limit: limit)
|
190
|
-
end
|
191
|
-
rescue LoadError
|
192
|
-
end
|
193
|
-
|
194
|
-
def has_attribute?(attribute)
|
195
|
-
case attribute.to_sym
|
196
|
-
when :name, :status, :password, :description, :age,
|
197
|
-
:credit_limit, :active, :born_at, :delivery_time,
|
198
|
-
:created_at, :updated_at, :lock_version, :home_picture,
|
199
|
-
:amount, :attempts, :action, :credit_card, :uuid,
|
200
|
-
:citext, :hstore, :json, :jsonb then true
|
201
|
-
else false
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
def self.human_attribute_name(attribute, options = {})
|
206
|
-
case attribute
|
207
|
-
when 'name', :name
|
208
|
-
'Super User Name!'
|
209
|
-
when 'description'
|
210
|
-
'User Description!'
|
211
|
-
when 'company'
|
212
|
-
'Company Human Name!'
|
213
|
-
else
|
214
|
-
attribute.to_s.humanize
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
def self.reflect_on_association(association)
|
219
|
-
case association
|
220
|
-
when :company
|
221
|
-
Association.new(Company, association, :belongs_to, nil, {})
|
222
|
-
when :tags
|
223
|
-
Association.new(Tag, association, :has_many, nil, {})
|
224
|
-
when :special_tags
|
225
|
-
Association.new(Tag, association, :has_many, ->(user) { where(id: user.id) }, {})
|
226
|
-
when :first_company
|
227
|
-
Association.new(Company, association, :has_one, nil, {})
|
228
|
-
when :special_company
|
229
|
-
Association.new(Company, association, :belongs_to, nil, conditions: { id: 1 })
|
230
|
-
when :extra_special_company
|
231
|
-
Association.new(Company, association, :belongs_to, nil, conditions: proc { { id: self.id } })
|
232
|
-
when :pictures
|
233
|
-
Association.new(Picture, association, :has_many, nil, {})
|
234
|
-
when :special_pictures
|
235
|
-
Association.new(Picture, association, :has_many, proc { where(name: self.name) }, {})
|
236
|
-
when :friends
|
237
|
-
Association.new(Friend, association, :has_many, nil, {})
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
def errors
|
242
|
-
@errors ||= begin
|
243
|
-
errors = ActiveModel::Errors.new(self)
|
244
|
-
errors.add(:name, "cannot be blank")
|
245
|
-
errors.add(:description, 'must be longer than 15 characters')
|
246
|
-
errors.add(:age, 'is not a number')
|
247
|
-
errors.add(:age, 'must be greater than 18')
|
248
|
-
errors.add(:company, 'company must be present')
|
249
|
-
errors.add(:company_id, 'must be valid')
|
250
|
-
errors
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
def self.readonly_attributes
|
255
|
-
["credit_card"]
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
class ValidatingUser < User
|
260
|
-
include ActiveModel::Validations
|
261
|
-
validates :name, presence: true
|
262
|
-
validates :company, presence: true
|
263
|
-
validates :age, presence: true, if: proc { |user| user.name }
|
264
|
-
validates :amount, presence: true, unless: proc { |user| user.age }
|
265
|
-
|
266
|
-
validates :action, presence: true, on: :create
|
267
|
-
validates :credit_limit, presence: true, on: :save
|
268
|
-
validates :phone_number, presence: true, on: :update
|
269
|
-
|
270
|
-
validates_numericality_of :age,
|
271
|
-
greater_than_or_equal_to: 18,
|
272
|
-
less_than_or_equal_to: 99,
|
273
|
-
only_integer: true
|
274
|
-
validates_numericality_of :amount,
|
275
|
-
greater_than: :min_amount,
|
276
|
-
less_than: :max_amount,
|
277
|
-
only_integer: true
|
278
|
-
validates_numericality_of :attempts,
|
279
|
-
greater_than_or_equal_to: :min_attempts,
|
280
|
-
less_than_or_equal_to: :max_attempts,
|
281
|
-
only_integer: true
|
282
|
-
validates_length_of :name, maximum: 25, minimum: 5
|
283
|
-
validates_length_of :description, in: 15..50
|
284
|
-
validates_length_of :home_picture, is: 12
|
285
|
-
|
286
|
-
def min_amount
|
287
|
-
10
|
288
|
-
end
|
289
|
-
|
290
|
-
def max_amount
|
291
|
-
100
|
292
|
-
end
|
293
|
-
|
294
|
-
def min_attempts
|
295
|
-
1
|
296
|
-
end
|
297
|
-
|
298
|
-
def max_attempts
|
299
|
-
100
|
300
|
-
end
|
301
|
-
end
|
302
|
-
|
303
|
-
class OtherValidatingUser < User
|
304
|
-
include ActiveModel::Validations
|
305
|
-
validates_numericality_of :age,
|
306
|
-
greater_than: 17,
|
307
|
-
less_than: 100,
|
308
|
-
only_integer: true
|
309
|
-
validates_numericality_of :amount,
|
310
|
-
greater_than: proc { |user| user.age },
|
311
|
-
less_than: proc { |user| user.age + 100 },
|
312
|
-
only_integer: true
|
313
|
-
validates_numericality_of :attempts,
|
314
|
-
greater_than_or_equal_to: proc { |user| user.age },
|
315
|
-
less_than_or_equal_to: proc { |user| user.age + 100 },
|
316
|
-
only_integer: true
|
317
|
-
|
318
|
-
validates_format_of :country, with: /\w+/
|
319
|
-
validates_format_of :name, with: proc { /\w+/ }
|
320
|
-
validates_format_of :description, without: /\d+/
|
321
|
-
end
|
322
|
-
|
323
|
-
class HashBackedAuthor < Hash
|
324
|
-
extend ActiveModel::Naming
|
325
|
-
include ActiveModel::Conversion
|
326
|
-
|
327
|
-
def persisted?; false; end
|
328
|
-
|
329
|
-
def name
|
330
|
-
'hash backed author'
|
331
|
-
end
|
332
|
-
end
|
333
|
-
|
334
|
-
class UserNumber1And2 < User
|
335
|
-
end
|
336
|
-
|
337
|
-
class UserWithAttachment < User
|
338
|
-
def avatar_attachment
|
339
|
-
OpenStruct.new
|
340
|
-
end
|
341
|
-
|
342
|
-
def avatars_attachments
|
343
|
-
OpenStruct.new
|
344
|
-
end
|
345
|
-
|
346
|
-
def remote_cover_url
|
347
|
-
"/uploads/cover.png"
|
348
|
-
end
|
349
|
-
|
350
|
-
def profile_image_attacher
|
351
|
-
OpenStruct.new
|
352
|
-
end
|
353
|
-
|
354
|
-
def portrait_file_name
|
355
|
-
"portrait.png"
|
356
|
-
end
|
357
|
-
end
|