padrino-helpers 0.11.3 → 0.11.4
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 +7 -0
- data/README.rdoc +1 -1
- data/lib/padrino-helpers.rb +3 -5
- data/lib/padrino-helpers/asset_tag_helpers.rb +32 -40
- data/lib/padrino-helpers/breadcrumb_helpers.rb +21 -39
- data/lib/padrino-helpers/form_builder/abstract_form_builder.rb +121 -118
- data/lib/padrino-helpers/form_builder/standard_form_builder.rb +6 -9
- data/lib/padrino-helpers/form_helpers.rb +190 -193
- data/lib/padrino-helpers/format_helpers.rb +29 -42
- data/lib/padrino-helpers/locale/cs.yml +14 -14
- data/lib/padrino-helpers/locale/da.yml +1 -1
- data/lib/padrino-helpers/locale/de.yml +1 -1
- data/lib/padrino-helpers/locale/en.yml +16 -16
- data/lib/padrino-helpers/locale/es.yml +16 -16
- data/lib/padrino-helpers/locale/fr.yml +1 -2
- data/lib/padrino-helpers/locale/hu.yml +16 -16
- data/lib/padrino-helpers/locale/it.yml +2 -2
- data/lib/padrino-helpers/locale/ja.yml +16 -16
- data/lib/padrino-helpers/locale/lv.yml +16 -16
- data/lib/padrino-helpers/locale/nl.yml +1 -1
- data/lib/padrino-helpers/locale/no.yml +1 -1
- data/lib/padrino-helpers/locale/pl.yml +7 -7
- data/lib/padrino-helpers/locale/pt_br.yml +16 -16
- data/lib/padrino-helpers/locale/ro.yml +16 -16
- data/lib/padrino-helpers/locale/ru.yml +16 -16
- data/lib/padrino-helpers/locale/sv.yml +16 -16
- data/lib/padrino-helpers/locale/tr.yml +16 -16
- data/lib/padrino-helpers/locale/uk.yml +16 -16
- data/lib/padrino-helpers/locale/zh_cn.yml +16 -16
- data/lib/padrino-helpers/locale/zh_tw.yml +16 -16
- data/lib/padrino-helpers/number_helpers.rb +10 -15
- data/lib/padrino-helpers/output_helpers.rb +49 -57
- data/lib/padrino-helpers/output_helpers/abstract_handler.rb +16 -18
- data/lib/padrino-helpers/output_helpers/erb_handler.rb +11 -12
- data/lib/padrino-helpers/output_helpers/haml_handler.rb +9 -9
- data/lib/padrino-helpers/output_helpers/slim_handler.rb +11 -13
- data/lib/padrino-helpers/render_helpers.rb +5 -6
- data/lib/padrino-helpers/tag_helpers.rb +18 -21
- data/lib/padrino-helpers/translation_helpers.rb +4 -6
- data/test/fixtures/markup_app/app.rb +7 -3
- data/test/fixtures/render_app/app.rb +1 -0
- data/test/test_asset_tag_helpers.rb +1 -1
- data/test/test_form_builder.rb +5 -6
- data/test/test_form_helpers.rb +24 -12
- data/test/test_format_helpers.rb +3 -3
- data/test/test_number_helpers.rb +4 -0
- data/test/test_output_helpers.rb +1 -1
- data/test/test_render_helpers.rb +1 -1
- data/test/test_tag_helpers.rb +1 -1
- metadata +9 -15
@@ -1,7 +1,7 @@
|
|
1
1
|
module Padrino
|
2
2
|
module Helpers
|
3
|
-
module FormBuilder
|
4
|
-
class AbstractFormBuilder
|
3
|
+
module FormBuilder
|
4
|
+
class AbstractFormBuilder
|
5
5
|
attr_accessor :template, :object, :multipart
|
6
6
|
|
7
7
|
def initialize(template, object, options={})
|
@@ -12,37 +12,32 @@ module Padrino
|
|
12
12
|
raise "FormBuilder object must not be a nil value. If there's no object, use a symbol instead! (i.e :user)" unless object
|
13
13
|
end
|
14
14
|
|
15
|
-
# f.error_messages
|
16
15
|
def error_messages(*params)
|
17
16
|
params.unshift object
|
18
17
|
@template.error_messages_for(*params)
|
19
18
|
end
|
20
19
|
|
21
|
-
# f.error_message_on(field)
|
22
20
|
def error_message_on(field, options={})
|
23
21
|
@template.error_message_on(object, field, options)
|
24
22
|
end
|
25
23
|
|
26
|
-
# f.label :username, :caption => "Nickname"
|
27
24
|
def label(field, options={}, &block)
|
28
25
|
options.reverse_merge!(:caption => "#{field_human_name(field)}: ")
|
29
26
|
@template.label_tag(field_id(field), options, &block)
|
30
27
|
end
|
31
28
|
|
32
|
-
# f.hidden_field :session_id, :value => "45"
|
33
29
|
def hidden_field(field, options={})
|
34
30
|
options.reverse_merge!(:value => field_value(field), :id => field_id(field))
|
35
31
|
@template.hidden_field_tag field_name(field), options
|
36
32
|
end
|
37
33
|
|
38
|
-
# f.text_field :username, :value => "(blank)", :id => 'username'
|
39
34
|
def text_field(field, options={})
|
40
35
|
options.reverse_merge!(:value => field_value(field), :id => field_id(field))
|
41
36
|
options.merge!(:class => field_error(field, options))
|
42
37
|
@template.text_field_tag field_name(field), options
|
43
38
|
end
|
44
39
|
|
45
|
-
|
40
|
+
def number_field(field, options={})
|
46
41
|
options.reverse_merge!(:value => field_value(field), :id => field_id(field))
|
47
42
|
options.merge!(:class => field_error(field, options))
|
48
43
|
@template.number_field_tag field_name(field), options
|
@@ -73,35 +68,28 @@ module Padrino
|
|
73
68
|
@template.url_field_tag field_name(field), options
|
74
69
|
end
|
75
70
|
|
76
|
-
# f.text_area :summary, :value => "(enter summary)", :id => 'summary'
|
77
71
|
def text_area(field, options={})
|
78
72
|
options.reverse_merge!(:value => field_value(field), :id => field_id(field))
|
79
73
|
options.merge!(:class => field_error(field, options))
|
80
74
|
@template.text_area_tag field_name(field), options
|
81
75
|
end
|
82
76
|
|
83
|
-
# f.password_field :password, :id => 'password'
|
84
77
|
def password_field(field, options={})
|
85
78
|
options.reverse_merge!(:value => field_value(field), :id => field_id(field))
|
86
79
|
options.merge!(:class => field_error(field, options))
|
87
80
|
@template.password_field_tag field_name(field), options
|
88
81
|
end
|
89
82
|
|
90
|
-
# f.select :color, :options => ['red', 'green'], :include_blank => true
|
91
|
-
# f.select :color, :collection => @colors, :fields => [:name, :id]
|
92
83
|
def select(field, options={})
|
93
84
|
options.reverse_merge!(:id => field_id(field), :selected => field_value(field))
|
94
85
|
options.merge!(:class => field_error(field, options))
|
95
86
|
@template.select_tag field_name(field), options
|
96
87
|
end
|
97
88
|
|
98
|
-
# f.check_box_group :color, :options => ['red', 'green', 'blue'], :selected => ['red', 'blue']
|
99
|
-
# f.check_box_group :color, :collection => @colors, :fields => [:name, :id]
|
100
89
|
def check_box_group(field, options={})
|
101
90
|
selected_values = Array(options[:selected] || field_value(field))
|
102
91
|
if options[:collection]
|
103
92
|
fields = options[:fields] || [:name, :id]
|
104
|
-
# don't use map!, it will break some orms
|
105
93
|
selected_values = selected_values.map{ |v| (v.respond_to?(fields[0]) ? v.send(fields[1]) : v).to_s }
|
106
94
|
end
|
107
95
|
labeled_group( field, options ) do |variant|
|
@@ -109,8 +97,6 @@ module Padrino
|
|
109
97
|
end
|
110
98
|
end
|
111
99
|
|
112
|
-
# f.radio_button_group :color, :options => ['red', 'green']
|
113
|
-
# f.radio_button_group :color, :collection => @colors, :fields => [:name, :id], :selected => @colors.first
|
114
100
|
def radio_button_group(field, options={})
|
115
101
|
fields = options[:fields] || [:name, :id]
|
116
102
|
selected_value = options[:selected] || field_value(field)
|
@@ -120,7 +106,6 @@ module Padrino
|
|
120
106
|
end
|
121
107
|
end
|
122
108
|
|
123
|
-
# f.check_box :remember_me, :value => 'true', :uncheck_value => '0'
|
124
109
|
def check_box(field, options={})
|
125
110
|
html = ActiveSupport::SafeBuffer.new
|
126
111
|
unchecked_value = options.delete(:uncheck_value) || '0'
|
@@ -130,14 +115,12 @@ module Padrino
|
|
130
115
|
html << @template.check_box_tag(field_name(field), options)
|
131
116
|
end
|
132
117
|
|
133
|
-
# f.radio_button :gender, :value => 'male'
|
134
118
|
def radio_button(field, options={})
|
135
119
|
options.reverse_merge!(:id => field_id(field, options[:value]))
|
136
120
|
options.reverse_merge!(:checked => true) if values_matches_field?(field, options[:value])
|
137
121
|
@template.radio_button_tag field_name(field), options
|
138
122
|
end
|
139
123
|
|
140
|
-
# f.file_field :photo, :class => 'avatar'
|
141
124
|
def file_field(field, options={})
|
142
125
|
self.multipart = true
|
143
126
|
options.reverse_merge!(:id => field_id(field))
|
@@ -145,19 +128,18 @@ module Padrino
|
|
145
128
|
@template.file_field_tag field_name(field), options
|
146
129
|
end
|
147
130
|
|
148
|
-
# f.submit "Update", :class => 'large'
|
149
131
|
def submit(*args)
|
150
132
|
options = args[-1].is_a?(Hash) ? args.pop : {}
|
151
133
|
caption = args.length >= 1 ? args.shift : "Submit"
|
152
134
|
@template.submit_tag caption, options
|
153
135
|
end
|
154
136
|
|
155
|
-
# f.image_submit "buttons/submit.png", :class => 'large'
|
156
137
|
def image_submit(source, options={})
|
157
138
|
@template.image_submit_tag source, options
|
158
139
|
end
|
159
140
|
|
160
|
-
|
141
|
+
##
|
142
|
+
# Supports nested fields for a child model within a form.
|
161
143
|
# f.fields_for :addresses
|
162
144
|
# f.fields_for :addresses, address
|
163
145
|
# f.fields_for :addresses, @addresses
|
@@ -166,7 +148,7 @@ module Padrino
|
|
166
148
|
include_index = default_collection.respond_to?(:each)
|
167
149
|
nested_options = { :parent => self, :association => child_association }
|
168
150
|
nested_objects = instance_or_collection ? Array(instance_or_collection) : Array(default_collection)
|
169
|
-
|
151
|
+
nested_objects.each_with_index.map do |child_instance, index|
|
170
152
|
nested_options[:index] = include_index ? index : nil
|
171
153
|
@template.fields_for(child_instance, { :nested => nested_options }, &block)
|
172
154
|
end.join("\n").html_safe
|
@@ -177,112 +159,133 @@ module Padrino
|
|
177
159
|
end
|
178
160
|
|
179
161
|
protected
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
162
|
+
# Returns the known field types for a Formbuilder.
|
163
|
+
def self.field_types
|
164
|
+
[:hidden_field, :text_field, :text_area, :password_field, :file_field, :radio_button, :check_box, :select]
|
165
|
+
end
|
184
166
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
167
|
+
##
|
168
|
+
# Returns true if the value matches the value in the field.
|
169
|
+
# field_has_value?(:gender, 'male')
|
170
|
+
def values_matches_field?(field, value)
|
171
|
+
value.present? && (field_value(field).to_s == value.to_s || field_value(field).to_s == 'true')
|
172
|
+
end
|
190
173
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
174
|
+
##
|
175
|
+
# Add a :invalid css class to the field if it contain an error.
|
176
|
+
#
|
177
|
+
def field_error(field, options)
|
178
|
+
error = @object.errors[field] rescue nil
|
179
|
+
error.blank? ? options[:class] : [options[:class], :invalid].flatten.compact.join(" ")
|
180
|
+
end
|
196
181
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
182
|
+
##
|
183
|
+
# Returns the human name of the field. Look that use builtin I18n.
|
184
|
+
#
|
185
|
+
def field_human_name(field)
|
186
|
+
I18n.translate("#{object_model_name}.attributes.#{field}", :count => 1, :default => field.to_s.humanize, :scope => :models)
|
187
|
+
end
|
201
188
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
189
|
+
##
|
190
|
+
# Returns the name for the given field.
|
191
|
+
# field_name(:username) => "user[username]"
|
192
|
+
# field_name(:number) => "user[telephone_attributes][number]"
|
193
|
+
# field_name(:street) => "user[addresses_attributes][0][street]"
|
194
|
+
def field_name(field=nil)
|
195
|
+
result = field_result
|
196
|
+
result << field_name_fragment if nested_form?
|
197
|
+
result << "[#{field}]" unless field.blank?
|
198
|
+
result.flatten.join
|
199
|
+
end
|
212
200
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
201
|
+
##
|
202
|
+
# Returns the id for the given field.
|
203
|
+
# field_id(:username) => "user_username"
|
204
|
+
# field_id(:gender, :male) => "user_gender_male"
|
205
|
+
# field_name(:number) => "user_telephone_attributes_number"
|
206
|
+
# field_name(:street) => "user_addresses_attributes_0_street"
|
207
|
+
def field_id(field=nil, value=nil)
|
208
|
+
result = []
|
209
|
+
result << "#{@options[:namespace]}_" if @options[:namespace] && root_form?
|
210
|
+
result << field_result
|
211
|
+
result << field_id_fragment if nested_form?
|
212
|
+
result << "_#{field}" unless field.blank?
|
213
|
+
result << "_#{value}" unless value.blank?
|
214
|
+
result.flatten.join
|
215
|
+
end
|
227
216
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
217
|
+
##
|
218
|
+
# Returns the child object if it exists.
|
219
|
+
#
|
220
|
+
def nested_object_id
|
221
|
+
nested_form? && object.respond_to?(:new_record?) && !object.new_record? && object.id
|
222
|
+
end
|
232
223
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
224
|
+
##
|
225
|
+
# Returns true if this form object is nested in a parent form.
|
226
|
+
#
|
227
|
+
def nested_form?
|
228
|
+
@options[:nested] && @options[:nested][:parent] && @options[:nested][:parent].respond_to?(:object)
|
229
|
+
end
|
237
230
|
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
231
|
+
##
|
232
|
+
# Returns the value for the object's field.
|
233
|
+
#
|
234
|
+
def field_value(field)
|
235
|
+
@object && @object.respond_to?(field) ? @object.send(field) : ""
|
236
|
+
end
|
243
237
|
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
238
|
+
##
|
239
|
+
# Returns a new record of the type specified in the object
|
240
|
+
#
|
241
|
+
def build_object(object_or_symbol)
|
242
|
+
object_or_symbol.is_a?(Symbol) ? @template.instance_variable_get("@#{object_or_symbol}") || object_class(object_or_symbol).new : object_or_symbol
|
243
|
+
end
|
249
244
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
245
|
+
##
|
246
|
+
# Returns the object's models name.
|
247
|
+
#
|
248
|
+
def object_model_name(explicit_object=object)
|
249
|
+
explicit_object.is_a?(Symbol) ? explicit_object : explicit_object.class.to_s.underscore.gsub(/\//, '_')
|
250
|
+
end
|
255
251
|
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
252
|
+
##
|
253
|
+
# Returns the class type for the given object.
|
254
|
+
#
|
255
|
+
def object_class(explicit_object)
|
256
|
+
explicit_object.is_a?(Symbol) ? explicit_object.to_s.camelize.constantize : explicit_object.class
|
257
|
+
end
|
260
258
|
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
259
|
+
##
|
260
|
+
# Returns true if this form is the top-level (not nested).
|
261
|
+
#
|
262
|
+
def root_form?
|
263
|
+
!nested_form?
|
264
|
+
end
|
265
265
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
266
|
+
##
|
267
|
+
# Builds a group of labels for radios or checkboxes.
|
268
|
+
#
|
269
|
+
def labeled_group(field, options={})
|
270
|
+
options.reverse_merge!(:id => field_id(field), :selected => field_value(field))
|
271
|
+
options.merge!(:class => field_error(field, options))
|
272
|
+
variants = case
|
273
|
+
when options[:options]
|
274
|
+
options[:options].map{ |caption, value| [caption.to_s, (value||caption).to_s] }
|
275
|
+
when options[:collection]
|
276
|
+
fields = options[:fields] || [:name, :id]
|
277
|
+
options[:collection].map{ |variant| [variant.send(fields.first).to_s, variant.send(fields.last).to_s] }
|
278
|
+
else
|
279
|
+
[]
|
280
|
+
end
|
281
|
+
variants.inject(''.html_safe) do |html, variant|
|
282
|
+
variant[2] = "#{field_id(field)}_#{variant[1]}"
|
283
|
+
html << @template.label_tag("#{field_name(field)}[]", :for => variant[2], :caption => "#{yield(variant)} #{variant[0]}")
|
283
284
|
end
|
285
|
+
end
|
284
286
|
|
285
287
|
private
|
288
|
+
|
286
289
|
def field_result
|
287
290
|
result = []
|
288
291
|
result << object_model_name if root_form?
|
@@ -308,7 +311,7 @@ module Padrino
|
|
308
311
|
:attributes_name => "#{@options[:nested][:association]}_attributes"
|
309
312
|
}
|
310
313
|
end
|
311
|
-
end
|
312
|
-
end
|
313
|
-
end
|
314
|
-
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
@@ -2,9 +2,8 @@ require File.expand_path(File.dirname(__FILE__) + '/abstract_form_builder') unle
|
|
2
2
|
|
3
3
|
module Padrino
|
4
4
|
module Helpers
|
5
|
-
module FormBuilder
|
6
|
-
class StandardFormBuilder < AbstractFormBuilder
|
7
|
-
|
5
|
+
module FormBuilder
|
6
|
+
class StandardFormBuilder < AbstractFormBuilder
|
8
7
|
##
|
9
8
|
# StandardFormBuilder
|
10
9
|
#
|
@@ -26,18 +25,16 @@ module Padrino
|
|
26
25
|
EOF
|
27
26
|
end
|
28
27
|
|
29
|
-
# submit_block("Update")
|
30
28
|
def submit_block(caption, options={})
|
31
29
|
submit_html = self.submit(caption, options)
|
32
30
|
@template.content_tag(:p, submit_html)
|
33
31
|
end
|
34
32
|
|
35
|
-
# image_submit_block("submit.png")
|
36
33
|
def image_submit_block(source, options={})
|
37
34
|
submit_html = self.image_submit(source, options)
|
38
35
|
@template.content_tag(:p, submit_html)
|
39
36
|
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -7,16 +7,16 @@ module Padrino
|
|
7
7
|
#
|
8
8
|
module FormHelpers
|
9
9
|
##
|
10
|
-
# Constructs a form for object using given or default form_builder
|
10
|
+
# Constructs a form for object using given or default form_builder.
|
11
11
|
#
|
12
12
|
# @param [Object] object
|
13
13
|
# The object for which the form is being built.
|
14
|
-
# @param [String]
|
14
|
+
# @param [String] URL
|
15
15
|
# The url this form will submit to.
|
16
16
|
# @param [Hash] settings
|
17
17
|
# The settings associated with this form.
|
18
18
|
# Accepts a :namespace option that will be prepended to the id attributes of the form's elements.
|
19
|
-
# Also accepts
|
19
|
+
# Also accepts HTML options.
|
20
20
|
# @option settings [String] :builder ("StandardFormBuilder")
|
21
21
|
# The FormBuilder class to use such as StandardFormBuilder.
|
22
22
|
# @param [Proc] block
|
@@ -30,7 +30,6 @@ module Padrino
|
|
30
30
|
# form_for :user, '/register' do |f| ... end
|
31
31
|
# form_for @user, '/register', :id => 'register' do |f| ... end
|
32
32
|
#
|
33
|
-
# @api public
|
34
33
|
def form_for(object, url, settings={}, &block)
|
35
34
|
instance = builder_instance(object, settings)
|
36
35
|
html = capture_html(instance, &block)
|
@@ -40,13 +39,13 @@ module Padrino
|
|
40
39
|
end
|
41
40
|
|
42
41
|
##
|
43
|
-
# Constructs form fields for an object using given or default form_builder
|
44
|
-
# Used within an existing form to allow alternate objects within one form
|
42
|
+
# Constructs form fields for an object using given or default form_builder.
|
43
|
+
# Used within an existing form to allow alternate objects within one form.
|
45
44
|
#
|
46
45
|
# @param [Object] object
|
47
46
|
# The object for which the fields are being built.
|
48
47
|
# @param [Hash] settings
|
49
|
-
# The settings associated with these fields. Accepts
|
48
|
+
# The settings associated with these fields. Accepts HTML options.
|
50
49
|
# @param [Proc] block
|
51
50
|
# The content inside this set of fields.
|
52
51
|
#
|
@@ -56,7 +55,6 @@ module Padrino
|
|
56
55
|
# fields_for @user.assignment do |assignment| ... end
|
57
56
|
# fields_for :assignment do |assigment| ... end
|
58
57
|
#
|
59
|
-
# @api public
|
60
58
|
def fields_for(object, settings={}, &block)
|
61
59
|
instance = builder_instance(object, settings)
|
62
60
|
fields_html = capture_html(instance, &block)
|
@@ -65,21 +63,20 @@ module Padrino
|
|
65
63
|
end
|
66
64
|
|
67
65
|
##
|
68
|
-
# Constructs a form without object based on options
|
66
|
+
# Constructs a form without object based on options.
|
69
67
|
#
|
70
68
|
# @param [String] url
|
71
|
-
# The
|
69
|
+
# The URL this form will submit to.
|
72
70
|
# @param [Hash] options
|
73
71
|
# The html options associated with this form.
|
74
72
|
# @param [Proc] block
|
75
73
|
# The fields and content inside this form.
|
76
74
|
#
|
77
|
-
# @return [String] The
|
75
|
+
# @return [String] The HTML form with the specified options and input fields.
|
78
76
|
#
|
79
77
|
# @example
|
80
78
|
# form_tag '/register', :class => "registration_form" do ... end
|
81
79
|
#
|
82
|
-
# @api public
|
83
80
|
def form_tag(url, options={}, &block)
|
84
81
|
desired_method = options[:method].to_s
|
85
82
|
options.delete(:method) unless desired_method =~ /get|post/i
|
@@ -99,12 +96,12 @@ module Padrino
|
|
99
96
|
end
|
100
97
|
|
101
98
|
##
|
102
|
-
# Returns the hidden method field for 'put' and 'delete' forms
|
99
|
+
# Returns the hidden method field for 'put' and 'delete' forms.
|
103
100
|
# Only 'get' and 'post' are allowed within browsers;
|
104
101
|
# 'put' and 'delete' are just specified using hidden fields with form action still 'put'.
|
105
102
|
#
|
106
103
|
# @param [String] desired_method
|
107
|
-
# The method this hidden field represents (i.e put or delete)
|
104
|
+
# The method this hidden field represents (i.e put or delete).
|
108
105
|
#
|
109
106
|
# @return [String] The hidden field representing the +desired_method+ for the form.
|
110
107
|
#
|
@@ -112,14 +109,13 @@ module Padrino
|
|
112
109
|
# # Generate: <input name="_method" value="delete" />
|
113
110
|
# hidden_form_method_field('delete')
|
114
111
|
#
|
115
|
-
# @api semipublic
|
116
112
|
def hidden_form_method_field(desired_method)
|
117
113
|
return ActiveSupport::SafeBuffer.new if desired_method.blank? || desired_method.to_s =~ /get|post/i
|
118
114
|
hidden_field_tag(:_method, :value => desired_method)
|
119
115
|
end
|
120
116
|
|
121
117
|
##
|
122
|
-
# Constructs a field_set to group fields with given options
|
118
|
+
# Constructs a field_set to group fields with given options.
|
123
119
|
#
|
124
120
|
# @overload field_set_tag(legend=nil, options={}, &block)
|
125
121
|
# @param [String] legend The legend caption for the fieldset
|
@@ -135,7 +131,6 @@ module Padrino
|
|
135
131
|
# field_set_tag(:class => "office-set") { }
|
136
132
|
# field_set_tag("Office", :class => 'office-set') { }
|
137
133
|
#
|
138
|
-
# @api public
|
139
134
|
def field_set_tag(*args, &block)
|
140
135
|
options = args.extract_options!
|
141
136
|
legend_text = args[0].is_a?(String) ? args.first : nil
|
@@ -145,13 +140,13 @@ module Padrino
|
|
145
140
|
end
|
146
141
|
|
147
142
|
##
|
148
|
-
# Constructs list
|
143
|
+
# Constructs list HTML for the errors for a given symbol.
|
149
144
|
#
|
150
145
|
# @overload error_messages_for(*objects, options = {})
|
151
146
|
# @param [Array<Object>] object Splat of objects to display errors for.
|
152
147
|
# @param [Hash] options Error message display options.
|
153
148
|
# @option options [String] :header_tag ("h2")
|
154
|
-
# Used for the header of the error div
|
149
|
+
# Used for the header of the error div.
|
155
150
|
# @option options [String] :id ("field-errors")
|
156
151
|
# The id of the error div.
|
157
152
|
# @option options [String] :class ("field-errors")
|
@@ -163,7 +158,7 @@ module Padrino
|
|
163
158
|
# The object name to use in the header, or any text that you prefer.
|
164
159
|
# If +:object_name+ is not set, the name of the first object will be used.
|
165
160
|
# @option options [String] :header_message ("X errors prohibited this object from being saved")
|
166
|
-
# The message in the header of the error div.
|
161
|
+
# The message in the header of the error div. Pass +nil+ or an empty string
|
167
162
|
# to avoid the header message altogether.
|
168
163
|
# @option options [String] :message ("There were problems with the following fields:")
|
169
164
|
# The explanation message after the header message and before
|
@@ -175,7 +170,6 @@ module Padrino
|
|
175
170
|
# @example
|
176
171
|
# error_messages_for :user
|
177
172
|
#
|
178
|
-
# @api public
|
179
173
|
def error_messages_for(*objects)
|
180
174
|
options = objects.extract_options!.symbolize_keys
|
181
175
|
objects = objects.map { |object_name|
|
@@ -194,19 +188,19 @@ module Padrino
|
|
194
188
|
end
|
195
189
|
end
|
196
190
|
|
197
|
-
options[:object_name] ||= objects.first.class
|
191
|
+
options[:object_name] ||= objects.first.class.to_s.underscore.gsub(/\//, ' ')
|
198
192
|
|
199
193
|
I18n.with_options :locale => options[:locale], :scope => [:models, :errors, :template] do |locale|
|
200
194
|
header_message = if options.include?(:header_message)
|
201
195
|
options[:header_message]
|
202
196
|
else
|
203
|
-
object_name = options[:object_name]
|
197
|
+
object_name = options[:object_name]
|
204
198
|
object_name = I18n.t(:name, :default => object_name.humanize, :scope => [:models, object_name], :count => 1)
|
205
199
|
locale.t :header, :count => count, :model => object_name
|
206
200
|
end
|
207
201
|
message = options.include?(:message) ? options[:message] : locale.t(:body)
|
208
202
|
error_messages = objects.map { |object|
|
209
|
-
object_name = options[:object_name]
|
203
|
+
object_name = options[:object_name]
|
210
204
|
object.errors.map { |f, msg|
|
211
205
|
field = I18n.t(f, :default => f.to_s.humanize, :scope => [:models, object_name, :attributes])
|
212
206
|
content_tag(:li, "%s %s" % [field, msg])
|
@@ -226,7 +220,8 @@ module Padrino
|
|
226
220
|
end
|
227
221
|
|
228
222
|
##
|
229
|
-
# Returns a string containing the error message attached to the
|
223
|
+
# Returns a string containing the error message attached to the
|
224
|
+
# +method+ on the +object+ if one exists.
|
230
225
|
#
|
231
226
|
# @param [Object] object
|
232
227
|
# The object to display the error for.
|
@@ -262,7 +257,7 @@ module Padrino
|
|
262
257
|
I18n.t("ohm.errors.messages.#{error[0]}", :default => error[0].to_s)
|
263
258
|
else
|
264
259
|
# Array(error).first is necessary because some ORMs
|
265
|
-
# give us an array others directly a value
|
260
|
+
# give us an array others directly a value.
|
266
261
|
Array(error)[0]
|
267
262
|
end
|
268
263
|
|
@@ -277,7 +272,7 @@ module Padrino
|
|
277
272
|
end
|
278
273
|
|
279
274
|
##
|
280
|
-
# Constructs a label tag from the given options
|
275
|
+
# Constructs a label tag from the given options.
|
281
276
|
#
|
282
277
|
# @param [String] name
|
283
278
|
# The name of the field to label.
|
@@ -294,7 +289,6 @@ module Padrino
|
|
294
289
|
# label_tag :username, :class => 'long-label'
|
295
290
|
# label_tag :username, :class => 'long-label' do ... end
|
296
291
|
#
|
297
|
-
# @api public
|
298
292
|
def label_tag(name, options={}, &block)
|
299
293
|
options.reverse_merge!(:caption => "#{name.to_s.humanize}: ", :for => name)
|
300
294
|
caption_text = options.delete(:caption).html_safe
|
@@ -309,7 +303,7 @@ module Padrino
|
|
309
303
|
end
|
310
304
|
|
311
305
|
##
|
312
|
-
# Creates a text field input with the given name and options
|
306
|
+
# Creates a text field input with the given name and options.
|
313
307
|
#
|
314
308
|
# @macro [new] text_field
|
315
309
|
# @param [Symbol] name
|
@@ -338,22 +332,22 @@ module Padrino
|
|
338
332
|
# @option options [Boolean] :spellcheck
|
339
333
|
# Specifies whether or not the field should have it's spelling and grammar checked for errors.
|
340
334
|
# @option options [Boolean] :draggable
|
341
|
-
# Specifies whether or not the field is draggable. (true, false, :auto)
|
335
|
+
# Specifies whether or not the field is draggable. (true, false, :auto).
|
342
336
|
# @option options [String] :pattern
|
343
337
|
# Specifies the regular expression pattern that the field's value is checked against.
|
344
338
|
# @option options [Symbol] :autocomplete
|
345
|
-
# Specifies whether or not the field should have autocomplete enabled. (:on, :off)
|
339
|
+
# Specifies whether or not the field should have autocomplete enabled. (:on, :off).
|
346
340
|
# @option options [Boolean] :autofocus
|
347
341
|
# Specifies whether or not the field should automatically get focus when the page loads.
|
348
342
|
# @option options [Boolean] :required
|
349
|
-
# Specifies whether or not the field is required to be
|
343
|
+
# Specifies whether or not the field is required to be completed before the form is submitted.
|
350
344
|
# @option options [Boolean] :readonly
|
351
345
|
# Specifies whether or not the field is read only.
|
352
346
|
# @option options [Boolean] :disabled
|
353
347
|
# Specifies whether or not the field is disabled.
|
354
348
|
#
|
355
349
|
# @return [String]
|
356
|
-
# Generated HTML with specified +options
|
350
|
+
# Generated HTML with specified +options+.
|
357
351
|
#
|
358
352
|
# @example
|
359
353
|
# text_field_tag :first_name, :maxlength => 40, :required => true
|
@@ -365,13 +359,12 @@ module Padrino
|
|
365
359
|
# text_field_tag :username, :placeholder => 'Your Username'
|
366
360
|
# # => <input name="username" placeholder="Your Username" type="text" />
|
367
361
|
#
|
368
|
-
# @api public
|
369
362
|
def text_field_tag(name, options={})
|
370
363
|
input_tag(:text, options.reverse_merge!(:name => name))
|
371
364
|
end
|
372
365
|
|
373
366
|
##
|
374
|
-
# Creates a number field input with the given name and options
|
367
|
+
# Creates a number field input with the given name and options.
|
375
368
|
#
|
376
369
|
# @macro [new] number_field
|
377
370
|
# @param [Symbol] name
|
@@ -400,11 +393,11 @@ module Padrino
|
|
400
393
|
# @option options [Boolean] :spellcheck
|
401
394
|
# Specifies whether or not the field should have it's spelling and grammar checked for errors.
|
402
395
|
# @option options [Boolean] :draggable
|
403
|
-
# Specifies whether or not the field is draggable. (true, false, :auto)
|
396
|
+
# Specifies whether or not the field is draggable. (true, false, :auto).
|
404
397
|
# @option options [String] :pattern
|
405
398
|
# Specifies the regular expression pattern that the field's value is checked against.
|
406
399
|
# @option options [Symbol] :autocomplete
|
407
|
-
# Specifies whether or not the field should have autocomplete enabled. (:on, :off)
|
400
|
+
# Specifies whether or not the field should have autocomplete enabled. (:on, :off).
|
408
401
|
# @option options [Boolean] :autofocus
|
409
402
|
# Specifies whether or not the field should automatically get focus when the page loads.
|
410
403
|
# @option options [Boolean] :required
|
@@ -415,11 +408,11 @@ module Padrino
|
|
415
408
|
# Specifies whether or not the field is disabled.
|
416
409
|
#
|
417
410
|
# @return [String]
|
418
|
-
# Generated HTML with specified +options
|
411
|
+
# Generated HTML with specified +options+.
|
419
412
|
#
|
420
413
|
# @example
|
421
|
-
# number_field_tag :
|
422
|
-
# # => <input name="
|
414
|
+
# number_field_tag :quantity, :class => 'numeric'
|
415
|
+
# # => <input name="quantity" class="numeric" type="number" />
|
423
416
|
#
|
424
417
|
# number_field_tag :zip_code, :pattern => /[0-9]{5}/
|
425
418
|
# # => <input name="zip_code" pattern="[0-9]{5}" type="number" />
|
@@ -430,13 +423,12 @@ module Padrino
|
|
430
423
|
# number_field_tag :age, :min => 18, :max => 120, :step => 1
|
431
424
|
# # => <input name="age" min="18" max="120" step="1" type="number" />
|
432
425
|
#
|
433
|
-
# @api public
|
434
426
|
def number_field_tag(name, options={})
|
435
427
|
input_tag(:number, options.reverse_merge(:name => name))
|
436
428
|
end
|
437
429
|
|
438
430
|
##
|
439
|
-
# Creates a telephone field input with the given name and options
|
431
|
+
# Creates a telephone field input with the given name and options.
|
440
432
|
#
|
441
433
|
# @macro text_field
|
442
434
|
#
|
@@ -452,14 +444,13 @@ module Padrino
|
|
452
444
|
# # => <input name="work_phone" tabindex="2" type="tel" />
|
453
445
|
# # => <input name="home_phone" tabindex="3" type="tel" />
|
454
446
|
#
|
455
|
-
# @api public
|
456
447
|
def telephone_field_tag(name, options={})
|
457
448
|
input_tag(:tel, options.reverse_merge(:name => name))
|
458
449
|
end
|
459
450
|
alias_method :phone_field_tag, :telephone_field_tag
|
460
451
|
|
461
452
|
##
|
462
|
-
# Creates an email field input with the given name and options
|
453
|
+
# Creates an email field input with the given name and options.
|
463
454
|
#
|
464
455
|
# @macro text_field
|
465
456
|
#
|
@@ -470,13 +461,12 @@ module Padrino
|
|
470
461
|
# email_field_tag :email, :value => 'padrinorb@gmail.com', :readonly => true
|
471
462
|
# # => <input name="email" value="padrinorb@gmail.com" readonly type="email" />
|
472
463
|
#
|
473
|
-
# @api public
|
474
464
|
def email_field_tag(name, options={})
|
475
465
|
input_tag(:email, options.reverse_merge(:name => name))
|
476
466
|
end
|
477
467
|
|
478
468
|
##
|
479
|
-
# Creates a search field input with the given name and options
|
469
|
+
# Creates a search field input with the given name and options.
|
480
470
|
#
|
481
471
|
# @macro text_field
|
482
472
|
#
|
@@ -493,13 +483,12 @@ module Padrino
|
|
493
483
|
# search_field_tag :search, :autofocus => true
|
494
484
|
# # => <input name="search" autofocus type="search" />
|
495
485
|
#
|
496
|
-
# @api public
|
497
486
|
def search_field_tag(name, options={})
|
498
487
|
input_tag(:search, options.reverse_merge(:name => name))
|
499
488
|
end
|
500
489
|
|
501
490
|
##
|
502
|
-
# Creates a
|
491
|
+
# Creates a URL field input with the given name and options.
|
503
492
|
#
|
504
493
|
# @macro text_field
|
505
494
|
#
|
@@ -510,43 +499,34 @@ module Padrino
|
|
510
499
|
# url_field_tag :home_page, :class => 'string url'
|
511
500
|
# <input name="home_page" class="string url", type="url" />
|
512
501
|
#
|
513
|
-
# @api public
|
514
502
|
def url_field_tag(name, options={})
|
515
503
|
input_tag(:url, options.reverse_merge(:name => name))
|
516
504
|
end
|
517
505
|
|
518
506
|
##
|
519
|
-
# Constructs a hidden field input from the given options
|
520
|
-
#
|
521
|
-
# @macro text_field
|
507
|
+
# Constructs a hidden field input from the given options.
|
522
508
|
#
|
523
509
|
# @example
|
524
510
|
# hidden_field_tag :session_key, :value => "__secret__"
|
525
511
|
#
|
526
|
-
# @api public
|
527
512
|
def hidden_field_tag(name, options={})
|
528
513
|
options.reverse_merge!(:name => name)
|
529
514
|
input_tag(:hidden, options)
|
530
515
|
end
|
531
516
|
|
532
517
|
##
|
533
|
-
# Constructs a text area input from the given options
|
534
|
-
#
|
535
|
-
# @macro text_field
|
518
|
+
# Constructs a text area input from the given options.
|
536
519
|
#
|
537
520
|
# @example
|
538
521
|
# text_area_tag :username, :class => 'long', :value => "Demo?"
|
539
522
|
#
|
540
|
-
# @api public
|
541
523
|
def text_area_tag(name, options={})
|
542
524
|
options.reverse_merge!(:name => name, :rows => "", :cols => "")
|
543
525
|
content_tag(:textarea, options.delete(:value).to_s, options)
|
544
526
|
end
|
545
527
|
|
546
528
|
##
|
547
|
-
# Constructs a password field input from the given options
|
548
|
-
#
|
549
|
-
# @macro text_field
|
529
|
+
# Constructs a password field input from the given options.
|
550
530
|
#
|
551
531
|
# @example
|
552
532
|
# password_field_tag :password, :class => 'long'
|
@@ -558,37 +538,29 @@ module Padrino
|
|
558
538
|
end
|
559
539
|
|
560
540
|
##
|
561
|
-
# Constructs a check_box from the given options
|
562
|
-
#
|
563
|
-
# @macro text_field
|
541
|
+
# Constructs a check_box from the given options.
|
564
542
|
#
|
565
543
|
# @example
|
566
544
|
# check_box_tag :remember_me, :value => 'Yes'
|
567
545
|
#
|
568
|
-
# @api public
|
569
546
|
def check_box_tag(name, options={})
|
570
547
|
options.reverse_merge!(:name => name, :value => '1')
|
571
548
|
input_tag(:checkbox, options)
|
572
549
|
end
|
573
550
|
|
574
551
|
##
|
575
|
-
# Constructs a radio_button from the given options
|
576
|
-
#
|
577
|
-
# @macro text_field
|
552
|
+
# Constructs a radio_button from the given options.
|
578
553
|
#
|
579
554
|
# @example
|
580
555
|
# radio_button_tag :remember_me, :value => 'true'
|
581
556
|
#
|
582
|
-
# @api public
|
583
557
|
def radio_button_tag(name, options={})
|
584
558
|
options.reverse_merge!(:name => name)
|
585
559
|
input_tag(:radio, options)
|
586
560
|
end
|
587
561
|
|
588
562
|
##
|
589
|
-
# Constructs a file field input from the given options
|
590
|
-
#
|
591
|
-
# @macro text_field
|
563
|
+
# Constructs a file field input from the given options.
|
592
564
|
#
|
593
565
|
# @example
|
594
566
|
# file_field_tag :photo, :class => 'long'
|
@@ -601,7 +573,7 @@ module Padrino
|
|
601
573
|
end
|
602
574
|
|
603
575
|
##
|
604
|
-
# Constructs a select from the given options
|
576
|
+
# Constructs a select from the given options.
|
605
577
|
#
|
606
578
|
# @example
|
607
579
|
# options = [['caption', 'value'], ['Green', 'green1'], ['Blue', 'blue1'], ['Black', "black1"]]
|
@@ -638,9 +610,8 @@ module Padrino
|
|
638
610
|
# @option options [Boolean] :multiple (false)
|
639
611
|
# Allow multiple options to be selected at once.
|
640
612
|
#
|
641
|
-
# @return [String] The
|
613
|
+
# @return [String] The HTML input field based on the +options+ specified.
|
642
614
|
#
|
643
|
-
# @api public
|
644
615
|
def select_tag(name, options={})
|
645
616
|
options.reverse_merge!(:name => name)
|
646
617
|
collection, fields = options.delete(:collection), options.delete(:fields)
|
@@ -657,7 +628,7 @@ module Padrino
|
|
657
628
|
end
|
658
629
|
|
659
630
|
##
|
660
|
-
# Constructs a button input from the given options
|
631
|
+
# Constructs a button input from the given options.
|
661
632
|
#
|
662
633
|
# @param [String] caption
|
663
634
|
# The caption for the button.
|
@@ -669,14 +640,13 @@ module Padrino
|
|
669
640
|
# @example
|
670
641
|
# button_tag "Cancel", :class => 'clear'
|
671
642
|
#
|
672
|
-
# @api public
|
673
643
|
def button_tag(caption, options = {})
|
674
644
|
options.reverse_merge!(:value => caption)
|
675
645
|
input_tag(:button, options)
|
676
646
|
end
|
677
647
|
|
678
648
|
##
|
679
|
-
# Constructs a submit button from the given options
|
649
|
+
# Constructs a submit button from the given options.
|
680
650
|
#
|
681
651
|
# @param [String] caption (defaults to: +Submit+)
|
682
652
|
# The caption for the submit button.
|
@@ -689,7 +659,6 @@ module Padrino
|
|
689
659
|
# submit_tag "Create", :class => 'success'
|
690
660
|
# submit_tag :class => 'btn'
|
691
661
|
#
|
692
|
-
# @api public
|
693
662
|
def submit_tag(*args)
|
694
663
|
options = args[-1].is_a?(Hash) ? args.pop : {}
|
695
664
|
caption = args.length >= 1 ? args.shift : "Submit"
|
@@ -697,7 +666,8 @@ module Padrino
|
|
697
666
|
input_tag(:submit, options)
|
698
667
|
end
|
699
668
|
|
700
|
-
|
669
|
+
##
|
670
|
+
# Constructs a submit button from the given options.
|
701
671
|
#
|
702
672
|
# @param [String] source
|
703
673
|
# The source image path for the button.
|
@@ -709,12 +679,12 @@ module Padrino
|
|
709
679
|
# @example
|
710
680
|
# submit_tag "Create", :class => 'success'
|
711
681
|
#
|
712
|
-
# @api public
|
713
682
|
def image_submit_tag(source, options={})
|
714
683
|
options.reverse_merge!(:src => image_path(source))
|
715
684
|
input_tag(:image, options)
|
716
685
|
end
|
717
686
|
|
687
|
+
##
|
718
688
|
# Constructs a hidden field containing a CSRF token.
|
719
689
|
#
|
720
690
|
# @param [String] token
|
@@ -725,17 +695,28 @@ module Padrino
|
|
725
695
|
# @example
|
726
696
|
# csrf_token_field
|
727
697
|
#
|
728
|
-
# @api public
|
729
698
|
def csrf_token_field(token = nil)
|
730
|
-
|
731
|
-
|
732
|
-
end
|
699
|
+
hidden_field_tag csrf_param, :value => csrf_token
|
700
|
+
end
|
733
701
|
|
734
|
-
|
702
|
+
##
|
703
|
+
# Constructs meta tags `csrf-param` and `csrf-token` with the name of the
|
704
|
+
# cross-site request forgery protection parameter and token, respectively.
|
705
|
+
#
|
706
|
+
# @return [String] The meta tags with the CSRF token and the param your app expects it in.
|
707
|
+
#
|
708
|
+
# @example
|
709
|
+
# csrf_meta_tags
|
710
|
+
#
|
711
|
+
def csrf_meta_tags
|
712
|
+
if is_protected_from_csrf?
|
713
|
+
meta_tag(csrf_param, :name => 'csrf-param') <<
|
714
|
+
meta_tag(csrf_token, :name => 'csrf-token')
|
715
|
+
end
|
735
716
|
end
|
736
717
|
|
737
718
|
##
|
738
|
-
# Creates a form containing a single button that submits to the
|
719
|
+
# Creates a form containing a single button that submits to the URL.
|
739
720
|
#
|
740
721
|
# @overload button_to(name, url, options={})
|
741
722
|
# @param [String] caption The text caption.
|
@@ -752,6 +733,8 @@ module Padrino
|
|
752
733
|
# Instructs ujs handler to handle the submit as ajax.
|
753
734
|
# @option options [Symbol] :method
|
754
735
|
# Instructs ujs handler to use different http method (i.e :post, :delete).
|
736
|
+
# @option options [Hash] :submit_options
|
737
|
+
# Hash of any options, that you want to pass to submit_tag (i.e :id, :class)
|
755
738
|
#
|
756
739
|
# @return [String] Form and button html with specified +options+.
|
757
740
|
#
|
@@ -763,22 +746,22 @@ module Padrino
|
|
763
746
|
# # <input type="submit" value="Delete" />
|
764
747
|
# # </form>
|
765
748
|
#
|
766
|
-
# @api public
|
767
749
|
def button_to(*args, &block)
|
768
750
|
name, url = args[0], args[1]
|
769
751
|
options = args.extract_options!
|
770
752
|
options['data-remote'] = 'true' if options.delete(:remote)
|
753
|
+
submit_options = options.delete(:submit_options) || {}
|
771
754
|
if block_given?
|
772
755
|
form_tag(url, options, &block)
|
773
756
|
else
|
774
757
|
form_tag(url, options.merge!(:not_concat => true)) do
|
775
|
-
submit_tag(name)
|
758
|
+
submit_tag(name, submit_options)
|
776
759
|
end
|
777
760
|
end
|
778
761
|
end
|
779
762
|
|
780
763
|
##
|
781
|
-
# Constructs a range tag from the given options
|
764
|
+
# Constructs a range tag from the given options.
|
782
765
|
#
|
783
766
|
# @example
|
784
767
|
# range_field_tag('ranger_with_min_max', :min => 1, :max => 50)
|
@@ -789,14 +772,13 @@ module Padrino
|
|
789
772
|
# @param [Hash] options
|
790
773
|
# The html options for the range field.
|
791
774
|
# @option options [Integer] :min
|
792
|
-
# The min range of the range field
|
775
|
+
# The min range of the range field.
|
793
776
|
# @option options [Integer] :max
|
794
|
-
# The max range of the range field
|
777
|
+
# The max range of the range field.
|
795
778
|
# @option options [range] :range
|
796
|
-
# The range, in lieu of :min and :max. See examples for details
|
779
|
+
# The range, in lieu of :min and :max. See examples for details.
|
797
780
|
# @return [String] The html range field
|
798
781
|
#
|
799
|
-
# @api public
|
800
782
|
def range_field_tag(name, options = {})
|
801
783
|
options.reverse_merge!(:name => name)
|
802
784
|
if range = options.delete(:range)
|
@@ -807,116 +789,131 @@ module Padrino
|
|
807
789
|
|
808
790
|
protected
|
809
791
|
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
792
|
+
##
|
793
|
+
# Returns an array of option items for a select field based on the given collection.
|
794
|
+
#
|
795
|
+
# @param [Array] fields
|
796
|
+
# fields is an array containing the fields to display from each item in the collection.
|
797
|
+
#
|
798
|
+
def options_from_collection(collection, fields)
|
799
|
+
collection.map { |item| [ item.send(fields.first), item.send(fields.last) ] }
|
800
|
+
end
|
817
801
|
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
end
|
802
|
+
##
|
803
|
+
# Returns the options tags for a select based on the given option items.
|
804
|
+
#
|
805
|
+
def options_for_select(option_items, selected_value=nil)
|
806
|
+
return [] if option_items.blank?
|
807
|
+
option_items.map do |caption, value, disabled|
|
808
|
+
value ||= caption
|
809
|
+
disabled ||= false
|
810
|
+
content_tag(:option, caption, :value => value, :selected => option_is_selected?(value, caption, selected_value), :disabled => disabled)
|
828
811
|
end
|
812
|
+
end
|
829
813
|
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
# or:
|
839
|
-
# {:first => [[1,2,3], {:disabled => true}], :second => [4,5,6]}
|
840
|
-
attributes_hash = value.last.is_a?(Hash) ? value.pop : nil
|
841
|
-
disabled ||= attributes_hash && attributes_hash.include?(:disabled) ? attributes_hash[:disabled] : false
|
842
|
-
content_tag :optgroup, options_for_select(value, selected), :label => key, :disabled => disabled
|
843
|
-
end
|
844
|
-
elsif collection.is_a?(Array)
|
845
|
-
# Array format:
|
846
|
-
# ["Option Label", [:option1, :option2, ...]]
|
814
|
+
##
|
815
|
+
# Returns the optgroups with options tags for a select based on the given :grouped_options items.
|
816
|
+
#
|
817
|
+
def grouped_options_for_select(collection, selected=nil, prompt=false)
|
818
|
+
if collection.is_a?(Hash)
|
819
|
+
collection.map do |key, value|
|
820
|
+
# Hash format:
|
821
|
+
# {:first => [1,2,3], :second => [4,5,6]}
|
847
822
|
# or:
|
848
|
-
#
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
content_tag :optgroup, options_for_select(optgroup.last, selected), :label => optgroup.first, :disabled => disabled
|
853
|
-
end
|
823
|
+
# {:first => [[1,2,3], {:disabled => true}], :second => [4,5,6]}
|
824
|
+
attributes_hash = value.last.is_a?(Hash) ? value.pop : nil
|
825
|
+
disabled ||= attributes_hash && attributes_hash.include?(:disabled) ? attributes_hash[:disabled] : false
|
826
|
+
content_tag :optgroup, options_for_select(value, selected), :label => key, :disabled => disabled
|
854
827
|
end
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
when Array then content_tag(:option, prompt.first, :value => prompt.last)
|
865
|
-
else content_tag(:option, '', :value => '')
|
828
|
+
elsif collection.is_a?(Array)
|
829
|
+
# Array format:
|
830
|
+
# ["Option Label", [:option1, :option2, ...]]
|
831
|
+
# or:
|
832
|
+
# ["Option Label", [:option1, :option2, ...], true]
|
833
|
+
# the last item tells if it is disabled or not. This is keeps it backwards compatible.
|
834
|
+
collection.map do |optgroup|
|
835
|
+
disabled ||= optgroup.count > 2 ? optgroup.pop : false
|
836
|
+
content_tag :optgroup, options_for_select(optgroup.last, selected), :label => optgroup.first, :disabled => disabled
|
866
837
|
end
|
867
838
|
end
|
839
|
+
end
|
868
840
|
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
def configured_form_builder_class(explicit_builder=nil)
|
879
|
-
default_builder = self.respond_to?(:settings) && self.settings.default_builder
|
880
|
-
configured_builder = explicit_builder || default_builder || 'StandardFormBuilder'
|
881
|
-
configured_builder = "Padrino::Helpers::FormBuilder::#{configured_builder}".constantize if configured_builder.is_a?(String)
|
882
|
-
configured_builder
|
841
|
+
##
|
842
|
+
# Returns the blank option serving as a prompt if passed.
|
843
|
+
#
|
844
|
+
def blank_option(prompt)
|
845
|
+
return unless prompt
|
846
|
+
case prompt
|
847
|
+
when String then content_tag(:option, prompt, :value => '')
|
848
|
+
when Array then content_tag(:option, prompt.first, :value => prompt.last)
|
849
|
+
else content_tag(:option, '', :value => '')
|
883
850
|
end
|
851
|
+
end
|
884
852
|
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
# @api private
|
892
|
-
def builder_instance(object, settings={})
|
893
|
-
builder_class = configured_form_builder_class(settings.delete(:builder))
|
894
|
-
builder_class.new(self, object, settings)
|
895
|
-
end
|
853
|
+
##
|
854
|
+
# Returns whether the application is being protected from CSRF. Defaults to true.
|
855
|
+
#
|
856
|
+
def is_protected_from_csrf?
|
857
|
+
defined?(settings) ? settings.protect_from_csrf : true
|
858
|
+
end
|
896
859
|
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
860
|
+
##
|
861
|
+
# Returns the current CSRF token (based on the session). If it doesn't exist,
|
862
|
+
# it will create one and assign it to the session's `csrf` key.
|
863
|
+
#
|
864
|
+
def csrf_token
|
865
|
+
session[:csrf] ||= SecureRandom.hex(32) if defined?(session)
|
866
|
+
end
|
867
|
+
|
868
|
+
##
|
869
|
+
# Returns the param/field name in which your CSRF token should be expected by your
|
870
|
+
# controllers. Defaults to `authenticity_token`.
|
871
|
+
#
|
872
|
+
# Set this in your application with `set :csrf_param, :something_else`.
|
873
|
+
#
|
874
|
+
def csrf_param
|
875
|
+
defined?(settings) && settings.respond_to?(:csrf_param) ?
|
876
|
+
settings.csrf_param : :authenticity_token
|
877
|
+
end
|
878
|
+
|
879
|
+
private
|
880
|
+
##
|
881
|
+
# Returns the FormBuilder class to use based on all available setting sources
|
882
|
+
# If explicitly defined, returns that, otherwise returns defaults.
|
883
|
+
#
|
884
|
+
# @example
|
885
|
+
# configured_form_builder_class(nil) => StandardFormBuilder
|
886
|
+
#
|
887
|
+
def configured_form_builder_class(explicit_builder=nil)
|
888
|
+
default_builder = self.respond_to?(:settings) && self.settings.default_builder
|
889
|
+
configured_builder = explicit_builder || default_builder || 'StandardFormBuilder'
|
890
|
+
configured_builder = "Padrino::Helpers::FormBuilder::#{configured_builder}".constantize if configured_builder.is_a?(String)
|
891
|
+
configured_builder
|
892
|
+
end
|
893
|
+
|
894
|
+
##
|
895
|
+
# Returns an initialized builder instance for the given object and settings.
|
896
|
+
#
|
897
|
+
# @example
|
898
|
+
# builder_instance(@account, :nested => { ... }) => <FormBuilder>
|
899
|
+
#
|
900
|
+
def builder_instance(object, settings={})
|
901
|
+
builder_class = configured_form_builder_class(settings.delete(:builder))
|
902
|
+
builder_class.new(self, object, settings)
|
903
|
+
end
|
910
904
|
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
905
|
+
##
|
906
|
+
# Returns whether the option should be selected or not.
|
907
|
+
#
|
908
|
+
# @example
|
909
|
+
# option_is_selected?("red", "Red", ["red", "blue"]) => true
|
910
|
+
# option_is_selected?("red", "Red", ["green", "blue"]) => false
|
911
|
+
#
|
912
|
+
def option_is_selected?(value, caption, selected_values)
|
913
|
+
Array(selected_values).any? do |selected|
|
914
|
+
[value.to_s, caption.to_s].include?(selected.to_s)
|
919
915
|
end
|
920
|
-
|
921
|
-
|
922
|
-
end
|
916
|
+
end
|
917
|
+
end
|
918
|
+
end
|
919
|
+
end
|