padrino-helpers 0.16.0.pre4 → 0.16.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/README.rdoc +29 -29
- data/Rakefile +1 -1
- data/lib/padrino/rendering/erb_template.rb +7 -7
- data/lib/padrino/rendering/erubi_template.rb +4 -4
- data/lib/padrino/rendering/erubis_template.rb +4 -4
- data/lib/padrino/rendering/haml_template.rb +1 -1
- data/lib/padrino/rendering/hamlit_template.rb +4 -4
- data/lib/padrino/rendering/slim_template.rb +5 -5
- data/lib/padrino/rendering.rb +54 -45
- data/lib/padrino/safe_buffer.rb +31 -36
- data/lib/padrino-helpers/asset_tag_helpers.rb +48 -48
- data/lib/padrino-helpers/form_builder/abstract_form_builder.rb +74 -70
- data/lib/padrino-helpers/form_builder/standard_form_builder.rb +20 -20
- data/lib/padrino-helpers/form_helpers/errors.rb +14 -14
- data/lib/padrino-helpers/form_helpers/options.rb +25 -24
- data/lib/padrino-helpers/form_helpers/security.rb +5 -5
- data/lib/padrino-helpers/form_helpers.rb +133 -133
- data/lib/padrino-helpers/format_helpers.rb +61 -63
- data/lib/padrino-helpers/number_helpers.rb +82 -78
- data/lib/padrino-helpers/output_helpers/abstract_handler.rb +5 -3
- data/lib/padrino-helpers/output_helpers/erb_handler.rb +2 -2
- data/lib/padrino-helpers/output_helpers/haml_handler.rb +1 -1
- data/lib/padrino-helpers/output_helpers.rb +16 -17
- data/lib/padrino-helpers/render_helpers.rb +28 -27
- data/lib/padrino-helpers/tag_helpers.rb +62 -58
- data/lib/padrino-helpers/translation_helpers.rb +2 -2
- data/lib/padrino-helpers.rb +1 -2
- data/padrino-helpers.gemspec +17 -17
- data/test/fixtures/apps/render.rb +2 -2
- data/test/fixtures/markup_app/app.rb +9 -8
- data/test/fixtures/markup_app/views/button_to.erb +3 -3
- data/test/fixtures/markup_app/views/button_to.haml +2 -2
- data/test/fixtures/markup_app/views/button_to.slim +3 -3
- data/test/fixtures/markup_app/views/content_for.erb +4 -4
- data/test/fixtures/markup_app/views/content_for.haml +4 -4
- data/test/fixtures/markup_app/views/content_for.slim +2 -2
- data/test/fixtures/markup_app/views/content_tag.erb +3 -3
- data/test/fixtures/markup_app/views/content_tag.haml +3 -3
- data/test/fixtures/markup_app/views/content_tag.slim +3 -3
- data/test/fixtures/markup_app/views/fields_for.erb +2 -2
- data/test/fixtures/markup_app/views/fields_for.haml +2 -2
- data/test/fixtures/markup_app/views/fields_for.slim +2 -2
- data/test/fixtures/markup_app/views/form_for.erb +41 -41
- data/test/fixtures/markup_app/views/form_for.haml +41 -41
- data/test/fixtures/markup_app/views/form_for.slim +41 -42
- data/test/fixtures/markup_app/views/form_tag.erb +47 -47
- data/test/fixtures/markup_app/views/form_tag.haml +48 -48
- data/test/fixtures/markup_app/views/form_tag.slim +49 -49
- data/test/fixtures/markup_app/views/link_to.erb +2 -2
- data/test/fixtures/markup_app/views/link_to.haml +2 -2
- data/test/fixtures/markup_app/views/link_to.slim +2 -2
- data/test/fixtures/markup_app/views/meta_tag.erb +2 -2
- data/test/fixtures/markup_app/views/meta_tag.haml +2 -2
- data/test/fixtures/markup_app/views/meta_tag.slim +2 -2
- data/test/fixtures/markup_app/views/simple_partial.erb +1 -1
- data/test/fixtures/markup_app/views/simple_partial.haml +1 -1
- data/test/fixtures/markup_app/views/simple_partial.slim +1 -1
- data/test/fixtures/render_app/app.rb +13 -12
- data/test/fixtures/render_app/views/_unsafe.html.builder +1 -1
- data/test/fixtures/render_app/views/_unsafe_object.html.builder +1 -1
- data/test/fixtures/render_app/views/explicit_engine.haml +3 -3
- data/test/helper.rb +19 -19
- data/test/test_asset_tag_helpers.rb +133 -133
- data/test/test_form_builder.rb +629 -628
- data/test/test_form_helpers.rb +610 -610
- data/test/test_format_helpers.rb +66 -63
- data/test/test_helpers.rb +2 -2
- data/test/test_locale.rb +13 -11
- data/test/test_number_helpers.rb +65 -65
- data/test/test_output_helpers.rb +76 -76
- data/test/test_render_helpers.rb +101 -101
- data/test/test_rendering.rb +329 -326
- data/test/test_rendering_extensions.rb +4 -4
- data/test/test_tag_helpers.rb +55 -55
- metadata +6 -6
|
@@ -6,16 +6,16 @@ module Padrino
|
|
|
6
6
|
attr_accessor :template, :object, :multipart
|
|
7
7
|
attr_reader :namespace, :is_nested, :parent_form, :nested_index, :attributes_name, :model_name
|
|
8
8
|
|
|
9
|
-
def initialize(template, object, options={})
|
|
9
|
+
def initialize(template, object, options = {})
|
|
10
10
|
@template = template
|
|
11
|
-
|
|
12
|
-
@object = object.
|
|
13
|
-
|
|
11
|
+
raise 'FormBuilder template must be initialized' unless template
|
|
12
|
+
@object = object.is_a?(Symbol) ? build_object(object) : object
|
|
13
|
+
raise "FormBuilder object must be present. If there's no object, use a symbol instead (i.e. :user)" unless object
|
|
14
14
|
@options = options
|
|
15
15
|
@namespace = options[:namespace]
|
|
16
16
|
@model_name = options[:as] || Inflections.underscore(@object.class).tr('/', '_')
|
|
17
17
|
nested = options[:nested]
|
|
18
|
-
if @is_nested = nested && (nested_parent = nested[:parent]) && nested_parent.respond_to?(:object)
|
|
18
|
+
if (@is_nested = nested && (nested_parent = nested[:parent]) && nested_parent.respond_to?(:object))
|
|
19
19
|
@parent_form = nested_parent
|
|
20
20
|
@nested_index = nested[:index]
|
|
21
21
|
@attributes_name = "#{nested[:association]}_attributes"
|
|
@@ -26,120 +26,122 @@ module Padrino
|
|
|
26
26
|
@template.error_messages_for object, *params
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
-
def error_message_on(field, options={})
|
|
29
|
+
def error_message_on(field, options = {})
|
|
30
30
|
@template.error_message_on object, field, options
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
def label(field, options={}, &block)
|
|
34
|
-
@template.label_tag(field_id(field), { :
|
|
33
|
+
def label(field, options = {}, &block)
|
|
34
|
+
@template.label_tag(field_id(field), { caption: "#{field_human_name(field)}: " }.update(options), &block)
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
def hidden_field(field, options={})
|
|
37
|
+
def hidden_field(field, options = {})
|
|
38
38
|
@template.hidden_field_tag field_name(field), default_options(field, options)
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
def text_field(field, options={})
|
|
41
|
+
def text_field(field, options = {})
|
|
42
42
|
@template.text_field_tag field_name(field), default_options(field, options)
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
def number_field(field, options={})
|
|
45
|
+
def number_field(field, options = {})
|
|
46
46
|
@template.number_field_tag field_name(field), default_options(field, options)
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
def telephone_field(field, options={})
|
|
49
|
+
def telephone_field(field, options = {})
|
|
50
50
|
@template.telephone_field_tag field_name(field), default_options(field, options)
|
|
51
51
|
end
|
|
52
|
-
|
|
52
|
+
alias phone_field telephone_field
|
|
53
53
|
|
|
54
|
-
def email_field(field, options={})
|
|
54
|
+
def email_field(field, options = {})
|
|
55
55
|
@template.email_field_tag field_name(field), default_options(field, options)
|
|
56
56
|
end
|
|
57
57
|
|
|
58
|
-
def search_field(field, options={})
|
|
58
|
+
def search_field(field, options = {})
|
|
59
59
|
@template.search_field_tag field_name(field), default_options(field, options)
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
-
def url_field(field, options={})
|
|
62
|
+
def url_field(field, options = {})
|
|
63
63
|
@template.url_field_tag field_name(field), default_options(field, options)
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
-
def text_area(field, options={})
|
|
66
|
+
def text_area(field, options = {})
|
|
67
67
|
@template.text_area_tag field_name(field), default_options(field, options)
|
|
68
68
|
end
|
|
69
69
|
|
|
70
|
-
def password_field(field, options={})
|
|
70
|
+
def password_field(field, options = {})
|
|
71
71
|
@template.password_field_tag field_name(field), default_options(field, options)
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
-
def select(field, options={})
|
|
74
|
+
def select(field, options = {})
|
|
75
75
|
@template.select_tag field_name(field), default_options(field, options)
|
|
76
76
|
end
|
|
77
77
|
|
|
78
|
-
def check_box_group(field, options={})
|
|
78
|
+
def check_box_group(field, options = {})
|
|
79
79
|
labeled_group(field, options) do |attributes|
|
|
80
|
-
@template.check_box_tag(field_name(field)
|
|
80
|
+
@template.check_box_tag("#{field_name(field)}[]", attributes)
|
|
81
81
|
end
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
-
def radio_button_group(field, options={})
|
|
84
|
+
def radio_button_group(field, options = {})
|
|
85
85
|
labeled_group(field, options) do |attributes|
|
|
86
86
|
@template.radio_button_tag(field_name(field), attributes)
|
|
87
87
|
end
|
|
88
88
|
end
|
|
89
89
|
|
|
90
|
-
def check_box(field, options={})
|
|
91
|
-
options = default_options(field, options, :
|
|
90
|
+
def check_box(field, options = {})
|
|
91
|
+
options = default_options(field, options, value: '1')
|
|
92
92
|
options[:checked] = true if is_checked?(field, options)
|
|
93
93
|
name = field_name(field)
|
|
94
|
-
html = @template.hidden_field_tag(name, :
|
|
94
|
+
html = @template.hidden_field_tag(name, value: options.delete(:uncheck_value) || '0')
|
|
95
95
|
html << @template.check_box_tag(name, options)
|
|
96
96
|
end
|
|
97
97
|
|
|
98
|
-
def radio_button(field, options={})
|
|
98
|
+
def radio_button(field, options = {})
|
|
99
99
|
options = default_options(field, options)
|
|
100
100
|
options[:checked] = true if is_checked?(field, options)
|
|
101
101
|
options[:id] = field_id(field, options[:value])
|
|
102
102
|
@template.radio_button_tag field_name(field), options
|
|
103
103
|
end
|
|
104
104
|
|
|
105
|
-
def file_field(field, options={})
|
|
105
|
+
def file_field(field, options = {})
|
|
106
106
|
self.multipart = true
|
|
107
|
-
|
|
107
|
+
options = default_options(field, options)
|
|
108
|
+
options.delete(:value)
|
|
109
|
+
@template.file_field_tag field_name(field), options
|
|
108
110
|
end
|
|
109
111
|
|
|
110
112
|
def submit(*args)
|
|
111
113
|
@template.submit_tag(*args)
|
|
112
114
|
end
|
|
113
115
|
|
|
114
|
-
def image_submit(source, options={})
|
|
116
|
+
def image_submit(source, options = {})
|
|
115
117
|
@template.image_submit_tag source, options
|
|
116
118
|
end
|
|
117
119
|
|
|
118
|
-
def datetime_field(field, options={})
|
|
120
|
+
def datetime_field(field, options = {})
|
|
119
121
|
@template.datetime_field_tag field_name(field), default_options(field, options)
|
|
120
122
|
end
|
|
121
123
|
|
|
122
|
-
def datetime_local_field(field, options={})
|
|
124
|
+
def datetime_local_field(field, options = {})
|
|
123
125
|
@template.datetime_local_field_tag field_name(field), default_options(field, options)
|
|
124
126
|
end
|
|
125
127
|
|
|
126
|
-
def date_field(field, options={})
|
|
128
|
+
def date_field(field, options = {})
|
|
127
129
|
@template.date_field_tag field_name(field), default_options(field, options)
|
|
128
130
|
end
|
|
129
131
|
|
|
130
|
-
def month_field(field, options={})
|
|
132
|
+
def month_field(field, options = {})
|
|
131
133
|
@template.month_field_tag field_name(field), default_options(field, options)
|
|
132
134
|
end
|
|
133
135
|
|
|
134
|
-
def week_field(field, options={})
|
|
136
|
+
def week_field(field, options = {})
|
|
135
137
|
@template.week_field_tag field_name(field), default_options(field, options)
|
|
136
138
|
end
|
|
137
139
|
|
|
138
|
-
def time_field(field, options={})
|
|
140
|
+
def time_field(field, options = {})
|
|
139
141
|
@template.time_field_tag field_name(field), default_options(field, options)
|
|
140
142
|
end
|
|
141
143
|
|
|
142
|
-
def color_field(field, options={})
|
|
144
|
+
def color_field(field, options = {})
|
|
143
145
|
@template.color_field_tag field_name(field), default_options(field, options)
|
|
144
146
|
end
|
|
145
147
|
|
|
@@ -149,15 +151,15 @@ module Padrino
|
|
|
149
151
|
# f.fields_for :addresses, address
|
|
150
152
|
# f.fields_for :addresses, @addresses
|
|
151
153
|
# f.fields_for :addresses, address, index: i
|
|
152
|
-
def fields_for(child_association, collection=nil, options={}, &block)
|
|
154
|
+
def fields_for(child_association, collection = nil, options = {}, &block)
|
|
153
155
|
default_collection = self.object.send(child_association)
|
|
154
156
|
collection ||= default_collection
|
|
155
157
|
include_index = default_collection.respond_to?(:each)
|
|
156
158
|
|
|
157
|
-
nested_options = { :
|
|
158
|
-
Array(collection).each_with_index.inject(SafeBuffer.new) do |all,(child_instance,index)|
|
|
159
|
+
nested_options = { parent: self, association: child_association }
|
|
160
|
+
Array(collection).each_with_index.inject(SafeBuffer.new) do |all, (child_instance, index)|
|
|
159
161
|
nested_options[:index] = options[:index] || (include_index ? index : nil)
|
|
160
|
-
all << @template.fields_for(child_instance,
|
|
162
|
+
all << @template.fields_for(child_instance, { nested: nested_options, builder: self.class }, &block) << "\n"
|
|
161
163
|
end
|
|
162
164
|
end
|
|
163
165
|
|
|
@@ -169,9 +171,10 @@ module Padrino
|
|
|
169
171
|
|
|
170
172
|
# Returns the known field types for a Formbuilder.
|
|
171
173
|
def self.field_types
|
|
172
|
-
[
|
|
173
|
-
|
|
174
|
-
|
|
174
|
+
%i[
|
|
175
|
+
hidden_field text_field text_area password_field file_field radio_button check_box select
|
|
176
|
+
number_field telephone_field email_field search_field url_field
|
|
177
|
+
datetime_field datetime_local_field date_field month_field week_field time_field color_field
|
|
175
178
|
]
|
|
176
179
|
end
|
|
177
180
|
|
|
@@ -179,14 +182,14 @@ module Padrino
|
|
|
179
182
|
# Returns the human name of the field. Look that use builtin I18n.
|
|
180
183
|
#
|
|
181
184
|
def field_human_name(field)
|
|
182
|
-
I18n.translate("#{model_name}.attributes.#{field}", :
|
|
185
|
+
I18n.translate("#{model_name}.attributes.#{field}", count: 1, default: Inflections.humanize(field), scope: :models)
|
|
183
186
|
end
|
|
184
187
|
|
|
185
188
|
##
|
|
186
189
|
# Returns the object's models name.
|
|
187
190
|
#
|
|
188
|
-
def object_model_name(explicit_object=object)
|
|
189
|
-
explicit_object.is_a?(Symbol) ? explicit_object : explicit_object.class.to_s.underscore.gsub(
|
|
191
|
+
def object_model_name(explicit_object = object)
|
|
192
|
+
explicit_object.is_a?(Symbol) ? explicit_object : explicit_object.class.to_s.underscore.gsub('/', '_')
|
|
190
193
|
end
|
|
191
194
|
|
|
192
195
|
##
|
|
@@ -194,7 +197,7 @@ module Padrino
|
|
|
194
197
|
# field_name(:username) => "user[username]"
|
|
195
198
|
# field_name(:number) => "user[telephone_attributes][number]"
|
|
196
199
|
# field_name(:street) => "user[addresses_attributes][0][street]"
|
|
197
|
-
def field_name(field=nil)
|
|
200
|
+
def field_name(field = nil)
|
|
198
201
|
result = field_name_fragment
|
|
199
202
|
result << "[#{field}]" if field
|
|
200
203
|
result
|
|
@@ -206,8 +209,8 @@ module Padrino
|
|
|
206
209
|
# field_id(:gender, :male) => "user_gender_male"
|
|
207
210
|
# field_name(:number) => "user_telephone_attributes_number"
|
|
208
211
|
# field_name(:street) => "user_addresses_attributes_0_street"
|
|
209
|
-
def field_id(field=nil, value=nil)
|
|
210
|
-
result =
|
|
212
|
+
def field_id(field = nil, value = nil)
|
|
213
|
+
result = namespace && !is_nested ? "#{namespace}_" : ''
|
|
211
214
|
result << field_id_fragment
|
|
212
215
|
result << "_#{field}" if field
|
|
213
216
|
result << "_#{value}" if value
|
|
@@ -238,29 +241,29 @@ module Padrino
|
|
|
238
241
|
##
|
|
239
242
|
# Builds a group of labels for radios or checkboxes.
|
|
240
243
|
#
|
|
241
|
-
def labeled_group(field, options={})
|
|
242
|
-
options = { :
|
|
243
|
-
options.update(error_class(field)){ |_
|
|
244
|
+
def labeled_group(field, options = {})
|
|
245
|
+
options = { id: field_id(field), selected: field_value(field) }.update(options)
|
|
246
|
+
options.update(error_class(field)) { |_, *values| values.compact.join(' ') }
|
|
244
247
|
selected_values = resolve_checked_values(field, options)
|
|
245
|
-
variants_for_group(options).inject(SafeBuffer.new) do |html, (caption,value)|
|
|
248
|
+
variants_for_group(options).inject(SafeBuffer.new) do |html, (caption, value)|
|
|
246
249
|
variant_id = "#{options[:id]}_#{value}"
|
|
247
|
-
attributes = { :
|
|
250
|
+
attributes = { value: value, id: variant_id, checked: selected_values.include?(value) }
|
|
248
251
|
caption = yield(attributes) << ' ' << caption
|
|
249
|
-
html << @template.label_tag("#{field_name(field)}[]", :
|
|
252
|
+
html << @template.label_tag("#{field_name(field)}[]", for: variant_id, caption: caption)
|
|
250
253
|
end
|
|
251
254
|
end
|
|
252
255
|
|
|
253
256
|
private
|
|
254
257
|
|
|
255
258
|
def is_checked?(field, options)
|
|
256
|
-
!options.
|
|
259
|
+
!options.key?(:checked) && [options[:value].to_s, 'true'].include?(field_value(field).to_s)
|
|
257
260
|
end
|
|
258
261
|
|
|
259
262
|
def variants_for_group(options)
|
|
260
|
-
if variants = options[:options]
|
|
261
|
-
variants.map{ |caption, value| [caption.to_s, (value||caption).to_s] }
|
|
262
|
-
elsif collection = options[:collection]
|
|
263
|
-
collection.map{ |variant| field_values(variant, options) }
|
|
263
|
+
if (variants = options[:options])
|
|
264
|
+
variants.map { |caption, value| [caption.to_s, (value || caption).to_s] }
|
|
265
|
+
elsif (collection = options[:collection])
|
|
266
|
+
collection.map { |variant| field_values(variant, options) }
|
|
264
267
|
else
|
|
265
268
|
[]
|
|
266
269
|
end
|
|
@@ -279,20 +282,20 @@ module Padrino
|
|
|
279
282
|
end
|
|
280
283
|
|
|
281
284
|
def field_methods(options)
|
|
282
|
-
options[:fields] || [
|
|
285
|
+
options[:fields] || %i[name id]
|
|
283
286
|
end
|
|
284
287
|
|
|
285
288
|
def field_values(object, options)
|
|
286
|
-
field_methods(options).map{ |field| object.send(field).to_s }
|
|
289
|
+
field_methods(options).map { |field| object.send(field).to_s }
|
|
287
290
|
end
|
|
288
291
|
|
|
289
292
|
def field_name_fragment
|
|
290
293
|
if is_nested
|
|
291
294
|
fragment = parent_form.field_name.dup << "[#{attributes_name}"
|
|
292
295
|
fragment << "][#{nested_index}" if nested_index
|
|
293
|
-
fragment <<
|
|
296
|
+
fragment << ']'
|
|
294
297
|
else
|
|
295
|
-
|
|
298
|
+
model_name.to_s.dup
|
|
296
299
|
end
|
|
297
300
|
end
|
|
298
301
|
|
|
@@ -302,19 +305,20 @@ module Padrino
|
|
|
302
305
|
fragment << "_#{nested_index}" if nested_index
|
|
303
306
|
fragment
|
|
304
307
|
else
|
|
305
|
-
|
|
308
|
+
model_name.to_s.dup
|
|
306
309
|
end
|
|
307
310
|
end
|
|
308
311
|
|
|
309
312
|
def error_class(field)
|
|
310
313
|
error = @object.errors[field] if @object.respond_to?(:errors)
|
|
311
|
-
error.nil? || error.empty? ? {} : { :
|
|
314
|
+
error.nil? || error.empty? ? {} : { class: 'invalid' }
|
|
312
315
|
end
|
|
313
316
|
|
|
314
|
-
def default_options(field, options, defaults={})
|
|
315
|
-
{ :
|
|
316
|
-
|
|
317
|
-
|
|
317
|
+
def default_options(field, options, defaults = {})
|
|
318
|
+
{ value: field_value(field), id: field_id(field) }
|
|
319
|
+
.update(defaults)
|
|
320
|
+
.update(options)
|
|
321
|
+
.update(error_class(field)) { |_, *values| values.compact.join(' ') }
|
|
318
322
|
end
|
|
319
323
|
end
|
|
320
324
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
require_relative 'abstract_form_builder' unless defined?(AbstractFormBuilder)
|
|
2
2
|
|
|
3
3
|
module Padrino
|
|
4
4
|
module Helpers
|
|
@@ -7,33 +7,33 @@ module Padrino
|
|
|
7
7
|
##
|
|
8
8
|
# StandardFormBuilder
|
|
9
9
|
#
|
|
10
|
-
# text_field_block(:username, { :
|
|
11
|
-
# text_area_block(:summary, { :
|
|
12
|
-
# password_field_block(:password, { :
|
|
13
|
-
# file_field_block(:photo, { :
|
|
14
|
-
# check_box_block(:remember_me, { :
|
|
15
|
-
# select_block(:color, :
|
|
10
|
+
# text_field_block(:username, { class: 'long' }, { class: 'wide-label' })
|
|
11
|
+
# text_area_block(:summary, { class: 'long' }, { class: 'wide-label' })
|
|
12
|
+
# password_field_block(:password, { class: 'long' }, { class: 'wide-label' })
|
|
13
|
+
# file_field_block(:photo, { class: 'long' }, { class: 'wide-label' })
|
|
14
|
+
# check_box_block(:remember_me, { class: 'long' }, { class: 'wide-label' })
|
|
15
|
+
# select_block(:color, options: ['green', 'black'])
|
|
16
16
|
#
|
|
17
|
-
(self.field_types - [
|
|
18
|
-
class_eval
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
(self.field_types - %i[hidden_field radio_button]).each do |field_type|
|
|
18
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
|
19
|
+
def #{field_type}_block(field, options={}, label_options={})
|
|
20
|
+
if options[:caption]
|
|
21
|
+
options = options.dup
|
|
22
|
+
label_options = { caption: options.delete(:caption) }.update(label_options)
|
|
23
|
+
end
|
|
24
|
+
field_html = label(field, label_options)
|
|
25
|
+
field_html << #{field_type}(field, options)
|
|
26
|
+
@template.content_tag(:p, field_html)
|
|
23
27
|
end
|
|
24
|
-
|
|
25
|
-
field_html << #{field_type}(field, options)
|
|
26
|
-
@template.content_tag(:p, field_html)
|
|
27
|
-
end
|
|
28
|
-
EOF
|
|
28
|
+
RUBY
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
def submit_block(caption, options={})
|
|
31
|
+
def submit_block(caption, options = {})
|
|
32
32
|
submit_html = self.submit(caption, options)
|
|
33
33
|
@template.content_tag(:p, submit_html)
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
def image_submit_block(source, options={})
|
|
36
|
+
def image_submit_block(source, options = {})
|
|
37
37
|
submit_html = self.image_submit(source, options)
|
|
38
38
|
@template.content_tag(:p, submit_html)
|
|
39
39
|
end
|
|
@@ -38,8 +38,8 @@ module Padrino
|
|
|
38
38
|
#
|
|
39
39
|
def error_messages_for(*objects)
|
|
40
40
|
options = objects.last.is_a?(Hash) ? Utils.symbolize_keys(objects.pop) : {}
|
|
41
|
-
objects = objects.map{ |obj| resolve_object(obj) }.compact
|
|
42
|
-
count = objects.inject(0){ |sum, object| sum + object.errors.count }
|
|
41
|
+
objects = objects.map { |obj| resolve_object(obj) }.compact
|
|
42
|
+
count = objects.inject(0) { |sum, object| sum + object.errors.count }
|
|
43
43
|
return SafeBuffer.new if count.zero?
|
|
44
44
|
|
|
45
45
|
content_tag(:div, error_contents(objects, count, options), error_html_attributes(options))
|
|
@@ -68,27 +68,27 @@ module Padrino
|
|
|
68
68
|
# error_message_on @post, :title
|
|
69
69
|
#
|
|
70
70
|
# # => <div class="custom" style="border:1px solid red">can't be blank</div>
|
|
71
|
-
# error_message_on :post, :title, :
|
|
71
|
+
# error_message_on :post, :title, tag: :id, class: :custom, style: 'border:1px solid red'
|
|
72
72
|
#
|
|
73
73
|
# # => <div class="error">This title can't be blank (or it won't work)</div>
|
|
74
|
-
# error_message_on :post, :title, :
|
|
74
|
+
# error_message_on :post, :title, prepend: 'This title', append: "(or it won't work)"
|
|
75
75
|
#
|
|
76
76
|
# @return [String] The html display of an error for a particular +object+ and +field+.
|
|
77
77
|
#
|
|
78
78
|
# @api public
|
|
79
|
-
def error_message_on(object, field, options={})
|
|
79
|
+
def error_message_on(object, field, options = {})
|
|
80
80
|
error = Array(resolve_object(object).errors[field]).first
|
|
81
81
|
return SafeBuffer.new unless error
|
|
82
|
-
options = { :
|
|
82
|
+
options = { tag: :span, class: :error }.update(options)
|
|
83
83
|
tag = options.delete(:tag)
|
|
84
|
-
error = [options.delete(:prepend), error, options.delete(:append)].compact.join(
|
|
84
|
+
error = [options.delete(:prepend), error, options.delete(:append)].compact.join(' ')
|
|
85
85
|
content_tag(tag, error, options)
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
private
|
|
89
89
|
|
|
90
90
|
def error_contents(objects, count, options)
|
|
91
|
-
object_name = options[:object_name] || Inflections.underscore(objects.first.class).gsub(
|
|
91
|
+
object_name = options[:object_name] || Inflections.underscore(objects.first.class).gsub('/', ' ')
|
|
92
92
|
|
|
93
93
|
contents = SafeBuffer.new
|
|
94
94
|
contents << error_header_tag(options, object_name, count)
|
|
@@ -97,9 +97,9 @@ module Padrino
|
|
|
97
97
|
end
|
|
98
98
|
|
|
99
99
|
def error_list_tag(objects, object_name)
|
|
100
|
-
errors = objects.inject({}){ |all,object| all.update(object.errors) }
|
|
100
|
+
errors = objects.inject({}) { |all, object| all.update(object.errors) }
|
|
101
101
|
error_messages = errors.inject(SafeBuffer.new) do |all, (field, message)|
|
|
102
|
-
field_name = I18n.t(field, :
|
|
102
|
+
field_name = I18n.t(field, default: Inflections.humanize(field), scope: [:models, object_name, :attributes])
|
|
103
103
|
all << content_tag(:li, "#{field_name} #{message}")
|
|
104
104
|
end
|
|
105
105
|
content_tag(:ul, error_messages)
|
|
@@ -107,19 +107,19 @@ module Padrino
|
|
|
107
107
|
|
|
108
108
|
def error_header_tag(options, object_name, count)
|
|
109
109
|
header_message = options[:header_message] || begin
|
|
110
|
-
model_name = I18n.t(:name, :
|
|
111
|
-
I18n.t :header, :
|
|
110
|
+
model_name = I18n.t(:name, default: Inflections.humanize(object_name), scope: [:models, object_name], count: 1)
|
|
111
|
+
I18n.t :header, count: count, model: model_name, locale: options[:locale], scope: %i[models errors template]
|
|
112
112
|
end
|
|
113
113
|
content_tag(options[:header_tag] || :h2, header_message) unless header_message.empty?
|
|
114
114
|
end
|
|
115
115
|
|
|
116
116
|
def error_body_tag(options)
|
|
117
|
-
body_message = options[:message] || I18n.t(:body, :
|
|
117
|
+
body_message = options[:message] || I18n.t(:body, locale: options[:locale], scope: %i[models errors template])
|
|
118
118
|
content_tag(:p, body_message) unless body_message.empty?
|
|
119
119
|
end
|
|
120
120
|
|
|
121
121
|
def error_html_attributes(options)
|
|
122
|
-
[
|
|
122
|
+
%i[id class style].each_with_object({}) do |key, all|
|
|
123
123
|
if options.include?(key)
|
|
124
124
|
value = options[key]
|
|
125
125
|
all[key] = value if value
|
|
@@ -7,12 +7,14 @@ module Padrino
|
|
|
7
7
|
module Options
|
|
8
8
|
def extract_option_tags!(options)
|
|
9
9
|
state = extract_option_state!(options)
|
|
10
|
-
option_tags =
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
option_tags =
|
|
11
|
+
if options[:grouped_options]
|
|
12
|
+
grouped_options_for_select(options.delete(:grouped_options), state)
|
|
13
|
+
else
|
|
14
|
+
options_for_select(extract_option_items!(options), state)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
if (prompt = options.delete(:include_blank))
|
|
16
18
|
option_tags.unshift(blank_option(prompt))
|
|
17
19
|
end
|
|
18
20
|
option_tags
|
|
@@ -28,11 +30,11 @@ module Padrino
|
|
|
28
30
|
when nil, false
|
|
29
31
|
nil
|
|
30
32
|
when String
|
|
31
|
-
content_tag(:option, prompt, :
|
|
33
|
+
content_tag(:option, prompt, value: '')
|
|
32
34
|
when Array
|
|
33
|
-
content_tag(:option, prompt.first, :
|
|
35
|
+
content_tag(:option, prompt.first, value: prompt.last)
|
|
34
36
|
else
|
|
35
|
-
content_tag(:option, '', :
|
|
37
|
+
content_tag(:option, '', value: '')
|
|
36
38
|
end
|
|
37
39
|
end
|
|
38
40
|
|
|
@@ -40,24 +42,23 @@ module Padrino
|
|
|
40
42
|
# Returns whether the option should be selected or not.
|
|
41
43
|
#
|
|
42
44
|
# @example
|
|
43
|
-
# option_is_selected?(
|
|
44
|
-
# option_is_selected?(
|
|
45
|
+
# option_is_selected?('red', 'Red', ['red', 'blue']) => true
|
|
46
|
+
# option_is_selected?('red', 'Red', ['green', 'blue']) => false
|
|
45
47
|
#
|
|
46
48
|
def option_is_selected?(value, caption, selected_values)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
caption.to_s == selected.to_s
|
|
51
|
-
end
|
|
49
|
+
check_value = (value || caption).to_s
|
|
50
|
+
|
|
51
|
+
Array(selected_values).any? { |selected| check_value == selected.to_s }
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
##
|
|
55
55
|
# Returns the options tags for a select based on the given option items.
|
|
56
56
|
#
|
|
57
57
|
def options_for_select(option_items, state = {})
|
|
58
|
-
return [] if option_items.
|
|
58
|
+
return [] if option_items.none?
|
|
59
|
+
|
|
59
60
|
option_items.map do |caption, value, attributes|
|
|
60
|
-
html_attributes = { :
|
|
61
|
+
html_attributes = { value: value || caption }.merge(attributes || {})
|
|
61
62
|
html_attributes[:selected] ||= option_is_selected?(html_attributes[:value], caption, state[:selected])
|
|
62
63
|
html_attributes[:disabled] ||= option_is_selected?(html_attributes[:value], caption, state[:disabled])
|
|
63
64
|
content_tag(:option, caption, html_attributes)
|
|
@@ -70,18 +71,18 @@ module Padrino
|
|
|
70
71
|
def grouped_options_for_select(collection, state = {})
|
|
71
72
|
collection.map do |item|
|
|
72
73
|
caption = item.shift
|
|
73
|
-
attributes = item.last.
|
|
74
|
+
attributes = item.last.is_a?(Hash) ? item.pop : {}
|
|
74
75
|
value = item.flatten(1)
|
|
75
|
-
attributes = value.pop if value.last.
|
|
76
|
-
html_attributes = { :
|
|
76
|
+
attributes = value.pop if value.last.is_a?(Hash)
|
|
77
|
+
html_attributes = { label: caption }.merge(attributes || {})
|
|
77
78
|
content_tag(:optgroup, options_for_select(value, state), html_attributes)
|
|
78
79
|
end
|
|
79
80
|
end
|
|
80
81
|
|
|
81
82
|
def extract_option_state!(options)
|
|
82
83
|
{
|
|
83
|
-
:
|
|
84
|
-
:
|
|
84
|
+
selected: Array(options.delete(:value)) | Array(options.delete(:selected)) | Array(options.delete(:selected_options)),
|
|
85
|
+
disabled: Array(options.delete(:disabled_options))
|
|
85
86
|
}
|
|
86
87
|
end
|
|
87
88
|
|
|
@@ -89,7 +90,7 @@ module Padrino
|
|
|
89
90
|
if options[:collection]
|
|
90
91
|
fields = options.delete(:fields)
|
|
91
92
|
collection = options.delete(:collection)
|
|
92
|
-
collection.map{ |item| [
|
|
93
|
+
collection.map { |item| [item.send(fields.first), item.send(fields.last)] }
|
|
93
94
|
else
|
|
94
95
|
options.delete(:options) || []
|
|
95
96
|
end
|
|
@@ -19,7 +19,7 @@ module Padrino
|
|
|
19
19
|
# csrf_token_field
|
|
20
20
|
#
|
|
21
21
|
def csrf_token_field
|
|
22
|
-
hidden_field_tag csrf_param, :
|
|
22
|
+
hidden_field_tag csrf_param, value: csrf_token
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
##
|
|
@@ -32,10 +32,10 @@ module Padrino
|
|
|
32
32
|
# csrf_meta_tags
|
|
33
33
|
#
|
|
34
34
|
def csrf_meta_tags
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
return unless is_protected_from_csrf?
|
|
36
|
+
|
|
37
|
+
meta_tag(csrf_param, name: 'csrf-param') <<
|
|
38
|
+
meta_tag(csrf_token, name: 'csrf-token')
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
protected
|