padrino-helpers 0.12.0 → 0.12.1
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/lib/padrino-helpers.rb +4 -1
- data/lib/padrino-helpers/asset_tag_helpers.rb +17 -14
- data/lib/padrino-helpers/breadcrumb_helpers.rb +6 -6
- data/lib/padrino-helpers/form_builder/abstract_form_builder.rb +119 -163
- data/lib/padrino-helpers/form_builder/deprecated_builder_methods.rb +92 -0
- data/lib/padrino-helpers/form_helpers.rb +66 -347
- data/lib/padrino-helpers/form_helpers/errors.rb +138 -0
- data/lib/padrino-helpers/form_helpers/options.rb +97 -0
- data/lib/padrino-helpers/form_helpers/security.rb +70 -0
- data/lib/padrino-helpers/output_helpers.rb +1 -1
- data/lib/padrino-helpers/output_helpers/abstract_handler.rb +1 -1
- data/lib/padrino-helpers/render_helpers.rb +10 -9
- data/lib/padrino-helpers/tag_helpers.rb +2 -1
- data/lib/padrino/rendering.rb +378 -0
- data/lib/padrino/rendering/extensions/erubis.rb +74 -0
- data/lib/padrino/rendering/extensions/haml.rb +29 -0
- data/lib/padrino/rendering/extensions/slim.rb +21 -0
- data/padrino-helpers.gemspec +2 -1
- data/test/fixtures/apps/.components +6 -0
- data/test/fixtures/apps/.gitignore +7 -0
- data/test/fixtures/apps/render.rb +25 -0
- data/test/fixtures/apps/views/article/comment/show.slim +1 -0
- data/test/fixtures/apps/views/blog/post.erb +1 -0
- data/test/fixtures/apps/views/layouts/specific.erb +1 -0
- data/test/fixtures/apps/views/test/post.erb +1 -0
- data/test/fixtures/layouts/layout.erb +1 -0
- data/test/fixtures/markup_app/app.rb +0 -1
- data/test/fixtures/render_app/app.rb +25 -1
- data/test/fixtures/render_app/views/_unsafe.html.builder +2 -0
- data/test/fixtures/render_app/views/_unsafe_object.html.builder +2 -0
- data/test/fixtures/render_app/views/ruby_block_capture_erb.erb +1 -0
- data/test/fixtures/render_app/views/ruby_block_capture_haml.haml +1 -0
- data/test/fixtures/render_app/views/ruby_block_capture_slim.slim +1 -0
- data/test/helper.rb +65 -1
- data/test/test_asset_tag_helpers.rb +83 -79
- data/test/test_breadcrumb_helpers.rb +20 -20
- data/test/test_form_builder.rb +196 -196
- data/test/test_form_helpers.rb +163 -163
- data/test/test_format_helpers.rb +65 -65
- data/test/test_locale.rb +1 -1
- data/test/test_number_helpers.rb +10 -11
- data/test/test_output_helpers.rb +28 -28
- data/test/test_render_helpers.rb +89 -35
- data/test/test_rendering.rb +683 -0
- data/test/test_rendering_extensions.rb +14 -0
- data/test/test_tag_helpers.rb +23 -23
- metadata +57 -5
@@ -0,0 +1,92 @@
|
|
1
|
+
module Padrino
|
2
|
+
module Helpers
|
3
|
+
module FormBuilder
|
4
|
+
module DeprecatedBuilderMethods
|
5
|
+
##
|
6
|
+
# Returns true if the value matches the value in the field.
|
7
|
+
# field_has_value?(:gender, 'male')
|
8
|
+
def values_matches_field?(field, value)
|
9
|
+
logger.warn "##{__method__} is deprecated"
|
10
|
+
value.present? && (field_value(field).to_s == value.to_s || field_value(field).to_s == 'true')
|
11
|
+
end
|
12
|
+
|
13
|
+
##
|
14
|
+
# Add a :invalid css class to the field if it contain an error.
|
15
|
+
#
|
16
|
+
def field_error(field, options)
|
17
|
+
logger.warn "##{__method__} is deprecated"
|
18
|
+
error = @object.errors[field] rescue nil
|
19
|
+
error.blank? ? options[:class] : [options[:class], :invalid].flatten.compact.join(" ")
|
20
|
+
end
|
21
|
+
|
22
|
+
def nested_form?
|
23
|
+
logger.warn "##{__method__} is deprecated"
|
24
|
+
@options[:nested] && @options[:nested][:parent] && @options[:nested][:parent].respond_to?(:object)
|
25
|
+
is_nested && object.respond_to?(:new_record?) && !object.new_record? && object.id
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# Returns a new record of the type specified in the object
|
30
|
+
#
|
31
|
+
def build_object(object_or_symbol)
|
32
|
+
logger.warn "##{__method__} is deprecated"
|
33
|
+
object_or_symbol.is_a?(Symbol) ? @template.instance_variable_get("@#{object_or_symbol}") || object_class(object_or_symbol).new : object_or
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
# Returns the object's models name.
|
38
|
+
#
|
39
|
+
def object_model_name(explicit_object=object)
|
40
|
+
logger.warn "##{__method__} is deprecated"
|
41
|
+
return @options[:as] if root_form? && @options[:as].is_a?(Symbol)
|
42
|
+
explicit_object.is_a?(Symbol) ? explicit_object : explicit_object.class.to_s.underscore.gsub(/\//, '_')
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Returns the class type for the given object.
|
47
|
+
#
|
48
|
+
def object_class(explicit_object)
|
49
|
+
logger.warn "##{__method__} is deprecated"
|
50
|
+
explicit_object.is_a?(Symbol) ? explicit_object.to_s.camelize.constantize : explicit_object.class
|
51
|
+
@object.respond_to?(field) ? @object.send(field) : ''
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# Returns true if this form is the top-level (not nested).
|
56
|
+
# Returns a record from template instance or create a record of specified class.
|
57
|
+
#
|
58
|
+
def root_form?
|
59
|
+
logger.warn "##{__method__} is deprecated"
|
60
|
+
!nested_form?
|
61
|
+
end
|
62
|
+
|
63
|
+
def build_object(symbol)
|
64
|
+
logger.warn "##{__method__} is deprecated"
|
65
|
+
@template.instance_variable_get("@#{symbol}") || symbol.to_s.camelize.constantize.new
|
66
|
+
end
|
67
|
+
|
68
|
+
def field_result
|
69
|
+
logger.warn "##{__method__} is deprecated"
|
70
|
+
result = []
|
71
|
+
result << object_model_name if root_form?
|
72
|
+
result
|
73
|
+
end
|
74
|
+
|
75
|
+
def merge_default_options!(field, options)
|
76
|
+
logger.warn "##{__method__} is deprecated"
|
77
|
+
options.reverse_merge!(:value => field_value(field), :id => field_id(field))
|
78
|
+
options.merge!(:class => field_error(field, options))
|
79
|
+
end
|
80
|
+
|
81
|
+
def result_options
|
82
|
+
logger.warn "##{__method__} is deprecated"
|
83
|
+
{
|
84
|
+
:parent_form => @options[:nested][:parent],
|
85
|
+
:nested_index => @options[:nested][:index],
|
86
|
+
:attributes_name => "#{@options[:nested][:association]}_attributes"
|
87
|
+
}
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
require '
|
1
|
+
require 'padrino-helpers/form_helpers/errors'
|
2
|
+
require 'padrino-helpers/form_helpers/options'
|
3
|
+
require 'padrino-helpers/form_helpers/security'
|
2
4
|
|
3
5
|
module Padrino
|
4
6
|
module Helpers
|
@@ -6,6 +8,12 @@ module Padrino
|
|
6
8
|
# Helpers related to producing form related tags and inputs into templates.
|
7
9
|
#
|
8
10
|
module FormHelpers
|
11
|
+
def self.included(base)
|
12
|
+
base.send(:include, FormHelpers::Errors)
|
13
|
+
base.send(:include, FormHelpers::Options)
|
14
|
+
base.send(:include, FormHelpers::Security)
|
15
|
+
end
|
16
|
+
|
9
17
|
##
|
10
18
|
# Constructs a form for object using given or default form_builder.
|
11
19
|
#
|
@@ -13,7 +21,7 @@ module Padrino
|
|
13
21
|
# The object for which the form is being built.
|
14
22
|
# @param [String] URL
|
15
23
|
# The url this form will submit to.
|
16
|
-
# @param [Hash]
|
24
|
+
# @param [Hash] options
|
17
25
|
# The settings associated with this form.
|
18
26
|
# Accepts a :namespace option that will be prepended to the id attributes of the form's elements.
|
19
27
|
# Also accepts HTML options.
|
@@ -33,13 +41,12 @@ module Padrino
|
|
33
41
|
# form_for @user, '/register', :id => 'register' do |f| ... end
|
34
42
|
# form_for @user, '/register', :as => :customer do |f| ... end
|
35
43
|
#
|
36
|
-
def form_for(object, url,
|
37
|
-
instance = builder_instance(object,
|
44
|
+
def form_for(object, url, options={}, &block)
|
45
|
+
instance = builder_instance(object, options)
|
46
|
+
# this can erect instance.multipart flag if the block calls instance.file_field
|
38
47
|
html = capture_html(instance, &block)
|
39
|
-
|
40
|
-
|
41
|
-
settings.delete(:as)
|
42
|
-
form_tag(url, settings) { html }
|
48
|
+
options = { :multipart => instance.multipart }.update(options.except(:namespace, :as))
|
49
|
+
form_tag(url, options) { html }
|
43
50
|
end
|
44
51
|
|
45
52
|
##
|
@@ -48,7 +55,7 @@ module Padrino
|
|
48
55
|
#
|
49
56
|
# @param [Object] object
|
50
57
|
# The object for which the fields are being built.
|
51
|
-
# @param [Hash]
|
58
|
+
# @param [Hash] options
|
52
59
|
# The settings associated with these fields. Accepts HTML options.
|
53
60
|
# @param [Proc] block
|
54
61
|
# The content inside this set of fields.
|
@@ -59,11 +66,11 @@ module Padrino
|
|
59
66
|
# fields_for @user.assignment do |assignment| ... end
|
60
67
|
# fields_for :assignment do |assigment| ... end
|
61
68
|
#
|
62
|
-
def fields_for(object,
|
63
|
-
instance = builder_instance(object,
|
69
|
+
def fields_for(object, options={}, &block)
|
70
|
+
instance = builder_instance(object, options)
|
64
71
|
fields_html = capture_html(instance, &block)
|
65
72
|
fields_html << instance.hidden_field(:id) if instance.send(:nested_object_id)
|
66
|
-
|
73
|
+
concat_content fields_html
|
67
74
|
end
|
68
75
|
|
69
76
|
##
|
@@ -82,20 +89,21 @@ module Padrino
|
|
82
89
|
# form_tag '/register', :class => "registration_form" do ... end
|
83
90
|
#
|
84
91
|
def form_tag(url, options={}, &block)
|
85
|
-
options =
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
:protect_from_csrf => is_protected_from_csrf? )
|
92
|
+
options = {
|
93
|
+
:action => url,
|
94
|
+
:protect_from_csrf => is_protected_from_csrf?,
|
95
|
+
'accept-charset' => 'UTF-8'
|
96
|
+
}.update(options)
|
91
97
|
options[:enctype] = 'multipart/form-data' if options.delete(:multipart)
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
98
|
+
|
99
|
+
if (desired_method = options[:method]) =~ /get/i
|
100
|
+
options.delete(:protect_from_csrf)
|
101
|
+
else
|
102
|
+
options[:method] = 'post'
|
96
103
|
end
|
97
|
-
inner_form_html
|
98
|
-
|
104
|
+
inner_form_html = hidden_form_method_field(desired_method)
|
105
|
+
inner_form_html << csrf_token_field if options[:protect_from_csrf]
|
106
|
+
concat_content content_tag(:form, inner_form_html << capture_html(&block), options)
|
99
107
|
end
|
100
108
|
|
101
109
|
##
|
@@ -136,125 +144,9 @@ module Padrino
|
|
136
144
|
#
|
137
145
|
def field_set_tag(*args, &block)
|
138
146
|
options = args.extract_options!
|
139
|
-
legend_text = args
|
147
|
+
legend_text = args.first
|
140
148
|
legend_html = legend_text.blank? ? ActiveSupport::SafeBuffer.new : content_tag(:legend, legend_text)
|
141
|
-
|
142
|
-
concat_content content_tag(:fieldset, field_set_content, options)
|
143
|
-
end
|
144
|
-
|
145
|
-
##
|
146
|
-
# Constructs list HTML for the errors for a given symbol.
|
147
|
-
#
|
148
|
-
# @overload error_messages_for(*objects, options = {})
|
149
|
-
# @param [Array<Object>] object Splat of objects to display errors for.
|
150
|
-
# @param [Hash] options Error message display options.
|
151
|
-
# @option options [String] :header_tag ("h2")
|
152
|
-
# Used for the header of the error div.
|
153
|
-
# @option options [String] :id ("field-errors")
|
154
|
-
# The id of the error div.
|
155
|
-
# @option options [String] :class ("field-errors")
|
156
|
-
# The class of the error div.
|
157
|
-
# @option options [Array<Object>] :object
|
158
|
-
# The object (or array of objects) for which to display errors,
|
159
|
-
# if you need to escape the instance variable convention.
|
160
|
-
# @option options [String] :object_name
|
161
|
-
# The object name to use in the header, or any text that you prefer.
|
162
|
-
# If +:object_name+ is not set, the name of the first object will be used.
|
163
|
-
# @option options [String] :header_message ("X errors prohibited this object from being saved")
|
164
|
-
# The message in the header of the error div. Pass +nil+ or an empty string
|
165
|
-
# to avoid the header message altogether.
|
166
|
-
# @option options [String] :message ("There were problems with the following fields:")
|
167
|
-
# The explanation message after the header message and before
|
168
|
-
# the error list. Pass +nil+ or an empty string to avoid the explanation message
|
169
|
-
# altogether.
|
170
|
-
#
|
171
|
-
# @return [String] The html section with all errors for the specified +objects+
|
172
|
-
#
|
173
|
-
# @example
|
174
|
-
# error_messages_for :user
|
175
|
-
#
|
176
|
-
def error_messages_for(*objects)
|
177
|
-
options = objects.extract_options!.symbolize_keys
|
178
|
-
objects = objects.map{ |obj| resolve_object(obj) }.compact
|
179
|
-
count = objects.inject(0){ |sum, object| sum + object.errors.count }
|
180
|
-
return ''.html_safe if count.zero?
|
181
|
-
|
182
|
-
html_options = {}
|
183
|
-
[:id, :class, :style].each do |key|
|
184
|
-
if options.include?(key)
|
185
|
-
value = options[key]
|
186
|
-
html_options[key] = value unless value.blank?
|
187
|
-
else
|
188
|
-
html_options[key] = 'field-errors' unless key == :style
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
I18n.with_options :locale => options[:locale], :scope => [:models, :errors, :template] do |locale|
|
193
|
-
object_name = options[:object_name] || objects.first.class.to_s.underscore.gsub(/\//, ' ')
|
194
|
-
|
195
|
-
header_message = if options.include?(:header_message)
|
196
|
-
options[:header_message]
|
197
|
-
else
|
198
|
-
model_name = I18n.t(:name, :default => object_name.humanize, :scope => [:models, object_name], :count => 1)
|
199
|
-
locale.t :header, :count => count, :model => model_name
|
200
|
-
end
|
201
|
-
|
202
|
-
body_message = options[:message] || locale.t(:body)
|
203
|
-
|
204
|
-
error_messages = objects.inject(''.html_safe) do |text, object|
|
205
|
-
object.errors.each do |field, message|
|
206
|
-
field_name = I18n.t(field, :default => field.to_s.humanize, :scope => [:models, object_name, :attributes])
|
207
|
-
text << content_tag(:li, "#{field_name} #{message}")
|
208
|
-
end
|
209
|
-
text
|
210
|
-
end
|
211
|
-
|
212
|
-
contents = ActiveSupport::SafeBuffer.new
|
213
|
-
contents << content_tag(options[:header_tag] || :h2, header_message) unless header_message.blank?
|
214
|
-
contents << content_tag(:p, body_message) unless body_message.blank?
|
215
|
-
contents << content_tag(:ul, error_messages)
|
216
|
-
content_tag(:div, contents, html_options)
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
##
|
221
|
-
# Returns a string containing the error message attached to the
|
222
|
-
# +method+ on the +object+ if one exists.
|
223
|
-
#
|
224
|
-
# @param [Object] object
|
225
|
-
# The object to display the error for.
|
226
|
-
# @param [Symbol] field
|
227
|
-
# The field on the +object+ to display the error for.
|
228
|
-
# @param [Hash] options
|
229
|
-
# The options to control the error display.
|
230
|
-
# @option options [String] :tag ("span")
|
231
|
-
# The tag that encloses the error.
|
232
|
-
# @option options [String] :prepend ("")
|
233
|
-
# The text to prepend before the field error.
|
234
|
-
# @option options [String] :append ("")
|
235
|
-
# The text to append after the field error.
|
236
|
-
#
|
237
|
-
# @example
|
238
|
-
# # => <span class="error">can't be blank</div>
|
239
|
-
# error_message_on :post, :title
|
240
|
-
# error_message_on @post, :title
|
241
|
-
#
|
242
|
-
# # => <div class="custom" style="border:1px solid red">can't be blank</div>
|
243
|
-
# error_message_on :post, :title, :tag => :id, :class => :custom, :style => "border:1px solid red"
|
244
|
-
#
|
245
|
-
# # => <div class="error">This title can't be blank (or it won't work)</div>
|
246
|
-
# error_message_on :post, :title, :prepend => "This title", :append => "(or it won't work)"
|
247
|
-
#
|
248
|
-
# @return [String] The html display of an error for a particular +object+ and +field+.
|
249
|
-
#
|
250
|
-
# @api public
|
251
|
-
def error_message_on(object, field, options={})
|
252
|
-
error = Array(resolve_object(object).errors[field]).first
|
253
|
-
return ''.html_safe unless error
|
254
|
-
options = options.reverse_merge(:tag => :span, :class => :error)
|
255
|
-
tag = options.delete(:tag)
|
256
|
-
error = [options.delete(:prepend), error, options.delete(:append)].compact.join(" ")
|
257
|
-
content_tag(tag, error, options)
|
149
|
+
concat_content content_tag(:fieldset, legend_html << capture_html(&block), options)
|
258
150
|
end
|
259
151
|
|
260
152
|
##
|
@@ -276,14 +168,12 @@ module Padrino
|
|
276
168
|
# label_tag :username, :class => 'long-label' do ... end
|
277
169
|
#
|
278
170
|
def label_tag(name, options={}, &block)
|
279
|
-
options =
|
280
|
-
caption_text =
|
281
|
-
caption_text.
|
282
|
-
caption_text.safe_concat "<span class='required'>*</span> " if options.delete(:required)
|
171
|
+
options = { :caption => "#{name.to_s.humanize}: ", :for => name }.update(options)
|
172
|
+
caption_text = ActiveSupport::SafeBuffer.new << options.delete(:caption)
|
173
|
+
caption_text << "<span class='required'>*</span> ".html_safe if options.delete(:required)
|
283
174
|
|
284
175
|
if block_given?
|
285
|
-
|
286
|
-
concat_content(content_tag(:label, label_content, options))
|
176
|
+
concat_content content_tag(:label, caption_text << capture_html(&block), options)
|
287
177
|
else
|
288
178
|
content_tag(:label, caption_text, options)
|
289
179
|
end
|
@@ -347,7 +237,7 @@ module Padrino
|
|
347
237
|
# # => <input name="username" placeholder="Your Username" type="text" />
|
348
238
|
#
|
349
239
|
def text_field_tag(name, options={})
|
350
|
-
input_tag(:text,
|
240
|
+
input_tag(:text, { :name => name }.update(options))
|
351
241
|
end
|
352
242
|
|
353
243
|
##
|
@@ -411,7 +301,7 @@ module Padrino
|
|
411
301
|
# # => <input name="age" min="18" max="120" step="1" type="number" />
|
412
302
|
#
|
413
303
|
def number_field_tag(name, options={})
|
414
|
-
input_tag(:number,
|
304
|
+
input_tag(:number, { :name => name }.update(options))
|
415
305
|
end
|
416
306
|
|
417
307
|
##
|
@@ -432,7 +322,7 @@ module Padrino
|
|
432
322
|
# # => <input name="home_phone" tabindex="3" type="tel" />
|
433
323
|
#
|
434
324
|
def telephone_field_tag(name, options={})
|
435
|
-
input_tag(:tel,
|
325
|
+
input_tag(:tel, { :name => name }.update(options))
|
436
326
|
end
|
437
327
|
alias_method :phone_field_tag, :telephone_field_tag
|
438
328
|
|
@@ -449,7 +339,7 @@ module Padrino
|
|
449
339
|
# # => <input name="email" value="padrinorb@gmail.com" readonly type="email" />
|
450
340
|
#
|
451
341
|
def email_field_tag(name, options={})
|
452
|
-
input_tag(:email,
|
342
|
+
input_tag(:email, { :name => name }.update(options))
|
453
343
|
end
|
454
344
|
|
455
345
|
##
|
@@ -471,7 +361,7 @@ module Padrino
|
|
471
361
|
# # => <input name="search" autofocus type="search" />
|
472
362
|
#
|
473
363
|
def search_field_tag(name, options={})
|
474
|
-
input_tag(:search,
|
364
|
+
input_tag(:search, { :name => name }.update(options))
|
475
365
|
end
|
476
366
|
|
477
367
|
##
|
@@ -487,7 +377,7 @@ module Padrino
|
|
487
377
|
# <input name="home_page" class="string url", type="url" />
|
488
378
|
#
|
489
379
|
def url_field_tag(name, options={})
|
490
|
-
input_tag(:url,
|
380
|
+
input_tag(:url, { :name => name }.update(options))
|
491
381
|
end
|
492
382
|
|
493
383
|
##
|
@@ -497,7 +387,7 @@ module Padrino
|
|
497
387
|
# hidden_field_tag :session_key, :value => "__secret__"
|
498
388
|
#
|
499
389
|
def hidden_field_tag(name, options={})
|
500
|
-
input_tag(:hidden,
|
390
|
+
input_tag(:hidden, { :name => name }.update(options))
|
501
391
|
end
|
502
392
|
|
503
393
|
##
|
@@ -507,8 +397,9 @@ module Padrino
|
|
507
397
|
# text_area_tag :username, :class => 'long', :value => "Demo?"
|
508
398
|
#
|
509
399
|
def text_area_tag(name, options={})
|
510
|
-
|
511
|
-
|
400
|
+
inner_html = options.delete(:value).to_s
|
401
|
+
options = { :name => name, :rows => "", :cols => "" }.update(options)
|
402
|
+
content_tag(:textarea, inner_html, options)
|
512
403
|
end
|
513
404
|
|
514
405
|
##
|
@@ -519,7 +410,7 @@ module Padrino
|
|
519
410
|
#
|
520
411
|
# @api public
|
521
412
|
def password_field_tag(name, options={})
|
522
|
-
input_tag(:password,
|
413
|
+
input_tag(:password, { :name => name }.update(options))
|
523
414
|
end
|
524
415
|
|
525
416
|
##
|
@@ -529,7 +420,7 @@ module Padrino
|
|
529
420
|
# check_box_tag :remember_me, :value => 'Yes'
|
530
421
|
#
|
531
422
|
def check_box_tag(name, options={})
|
532
|
-
input_tag(:checkbox,
|
423
|
+
input_tag(:checkbox, { :name => name, :value => '1' }.update(options))
|
533
424
|
end
|
534
425
|
|
535
426
|
##
|
@@ -539,7 +430,7 @@ module Padrino
|
|
539
430
|
# radio_button_tag :remember_me, :value => 'true'
|
540
431
|
#
|
541
432
|
def radio_button_tag(name, options={})
|
542
|
-
input_tag(:radio,
|
433
|
+
input_tag(:radio, { :name => name }.update(options))
|
543
434
|
end
|
544
435
|
|
545
436
|
##
|
@@ -551,7 +442,7 @@ module Padrino
|
|
551
442
|
# @api public
|
552
443
|
def file_field_tag(name, options={})
|
553
444
|
name = "#{name}[]" if options[:multiple]
|
554
|
-
input_tag(:file,
|
445
|
+
input_tag(:file, { :name => name }.update(options))
|
555
446
|
end
|
556
447
|
|
557
448
|
##
|
@@ -595,12 +486,9 @@ module Padrino
|
|
595
486
|
# @return [String] The HTML input field based on the +options+ specified.
|
596
487
|
#
|
597
488
|
def select_tag(name, options={})
|
598
|
-
options =
|
489
|
+
options = { :name => name }.merge(options)
|
599
490
|
options[:name] = "#{options[:name]}[]" if options[:multiple]
|
600
|
-
|
601
|
-
options[:options] = options_from_collection(collection, fields) if collection
|
602
|
-
options_tags = extract_option_tags!(options)
|
603
|
-
content_tag(:select, options_tags, options)
|
491
|
+
content_tag(:select, extract_option_tags!(options), options)
|
604
492
|
end
|
605
493
|
|
606
494
|
##
|
@@ -617,7 +505,7 @@ module Padrino
|
|
617
505
|
# button_tag "Cancel", :class => 'clear'
|
618
506
|
#
|
619
507
|
def button_tag(caption, options = {})
|
620
|
-
input_tag(:button,
|
508
|
+
input_tag(:button, { :value => caption }.update(options))
|
621
509
|
end
|
622
510
|
|
623
511
|
##
|
@@ -637,7 +525,7 @@ module Padrino
|
|
637
525
|
def submit_tag(*args)
|
638
526
|
options = args.extract_options!
|
639
527
|
caption = args.length >= 1 ? args.first : "Submit"
|
640
|
-
input_tag(:submit,
|
528
|
+
input_tag(:submit, { :value => caption }.merge(options))
|
641
529
|
end
|
642
530
|
|
643
531
|
##
|
@@ -654,38 +542,7 @@ module Padrino
|
|
654
542
|
# image_submit_tag 'form/submit.png'
|
655
543
|
#
|
656
544
|
def image_submit_tag(source, options={})
|
657
|
-
input_tag(:image,
|
658
|
-
end
|
659
|
-
|
660
|
-
##
|
661
|
-
# Constructs a hidden field containing a CSRF token.
|
662
|
-
#
|
663
|
-
# @param [String] token
|
664
|
-
# The token to use. Will be read from the session by default.
|
665
|
-
#
|
666
|
-
# @return [String] The hidden field with CSRF token as value.
|
667
|
-
#
|
668
|
-
# @example
|
669
|
-
# csrf_token_field
|
670
|
-
#
|
671
|
-
def csrf_token_field(token = nil)
|
672
|
-
hidden_field_tag csrf_param, :value => csrf_token
|
673
|
-
end
|
674
|
-
|
675
|
-
##
|
676
|
-
# Constructs meta tags `csrf-param` and `csrf-token` with the name of the
|
677
|
-
# cross-site request forgery protection parameter and token, respectively.
|
678
|
-
#
|
679
|
-
# @return [String] The meta tags with the CSRF token and the param your app expects it in.
|
680
|
-
#
|
681
|
-
# @example
|
682
|
-
# csrf_meta_tags
|
683
|
-
#
|
684
|
-
def csrf_meta_tags
|
685
|
-
if is_protected_from_csrf?
|
686
|
-
meta_tag(csrf_param, :name => 'csrf-param') <<
|
687
|
-
meta_tag(csrf_token, :name => 'csrf-token')
|
688
|
-
end
|
545
|
+
input_tag(:image, { :src => image_path(source) }.update(options))
|
689
546
|
end
|
690
547
|
|
691
548
|
##
|
@@ -721,16 +578,10 @@ module Padrino
|
|
721
578
|
#
|
722
579
|
def button_to(*args, &block)
|
723
580
|
options = args.extract_options!.dup
|
724
|
-
name, url = args
|
581
|
+
name, url = *args
|
725
582
|
options['data-remote'] = 'true' if options.delete(:remote)
|
726
|
-
|
727
|
-
|
728
|
-
form_tag(url || name, options, &block)
|
729
|
-
else
|
730
|
-
form_tag(url, options) do
|
731
|
-
submit_tag(name, submit_options)
|
732
|
-
end
|
733
|
-
end
|
583
|
+
block ||= proc { submit_tag(name, options.delete(:submit_options) || {}) }
|
584
|
+
form_tag(url || name, options, &block)
|
734
585
|
end
|
735
586
|
|
736
587
|
##
|
@@ -753,158 +604,26 @@ module Padrino
|
|
753
604
|
# @return [String] The html range field
|
754
605
|
#
|
755
606
|
def range_field_tag(name, options = {})
|
756
|
-
options =
|
607
|
+
options = { :name => name }.update(options)
|
757
608
|
if range = options.delete(:range)
|
758
609
|
options[:min], options[:max] = range.min, range.max
|
759
610
|
end
|
760
611
|
input_tag(:range, options)
|
761
612
|
end
|
762
613
|
|
763
|
-
protected
|
764
|
-
|
765
|
-
##
|
766
|
-
# Returns an array of option items for a select field based on the given collection.
|
767
|
-
#
|
768
|
-
# @param [Array] fields
|
769
|
-
# fields is an array containing the fields to display from each item in the collection.
|
770
|
-
#
|
771
|
-
def options_from_collection(collection, fields)
|
772
|
-
collection.map { |item| [ item.send(fields.first), item.send(fields.last) ] }
|
773
|
-
end
|
774
|
-
|
775
|
-
##
|
776
|
-
# Returns the options tags for a select based on the given option items.
|
777
|
-
#
|
778
|
-
def options_for_select(option_items, state = {})
|
779
|
-
return [] if option_items.blank?
|
780
|
-
option_items.map do |caption, value, attributes|
|
781
|
-
html_attributes = { :value => value || caption }.merge(attributes||{})
|
782
|
-
html_attributes[:selected] ||= option_is_selected?(value, caption, state[:selected])
|
783
|
-
html_attributes[:disabled] ||= option_is_selected?(value, caption, state[:disabled])
|
784
|
-
content_tag(:option, caption, html_attributes)
|
785
|
-
end
|
786
|
-
end
|
787
|
-
|
788
|
-
##
|
789
|
-
# Returns the optgroups with options tags for a select based on the given :grouped_options items.
|
790
|
-
#
|
791
|
-
def grouped_options_for_select(collection, state = {})
|
792
|
-
collection.map do |item|
|
793
|
-
caption = item.shift
|
794
|
-
attributes = item.last.kind_of?(Hash) ? item.pop : {}
|
795
|
-
value = item.flatten(1)
|
796
|
-
attributes = value.pop if value.last.kind_of?(Hash)
|
797
|
-
html_attributes = { :label => caption }.merge(attributes||{})
|
798
|
-
content_tag(:optgroup, options_for_select(value, state), html_attributes)
|
799
|
-
end
|
800
|
-
end
|
801
|
-
|
802
|
-
##
|
803
|
-
# Returns the blank option serving as a prompt if passed.
|
804
|
-
#
|
805
|
-
def blank_option(prompt)
|
806
|
-
case prompt
|
807
|
-
when nil, false
|
808
|
-
nil
|
809
|
-
when String
|
810
|
-
content_tag(:option, prompt, :value => '')
|
811
|
-
when Array
|
812
|
-
content_tag(:option, prompt.first, :value => prompt.last)
|
813
|
-
else
|
814
|
-
content_tag(:option, '', :value => '')
|
815
|
-
end
|
816
|
-
end
|
817
|
-
|
818
|
-
##
|
819
|
-
# Returns whether the application is being protected from CSRF. Defaults to true.
|
820
|
-
#
|
821
|
-
def is_protected_from_csrf?
|
822
|
-
defined?(settings) ? settings.protect_from_csrf : true
|
823
|
-
end
|
824
|
-
|
825
|
-
##
|
826
|
-
# Returns the current CSRF token (based on the session). If it doesn't exist,
|
827
|
-
# it will create one and assign it to the session's `csrf` key.
|
828
|
-
#
|
829
|
-
def csrf_token
|
830
|
-
session[:csrf] ||= SecureRandom.hex(32) if defined?(session)
|
831
|
-
end
|
832
|
-
|
833
|
-
##
|
834
|
-
# Returns the param/field name in which your CSRF token should be expected by your
|
835
|
-
# controllers. Defaults to `authenticity_token`.
|
836
|
-
#
|
837
|
-
# Set this in your application with `set :csrf_param, :something_else`.
|
838
|
-
#
|
839
|
-
def csrf_param
|
840
|
-
defined?(settings) && settings.respond_to?(:csrf_param) ?
|
841
|
-
settings.csrf_param : :authenticity_token
|
842
|
-
end
|
843
|
-
|
844
614
|
private
|
845
615
|
|
846
|
-
##
|
847
|
-
# Returns the FormBuilder class to use based on all available setting sources
|
848
|
-
# If explicitly defined, returns that, otherwise returns defaults.
|
849
|
-
#
|
850
|
-
# @example
|
851
|
-
# configured_form_builder_class(nil) => StandardFormBuilder
|
852
|
-
#
|
853
|
-
def configured_form_builder_class(explicit_builder=nil)
|
854
|
-
default_builder = self.respond_to?(:settings) && self.settings.default_builder
|
855
|
-
configured_builder = explicit_builder || default_builder || 'StandardFormBuilder'
|
856
|
-
configured_builder = "Padrino::Helpers::FormBuilder::#{configured_builder}".constantize if configured_builder.is_a?(String)
|
857
|
-
configured_builder
|
858
|
-
end
|
859
|
-
|
860
616
|
##
|
861
617
|
# Returns an initialized builder instance for the given object and settings.
|
862
618
|
#
|
863
619
|
# @example
|
864
620
|
# builder_instance(@account, :nested => { ... }) => <FormBuilder>
|
865
621
|
#
|
866
|
-
def builder_instance(object,
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
##
|
872
|
-
# Returns whether the option should be selected or not.
|
873
|
-
#
|
874
|
-
# @example
|
875
|
-
# option_is_selected?("red", "Red", ["red", "blue"]) => true
|
876
|
-
# option_is_selected?("red", "Red", ["green", "blue"]) => false
|
877
|
-
#
|
878
|
-
def option_is_selected?(value, caption, selected_values)
|
879
|
-
Array(selected_values).any? do |selected|
|
880
|
-
[value.to_s, caption.to_s].include?(selected.to_s)
|
881
|
-
end
|
882
|
-
end
|
883
|
-
|
884
|
-
def extract_option_state!(options)
|
885
|
-
{
|
886
|
-
:selected => Array(options.delete(:selected))|Array(options.delete(:selected_options)),
|
887
|
-
:disabled => Array(options.delete(:disabled_options))
|
888
|
-
}
|
889
|
-
end
|
890
|
-
|
891
|
-
def extract_option_tags!(options)
|
892
|
-
state = extract_option_state!(options)
|
893
|
-
option_tags = case
|
894
|
-
when options[:options]
|
895
|
-
options_for_select(options.delete(:options), state)
|
896
|
-
when options[:grouped_options]
|
897
|
-
grouped_options_for_select(options.delete(:grouped_options), state)
|
898
|
-
else
|
899
|
-
[]
|
900
|
-
end
|
901
|
-
prompt = options.delete(:include_blank)
|
902
|
-
option_tags.unshift(blank_option(prompt)) if prompt
|
903
|
-
option_tags
|
904
|
-
end
|
905
|
-
|
906
|
-
def resolve_object(object)
|
907
|
-
object.is_a?(Symbol) ? instance_variable_get("@#{object}") : object
|
622
|
+
def builder_instance(object, options={})
|
623
|
+
default_builder = respond_to?(:settings) && settings.default_builder || 'StandardFormBuilder'
|
624
|
+
builder_class = options.delete(:builder) || default_builder
|
625
|
+
builder_class = "Padrino::Helpers::FormBuilder::#{builder_class}".constantize if builder_class.is_a?(String)
|
626
|
+
builder_class.new(self, object, options)
|
908
627
|
end
|
909
628
|
end
|
910
629
|
end
|