padrino-helpers 0.12.0 → 0.12.1

Sign up to get free protection for your applications and to get access to all the features.
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