padrino-helpers 0.11.4 → 0.12.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/README.rdoc +6 -6
  3. data/lib/padrino-helpers/asset_tag_helpers.rb +26 -33
  4. data/lib/padrino-helpers/form_builder/abstract_form_builder.rb +16 -17
  5. data/lib/padrino-helpers/form_helpers.rb +121 -129
  6. data/lib/padrino-helpers/format_helpers.rb +1 -1
  7. data/lib/padrino-helpers/output_helpers/abstract_handler.rb +25 -60
  8. data/lib/padrino-helpers/output_helpers/erb_handler.rb +7 -58
  9. data/lib/padrino-helpers/output_helpers/haml_handler.rb +5 -43
  10. data/lib/padrino-helpers/output_helpers/slim_handler.rb +5 -65
  11. data/lib/padrino-helpers/output_helpers.rb +26 -13
  12. data/lib/padrino-helpers/render_helpers.rb +21 -18
  13. data/lib/padrino-helpers.rb +1 -0
  14. data/padrino-helpers.gemspec +2 -1
  15. data/test/fixtures/markup_app/app.rb +14 -10
  16. data/test/fixtures/markup_app/views/button_to.haml +2 -2
  17. data/test/fixtures/markup_app/views/capture_concat.haml +3 -3
  18. data/test/fixtures/markup_app/views/capture_concat.slim +3 -3
  19. data/test/fixtures/markup_app/views/content_for.erb +10 -1
  20. data/test/fixtures/markup_app/views/content_for.haml +7 -0
  21. data/test/fixtures/markup_app/views/content_for.slim +8 -1
  22. data/test/fixtures/markup_app/views/content_tag.erb +2 -0
  23. data/test/fixtures/markup_app/views/content_tag.haml +4 -2
  24. data/test/fixtures/markup_app/views/content_tag.slim +3 -1
  25. data/test/fixtures/markup_app/views/fields_for.haml +4 -4
  26. data/test/fixtures/markup_app/views/form_for.haml +3 -3
  27. data/test/fixtures/markup_app/views/form_tag.haml +6 -6
  28. data/test/fixtures/markup_app/views/link_to.haml +1 -1
  29. data/test/fixtures/markup_app/views/simple_partial.slim +1 -1
  30. data/test/fixtures/render_app/app.rb +16 -4
  31. data/test/fixtures/render_app/views/_deep.erb +3 -0
  32. data/test/fixtures/render_app/views/_deep.haml +2 -0
  33. data/test/fixtures/render_app/views/_deep.slim +2 -0
  34. data/test/fixtures/render_app/views/_partial_block_erb.erb +10 -0
  35. data/test/fixtures/render_app/views/_partial_block_haml.haml +7 -0
  36. data/test/fixtures/render_app/views/_partial_block_slim.slim +7 -0
  37. data/test/fixtures/render_app/views/double_capture_erb.erb +2 -2
  38. data/test/fixtures/render_app/views/double_capture_haml.haml +1 -1
  39. data/test/fixtures/render_app/views/double_capture_slim.slim +1 -1
  40. data/test/fixtures/render_app/views/render_block_erb.erb +5 -0
  41. data/test/fixtures/render_app/views/render_block_haml.haml +4 -0
  42. data/test/fixtures/render_app/views/render_block_slim.slim +4 -0
  43. data/test/fixtures/render_app/views/wrong_capture_erb.erb +3 -0
  44. data/test/fixtures/render_app/views/wrong_capture_haml.haml +2 -0
  45. data/test/fixtures/render_app/views/wrong_capture_slim.slim +2 -0
  46. data/test/test_asset_tag_helpers.rb +34 -0
  47. data/test/test_form_builder.rb +10 -0
  48. data/test/test_form_helpers.rb +18 -18
  49. data/test/test_format_helpers.rb +10 -0
  50. data/test/test_output_helpers.rb +25 -22
  51. data/test/test_render_helpers.rb +67 -0
  52. data/test/test_tag_helpers.rb +9 -0
  53. metadata +38 -7
@@ -19,6 +19,8 @@ module Padrino
19
19
  # Also accepts HTML options.
20
20
  # @option settings [String] :builder ("StandardFormBuilder")
21
21
  # The FormBuilder class to use such as StandardFormBuilder.
22
+ # @option settings [Symbol] :as
23
+ # Sets custom form object name.
22
24
  # @param [Proc] block
23
25
  # The fields and content inside this form.
24
26
  #
@@ -29,12 +31,14 @@ module Padrino
29
31
  # @example
30
32
  # form_for :user, '/register' do |f| ... end
31
33
  # form_for @user, '/register', :id => 'register' do |f| ... end
34
+ # form_for @user, '/register', :as => :customer do |f| ... end
32
35
  #
33
36
  def form_for(object, url, settings={}, &block)
34
37
  instance = builder_instance(object, settings)
35
38
  html = capture_html(instance, &block)
36
39
  settings[:multipart] = instance.multipart unless settings.include?(:multipart)
37
40
  settings.delete(:namespace)
41
+ settings.delete(:as)
38
42
  form_tag(url, settings) { html }
39
43
  end
40
44
 
@@ -78,6 +82,7 @@ module Padrino
78
82
  # form_tag '/register', :class => "registration_form" do ... end
79
83
  #
80
84
  def form_tag(url, options={}, &block)
85
+ options = options.dup
81
86
  desired_method = options[:method].to_s
82
87
  options.delete(:method) unless desired_method =~ /get|post/i
83
88
  options.reverse_merge!(:method => 'post',
@@ -90,9 +95,7 @@ module Padrino
90
95
  inner_form_html << csrf_token_field
91
96
  end
92
97
  inner_form_html << mark_safe(capture_html(&block))
93
- not_concat = options.delete(:not_concat)
94
- form_html = content_tag(:form, inner_form_html, options)
95
- not_concat ? form_html : concat_content(form_html)
98
+ concat_content content_tag(:form, inner_form_html, options)
96
99
  end
97
100
 
98
101
  ##
@@ -172,50 +175,45 @@ module Padrino
172
175
  #
173
176
  def error_messages_for(*objects)
174
177
  options = objects.extract_options!.symbolize_keys
175
- objects = objects.map { |object_name|
176
- object_name.is_a?(Symbol) ? instance_variable_get("@#{object_name}") : object_name
177
- }.compact
178
- count = objects.inject(0) { |sum, object| sum + object.errors.count }
179
-
180
- unless count.zero?
181
- html = {}
182
- [:id, :class, :style].each do |key|
183
- if options.include?(key)
184
- value = options[key]
185
- html[key] = value unless value.blank?
186
- else
187
- html[key] = 'field-errors' unless key == :style
188
- end
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
189
200
  end
190
201
 
191
- options[:object_name] ||= objects.first.class.to_s.underscore.gsub(/\//, ' ')
202
+ body_message = options[:message] || locale.t(:body)
192
203
 
193
- I18n.with_options :locale => options[:locale], :scope => [:models, :errors, :template] do |locale|
194
- header_message = if options.include?(:header_message)
195
- options[:header_message]
196
- else
197
- object_name = options[:object_name]
198
- object_name = I18n.t(:name, :default => object_name.humanize, :scope => [:models, object_name], :count => 1)
199
- locale.t :header, :count => count, :model => object_name
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}")
200
208
  end
201
- message = options.include?(:message) ? options[:message] : locale.t(:body)
202
- error_messages = objects.map { |object|
203
- object_name = options[:object_name]
204
- object.errors.map { |f, msg|
205
- field = I18n.t(f, :default => f.to_s.humanize, :scope => [:models, object_name, :attributes])
206
- content_tag(:li, "%s %s" % [field, msg])
207
- }
208
- }.join
209
-
210
- contents = ActiveSupport::SafeBuffer.new
211
- contents << content_tag(options[:header_tag] || :h2, header_message) unless header_message.blank?
212
- contents << content_tag(:p, message) unless message.blank?
213
- contents << safe_content_tag(:ul, error_messages)
214
-
215
- content_tag(:div, contents, html)
209
+ text
216
210
  end
217
- else
218
- ''
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)
219
217
  end
220
218
  end
221
219
 
@@ -251,24 +249,12 @@ module Padrino
251
249
  #
252
250
  # @api public
253
251
  def error_message_on(object, field, options={})
254
- object = object.is_a?(Symbol) ? instance_variable_get("@#{object}") : object
255
- error = object.errors[field] rescue nil
256
- error = if defined?(Ohm::Model) && object.is_a?(Ohm::Model)
257
- I18n.t("ohm.errors.messages.#{error[0]}", :default => error[0].to_s)
258
- else
259
- # Array(error).first is necessary because some ORMs
260
- # give us an array others directly a value.
261
- Array(error)[0]
262
- end
263
-
264
- if error = Array(error)[0]
265
- options.reverse_merge!(:tag => :span, :class => :error)
266
- tag = options.delete(:tag)
267
- error = [options.delete(:prepend), error, options.delete(:append)].compact.join(" ")
268
- content_tag(tag, error, options)
269
- else
270
- ''
271
- end
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)
272
258
  end
273
259
 
274
260
  ##
@@ -290,14 +276,15 @@ module Padrino
290
276
  # label_tag :username, :class => 'long-label' do ... end
291
277
  #
292
278
  def label_tag(name, options={}, &block)
293
- options.reverse_merge!(:caption => "#{name.to_s.humanize}: ", :for => name)
294
- caption_text = options.delete(:caption).html_safe
279
+ options = options.reverse_merge(:caption => "#{name.to_s.humanize}: ", :for => name)
280
+ caption_text = ''.html_safe
281
+ caption_text.concat options.delete(:caption)
295
282
  caption_text.safe_concat "<span class='required'>*</span> " if options.delete(:required)
296
283
 
297
- if block_given? # label with inner content
284
+ if block_given?
298
285
  label_content = caption_text.concat capture_html(&block)
299
286
  concat_content(content_tag(:label, label_content, options))
300
- else # regular label
287
+ else
301
288
  content_tag(:label, caption_text, options)
302
289
  end
303
290
  end
@@ -360,7 +347,7 @@ module Padrino
360
347
  # # => <input name="username" placeholder="Your Username" type="text" />
361
348
  #
362
349
  def text_field_tag(name, options={})
363
- input_tag(:text, options.reverse_merge!(:name => name))
350
+ input_tag(:text, options.reverse_merge(:name => name))
364
351
  end
365
352
 
366
353
  ##
@@ -510,8 +497,7 @@ module Padrino
510
497
  # hidden_field_tag :session_key, :value => "__secret__"
511
498
  #
512
499
  def hidden_field_tag(name, options={})
513
- options.reverse_merge!(:name => name)
514
- input_tag(:hidden, options)
500
+ input_tag(:hidden, options.reverse_merge(:name => name))
515
501
  end
516
502
 
517
503
  ##
@@ -521,7 +507,7 @@ module Padrino
521
507
  # text_area_tag :username, :class => 'long', :value => "Demo?"
522
508
  #
523
509
  def text_area_tag(name, options={})
524
- options.reverse_merge!(:name => name, :rows => "", :cols => "")
510
+ options = options.reverse_merge(:name => name, :rows => "", :cols => "")
525
511
  content_tag(:textarea, options.delete(:value).to_s, options)
526
512
  end
527
513
 
@@ -533,8 +519,7 @@ module Padrino
533
519
  #
534
520
  # @api public
535
521
  def password_field_tag(name, options={})
536
- options.reverse_merge!(:name => name)
537
- input_tag(:password, options)
522
+ input_tag(:password, options.reverse_merge(:name => name))
538
523
  end
539
524
 
540
525
  ##
@@ -544,8 +529,7 @@ module Padrino
544
529
  # check_box_tag :remember_me, :value => 'Yes'
545
530
  #
546
531
  def check_box_tag(name, options={})
547
- options.reverse_merge!(:name => name, :value => '1')
548
- input_tag(:checkbox, options)
532
+ input_tag(:checkbox, options.reverse_merge(:name => name, :value => '1'))
549
533
  end
550
534
 
551
535
  ##
@@ -555,8 +539,7 @@ module Padrino
555
539
  # radio_button_tag :remember_me, :value => 'true'
556
540
  #
557
541
  def radio_button_tag(name, options={})
558
- options.reverse_merge!(:name => name)
559
- input_tag(:radio, options)
542
+ input_tag(:radio, options.reverse_merge(:name => name))
560
543
  end
561
544
 
562
545
  ##
@@ -568,8 +551,7 @@ module Padrino
568
551
  # @api public
569
552
  def file_field_tag(name, options={})
570
553
  name = "#{name}[]" if options[:multiple]
571
- options.reverse_merge!(:name => name)
572
- input_tag(:file, options)
554
+ input_tag(:file, options.reverse_merge(:name => name))
573
555
  end
574
556
 
575
557
  ##
@@ -613,18 +595,12 @@ module Padrino
613
595
  # @return [String] The HTML input field based on the +options+ specified.
614
596
  #
615
597
  def select_tag(name, options={})
616
- options.reverse_merge!(:name => name)
598
+ options = options.reverse_merge(:name => name)
599
+ options[:name] = "#{options[:name]}[]" if options[:multiple]
617
600
  collection, fields = options.delete(:collection), options.delete(:fields)
618
601
  options[:options] = options_from_collection(collection, fields) if collection
619
- prompt = options.delete(:include_blank)
620
- select_options_html = if options[:options]
621
- options_for_select(options.delete(:options), options.delete(:selected))
622
- elsif options[:grouped_options]
623
- grouped_options_for_select(options.delete(:grouped_options), options.delete(:selected), prompt)
624
- end
625
- select_options_html = select_options_html.unshift(blank_option(prompt)) if select_options_html.is_a?(Array)
626
- options.merge!(:name => "#{options[:name]}[]") if options[:multiple]
627
- safe_content_tag(:select, select_options_html, options)
602
+ options_tags = extract_option_tags!(options)
603
+ content_tag(:select, options_tags, options)
628
604
  end
629
605
 
630
606
  ##
@@ -641,8 +617,7 @@ module Padrino
641
617
  # button_tag "Cancel", :class => 'clear'
642
618
  #
643
619
  def button_tag(caption, options = {})
644
- options.reverse_merge!(:value => caption)
645
- input_tag(:button, options)
620
+ input_tag(:button, options.reverse_merge(:value => caption))
646
621
  end
647
622
 
648
623
  ##
@@ -660,10 +635,9 @@ module Padrino
660
635
  # submit_tag :class => 'btn'
661
636
  #
662
637
  def submit_tag(*args)
663
- options = args[-1].is_a?(Hash) ? args.pop : {}
664
- caption = args.length >= 1 ? args.shift : "Submit"
665
- options.reverse_merge!(:value => caption)
666
- input_tag(:submit, options)
638
+ options = args.extract_options!
639
+ caption = args.length >= 1 ? args.first : "Submit"
640
+ input_tag(:submit, options.reverse_merge(:value => caption))
667
641
  end
668
642
 
669
643
  ##
@@ -677,11 +651,10 @@ module Padrino
677
651
  # @return [String] The html image button based on the +options+ specified.
678
652
  #
679
653
  # @example
680
- # submit_tag "Create", :class => 'success'
654
+ # image_submit_tag 'form/submit.png'
681
655
  #
682
656
  def image_submit_tag(source, options={})
683
- options.reverse_merge!(:src => image_path(source))
684
- input_tag(:image, options)
657
+ input_tag(:image, options.reverse_merge(:src => image_path(source)))
685
658
  end
686
659
 
687
660
  ##
@@ -747,14 +720,14 @@ module Padrino
747
720
  # # </form>
748
721
  #
749
722
  def button_to(*args, &block)
723
+ options = args.extract_options!.dup
750
724
  name, url = args[0], args[1]
751
- options = args.extract_options!
752
725
  options['data-remote'] = 'true' if options.delete(:remote)
753
726
  submit_options = options.delete(:submit_options) || {}
754
727
  if block_given?
755
- form_tag(url, options, &block)
728
+ form_tag(url || name, options, &block)
756
729
  else
757
- form_tag(url, options.merge!(:not_concat => true)) do
730
+ form_tag(url, options) do
758
731
  submit_tag(name, submit_options)
759
732
  end
760
733
  end
@@ -780,7 +753,7 @@ module Padrino
780
753
  # @return [String] The html range field
781
754
  #
782
755
  def range_field_tag(name, options = {})
783
- options.reverse_merge!(:name => name)
756
+ options = options.reverse_merge(:name => name)
784
757
  if range = options.delete(:range)
785
758
  options[:min], options[:max] = range.min, range.max
786
759
  end
@@ -802,39 +775,27 @@ module Padrino
802
775
  ##
803
776
  # Returns the options tags for a select based on the given option items.
804
777
  #
805
- def options_for_select(option_items, selected_value=nil)
778
+ def options_for_select(option_items, state = {})
806
779
  return [] if option_items.blank?
807
- option_items.map do |caption, value, disabled|
808
- value ||= caption
809
- disabled ||= false
810
- content_tag(:option, caption, :value => value, :selected => option_is_selected?(value, caption, selected_value), :disabled => disabled)
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)
811
785
  end
812
786
  end
813
787
 
814
788
  ##
815
789
  # Returns the optgroups with options tags for a select based on the given :grouped_options items.
816
790
  #
817
- def grouped_options_for_select(collection, selected=nil, prompt=false)
818
- if collection.is_a?(Hash)
819
- collection.map do |key, value|
820
- # Hash format:
821
- # {:first => [1,2,3], :second => [4,5,6]}
822
- # or:
823
- # {:first => [[1,2,3], {:disabled => true}], :second => [4,5,6]}
824
- attributes_hash = value.last.is_a?(Hash) ? value.pop : nil
825
- disabled ||= attributes_hash && attributes_hash.include?(:disabled) ? attributes_hash[:disabled] : false
826
- content_tag :optgroup, options_for_select(value, selected), :label => key, :disabled => disabled
827
- end
828
- elsif collection.is_a?(Array)
829
- # Array format:
830
- # ["Option Label", [:option1, :option2, ...]]
831
- # or:
832
- # ["Option Label", [:option1, :option2, ...], true]
833
- # the last item tells if it is disabled or not. This is keeps it backwards compatible.
834
- collection.map do |optgroup|
835
- disabled ||= optgroup.count > 2 ? optgroup.pop : false
836
- content_tag :optgroup, options_for_select(optgroup.last, selected), :label => optgroup.first, :disabled => disabled
837
- end
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)
838
799
  end
839
800
  end
840
801
 
@@ -842,11 +803,15 @@ module Padrino
842
803
  # Returns the blank option serving as a prompt if passed.
843
804
  #
844
805
  def blank_option(prompt)
845
- return unless prompt
846
806
  case prompt
847
- when String then content_tag(:option, prompt, :value => '')
848
- when Array then content_tag(:option, prompt.first, :value => prompt.last)
849
- else content_tag(:option, '', :value => '')
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 => '')
850
815
  end
851
816
  end
852
817
 
@@ -877,6 +842,7 @@ module Padrino
877
842
  end
878
843
 
879
844
  private
845
+
880
846
  ##
881
847
  # Returns the FormBuilder class to use based on all available setting sources
882
848
  # If explicitly defined, returns that, otherwise returns defaults.
@@ -914,6 +880,32 @@ module Padrino
914
880
  [value.to_s, caption.to_s].include?(selected.to_s)
915
881
  end
916
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
908
+ end
917
909
  end
918
910
  end
919
911
  end
@@ -78,7 +78,7 @@ module Padrino
78
78
  def simple_format(text, options={})
79
79
  t = options.delete(:tag) || :p
80
80
  start_tag = tag(t, options, true)
81
- text = escape_html(text.to_s.dup)
81
+ text = escape_html(text.to_s.dup) unless text.html_safe?
82
82
  text.gsub!(/\r\n?/, "\n") # \r\n and \r -> \n
83
83
  text.gsub!(/\n\n+/, "</#{t}>\n\n#{start_tag}") # 2+ newline -> paragraph
84
84
  text.gsub!(/([^\n]\n)(?=[^\n])/, '\1<br />') # 1 newline -> br
@@ -1,94 +1,59 @@
1
1
  module Padrino
2
2
  module Helpers
3
3
  module OutputHelpers
4
- ##
5
- # Returns the list of all available template handlers.
6
- #
7
- # @example
8
- # OutputHelpers.handlers => [<OutputHelpers::HamlHandler>, <OutputHelpers::ErbHandler>]
9
- #
10
- def self.handlers
11
- @_template_handlers ||= []
12
- end
13
-
14
- ##
15
- # Registers a new handler as available to the output helpers.
16
- #
17
- # @example
18
- # OutputHelpers.register(OutputHelpers::HamlHandler)
19
- #
20
- def self.register(handler)
21
- handlers << handler
22
- end
23
-
24
- # @abstract Extend this to create a template handler.
25
4
  class AbstractHandler
26
- attr_reader :template
5
+ attr_reader :template, :output_buffer
27
6
 
28
7
  def initialize(template)
29
8
  @template = template
30
- end
31
-
32
- ##
33
- # Returns extension of the template.
34
- #
35
- # @example
36
- # @handler.template_extension => "erb"
37
- #
38
- def template_extension
39
- caller.find { |c| c =~ /\/views\// }[/\.([\w]*?)\:/, 1] rescue nil
40
- # "/some/path/app/views/posts/foo.html.erb:3:in `evaluate_source'"
41
- # => "erb"
42
- end
43
-
44
- ##
45
- # Returns an array of engines used for the template.
46
- #
47
- # @example
48
- # @handler.engines => [:erb, :erubis]
49
- #
50
- def engines
51
- # Implemented in subclass.
52
- end
53
-
54
- ##
55
- # Returns true if the current template type is same as this handlers; false otherwise.
56
- #
57
- # @example
58
- # @handler.is_type? => true
59
- #
60
- def is_type?
61
- # Implemented in subclass.
9
+ @output_buffer = template.instance_variable_get(:@_out_buf)
62
10
  end
63
11
 
64
12
  ##
65
13
  # Returns true if the block given is of the handler's template type; false otherwise.
66
14
  #
67
15
  # @example
68
- # @handler.block_is_type?(block) => true
16
+ # @handler.engine_matches?(block) => true
69
17
  #
70
- def block_is_type?(block)
71
- # Implemented in subclass.
18
+ def engine_matches?(block)
72
19
  end
73
20
 
74
21
  ##
75
22
  # Captures the html from a block of template code for this handler.
76
23
  #
24
+ # This method is called to capture content of a block-loving helpers in templates.
25
+ # Haml has a special method to do this, for Erb and Slim we save original buffer,
26
+ # call the block and then restore the buffer.
27
+ #
77
28
  # @example
78
29
  # @handler.capture_from_template(&block) => "...html..."
79
30
  #
80
31
  def capture_from_template(*args, &block)
81
- # Implemented in subclass.
32
+ self.output_buffer, _buf_was = ActiveSupport::SafeBuffer.new, self.output_buffer
33
+ raw = block.call(*args)
34
+ captured = template.instance_variable_get(:@_out_buf)
35
+ self.output_buffer = _buf_was
36
+ engine_matches?(block) ? captured : raw
82
37
  end
83
38
 
84
39
  ##
85
- # Outputs the given text to the templates buffer directly.
40
+ # Outputs the given text to the template.
41
+ #
42
+ # This method is called when template uses block-aware helpers. For Slim and Haml such
43
+ # helpers just return output to use with `=`. For Erb this method is implemented in
44
+ # ErbHandler by concatenating given text to output buffer.
86
45
  #
87
46
  # @example
88
47
  # @handler.concat_to_template("This will be output to the template buffer")
89
48
  #
90
49
  def concat_to_template(text="")
91
- # Implemented in subclass.
50
+ text
51
+ end
52
+
53
+ protected
54
+
55
+ def output_buffer=(val)
56
+ template.instance_variable_set(:@_out_buf, val)
92
57
  end
93
58
  end
94
59
  end
@@ -2,77 +2,26 @@ module Padrino
2
2
  module Helpers
3
3
  module OutputHelpers
4
4
  ##
5
- # Handler for reading and writing from an erb template.
5
+ # Handler for Erb template.
6
6
  #
7
7
  class ErbHandler < AbstractHandler
8
- attr_reader :output_buffer
9
-
10
- def initialize(template)
11
- super
12
- @output_buffer = template.instance_variable_get(:@_out_buf)
13
- end
14
-
15
- ##
16
- # Returns true if the current template type is same as this handlers; false otherwise.
17
- #
18
- # @example
19
- # @handler.is_type? => true
20
- #
21
- def is_type?
22
- !self.output_buffer.nil?
23
- end
24
-
25
- ##
26
- # Captures the html from a block of template code for this handler.
27
- #
28
- # @example
29
- # @handler.capture_from_template(&block) => "...html..."
30
- #
31
- def capture_from_template(*args, &block)
32
- self.output_buffer, _buf_was = ActiveSupport::SafeBuffer.new, self.output_buffer
33
- captured_block = block.call(*args)
34
- ret = eval("@_out_buf", block.binding)
35
- self.output_buffer = _buf_was
36
- [ ret, captured_block ]
37
- end
38
-
39
8
  ##
40
9
  # Outputs the given text to the templates buffer directly.
41
10
  #
42
- # @example
43
- # @handler.concat_to_template("This will be output to the template buffer")
44
- #
45
11
  def concat_to_template(text="")
46
- self.output_buffer << text if is_type? && text
12
+ output_buffer << text
47
13
  nil
48
14
  end
49
15
 
50
16
  ##
51
- # Returns true if the block given is of the handler's template type; false otherwise.
17
+ # Returns true if the block is Erb.
52
18
  #
53
- # @example
54
- # @handler.block_is_type?(block) => true
55
- #
56
- def block_is_type?(block)
57
- is_type? || (block && eval('defined?(__in_erb_template)', block.binding))
58
- end
59
-
60
- ##
61
- # Returns an array of engines used for the template.
62
- #
63
- # @example
64
- # @handler.engines => [:erb, :erubis]
65
- #
66
- def engines
67
- @_engines ||= [:erb, :erubis]
68
- end
69
-
70
- protected
71
- def output_buffer=(val)
72
- template.instance_variable_set(:@_out_buf, val)
19
+ def engine_matches?(block)
20
+ block.binding.eval('defined? __in_erb_template')
73
21
  end
74
22
  end
75
- OutputHelpers.register(ErbHandler)
23
+ OutputHelpers.register(:erb, ErbHandler)
24
+ OutputHelpers.register(:erubis, ErbHandler)
76
25
  end
77
26
  end
78
27
  end