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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/lib/padrino-helpers.rb +4 -1
  3. data/lib/padrino-helpers/asset_tag_helpers.rb +17 -14
  4. data/lib/padrino-helpers/breadcrumb_helpers.rb +6 -6
  5. data/lib/padrino-helpers/form_builder/abstract_form_builder.rb +119 -163
  6. data/lib/padrino-helpers/form_builder/deprecated_builder_methods.rb +92 -0
  7. data/lib/padrino-helpers/form_helpers.rb +66 -347
  8. data/lib/padrino-helpers/form_helpers/errors.rb +138 -0
  9. data/lib/padrino-helpers/form_helpers/options.rb +97 -0
  10. data/lib/padrino-helpers/form_helpers/security.rb +70 -0
  11. data/lib/padrino-helpers/output_helpers.rb +1 -1
  12. data/lib/padrino-helpers/output_helpers/abstract_handler.rb +1 -1
  13. data/lib/padrino-helpers/render_helpers.rb +10 -9
  14. data/lib/padrino-helpers/tag_helpers.rb +2 -1
  15. data/lib/padrino/rendering.rb +378 -0
  16. data/lib/padrino/rendering/extensions/erubis.rb +74 -0
  17. data/lib/padrino/rendering/extensions/haml.rb +29 -0
  18. data/lib/padrino/rendering/extensions/slim.rb +21 -0
  19. data/padrino-helpers.gemspec +2 -1
  20. data/test/fixtures/apps/.components +6 -0
  21. data/test/fixtures/apps/.gitignore +7 -0
  22. data/test/fixtures/apps/render.rb +25 -0
  23. data/test/fixtures/apps/views/article/comment/show.slim +1 -0
  24. data/test/fixtures/apps/views/blog/post.erb +1 -0
  25. data/test/fixtures/apps/views/layouts/specific.erb +1 -0
  26. data/test/fixtures/apps/views/test/post.erb +1 -0
  27. data/test/fixtures/layouts/layout.erb +1 -0
  28. data/test/fixtures/markup_app/app.rb +0 -1
  29. data/test/fixtures/render_app/app.rb +25 -1
  30. data/test/fixtures/render_app/views/_unsafe.html.builder +2 -0
  31. data/test/fixtures/render_app/views/_unsafe_object.html.builder +2 -0
  32. data/test/fixtures/render_app/views/ruby_block_capture_erb.erb +1 -0
  33. data/test/fixtures/render_app/views/ruby_block_capture_haml.haml +1 -0
  34. data/test/fixtures/render_app/views/ruby_block_capture_slim.slim +1 -0
  35. data/test/helper.rb +65 -1
  36. data/test/test_asset_tag_helpers.rb +83 -79
  37. data/test/test_breadcrumb_helpers.rb +20 -20
  38. data/test/test_form_builder.rb +196 -196
  39. data/test/test_form_helpers.rb +163 -163
  40. data/test/test_format_helpers.rb +65 -65
  41. data/test/test_locale.rb +1 -1
  42. data/test/test_number_helpers.rb +10 -11
  43. data/test/test_output_helpers.rb +28 -28
  44. data/test/test_render_helpers.rb +89 -35
  45. data/test/test_rendering.rb +683 -0
  46. data/test/test_rendering_extensions.rb +14 -0
  47. data/test/test_tag_helpers.rb +23 -23
  48. 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 'securerandom'
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] settings
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, settings={}, &block)
37
- instance = builder_instance(object, settings)
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
- settings[:multipart] = instance.multipart unless settings.include?(:multipart)
40
- settings.delete(:namespace)
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] settings
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, settings={}, &block)
63
- instance = builder_instance(object, settings)
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
- concat_safe_content fields_html
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 = options.dup
86
- desired_method = options[:method].to_s
87
- options.delete(:method) unless desired_method =~ /get|post/i
88
- options.reverse_merge!(:method => 'post',
89
- :action => url,
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
- options['accept-charset'] ||= 'UTF-8'
93
- inner_form_html = hidden_form_method_field(desired_method)
94
- if options[:protect_from_csrf] == true && !(desired_method =~ /get/i)
95
- inner_form_html << csrf_token_field
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 << mark_safe(capture_html(&block))
98
- concat_content content_tag(:form, inner_form_html, options)
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[0].is_a?(String) ? args.first : nil
147
+ legend_text = args.first
140
148
  legend_html = legend_text.blank? ? ActiveSupport::SafeBuffer.new : content_tag(:legend, legend_text)
141
- field_set_content = legend_html + mark_safe(capture_html(&block))
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 = options.reverse_merge(:caption => "#{name.to_s.humanize}: ", :for => name)
280
- caption_text = ''.html_safe
281
- caption_text.concat options.delete(:caption)
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
- label_content = caption_text.concat capture_html(&block)
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, options.reverse_merge(:name => name))
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, options.reverse_merge(:name => name))
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, options.reverse_merge(:name => name))
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, options.reverse_merge(:name => name))
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, options.reverse_merge(:name => name))
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, options.reverse_merge(:name => name))
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, options.reverse_merge(:name => name))
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
- options = options.reverse_merge(:name => name, :rows => "", :cols => "")
511
- content_tag(:textarea, options.delete(:value).to_s, options)
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, options.reverse_merge(:name => name))
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, options.reverse_merge(:name => name, :value => '1'))
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, options.reverse_merge(:name => name))
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, options.reverse_merge(:name => name))
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 = options.reverse_merge(:name => name)
489
+ options = { :name => name }.merge(options)
599
490
  options[:name] = "#{options[:name]}[]" if options[:multiple]
600
- collection, fields = options.delete(:collection), options.delete(:fields)
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, options.reverse_merge(:value => caption))
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, options.reverse_merge(:value => caption))
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, options.reverse_merge(:src => image_path(source)))
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[0], args[1]
581
+ name, url = *args
725
582
  options['data-remote'] = 'true' if options.delete(:remote)
726
- submit_options = options.delete(:submit_options) || {}
727
- if block_given?
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 = options.reverse_merge(:name => name)
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, settings={})
867
- builder_class = configured_form_builder_class(settings.delete(:builder))
868
- builder_class.new(self, object, settings)
869
- end
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