padrino-helpers 0.9.24 → 0.9.25

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/lib/padrino-helpers.rb +0 -1
  2. data/lib/padrino-helpers/asset_tag_helpers.rb +2 -2
  3. data/lib/padrino-helpers/form_builder/abstract_form_builder.rb +1 -1
  4. data/lib/padrino-helpers/form_helpers.rb +57 -12
  5. data/lib/padrino-helpers/format_helpers.rb +8 -6
  6. data/lib/padrino-helpers/output_helpers.rb +28 -8
  7. data/lib/padrino-helpers/output_helpers/abstract_handler.rb +17 -10
  8. data/lib/padrino-helpers/output_helpers/erb_handler.rb +31 -32
  9. data/lib/padrino-helpers/output_helpers/haml_handler.rb +13 -4
  10. data/lib/padrino-helpers/output_helpers/slim_handler.rb +82 -0
  11. data/lib/padrino-helpers/render_helpers.rb +1 -1
  12. data/lib/padrino-helpers/tag_helpers.rb +1 -1
  13. data/test/fixtures/markup_app/app.rb +6 -4
  14. data/test/fixtures/markup_app/views/capture_concat.slim +13 -0
  15. data/test/fixtures/markup_app/views/content_for.slim +9 -0
  16. data/test/fixtures/markup_app/views/content_tag.slim +9 -0
  17. data/test/fixtures/markup_app/views/current_engine.erb +5 -0
  18. data/test/fixtures/markup_app/views/current_engine.haml +5 -0
  19. data/test/fixtures/markup_app/views/current_engine.slim +5 -0
  20. data/test/fixtures/markup_app/views/fields_for.erb +1 -1
  21. data/test/fixtures/markup_app/views/fields_for.haml +7 -7
  22. data/test/fixtures/markup_app/views/fields_for.slim +15 -0
  23. data/test/fixtures/markup_app/views/form_for.slim +47 -0
  24. data/test/fixtures/markup_app/views/form_tag.slim +45 -0
  25. data/test/fixtures/markup_app/views/link_to.slim +4 -0
  26. data/test/fixtures/markup_app/views/mail_to.slim +3 -0
  27. data/test/fixtures/markup_app/views/meta_tag.slim +3 -0
  28. data/test/fixtures/markup_app/views/partials/_erb.erb +1 -0
  29. data/test/fixtures/markup_app/views/partials/_haml.haml +1 -0
  30. data/test/fixtures/markup_app/views/partials/_slim.slim +1 -0
  31. data/test/fixtures/render_app/app.rb +10 -0
  32. data/test/fixtures/render_app/views/current_engine.haml +5 -0
  33. data/test/fixtures/render_app/views/current_engines/_erb.erb +1 -0
  34. data/test/fixtures/render_app/views/current_engines/_haml.haml +1 -0
  35. data/test/fixtures/render_app/views/current_engines/_slim.slim +1 -0
  36. data/test/helper.rb +1 -12
  37. data/test/test_asset_tag_helpers.rb +48 -0
  38. data/test/test_form_builder.rb +159 -6
  39. data/test/test_form_helpers.rb +165 -4
  40. data/test/test_format_helpers.rb +19 -2
  41. data/test/test_output_helpers.rb +53 -0
  42. data/test/test_render_helpers.rb +11 -0
  43. data/test/test_tag_helpers.rb +20 -0
  44. metadata +27 -9
  45. data/lib/padrino-helpers/dom_helpers.rb +0 -46
  46. data/test/test_dom_helpers.rb +0 -37
@@ -31,7 +31,6 @@ module Padrino
31
31
  class << self
32
32
  def registered(app)
33
33
  app.set :default_builder, 'StandardFormBuilder'
34
- app.helpers Padrino::Helpers::DomHelpers
35
34
  app.helpers Padrino::Helpers::OutputHelpers
36
35
  app.helpers Padrino::Helpers::TagHelpers
37
36
  app.helpers Padrino::Helpers::AssetTagHelpers
@@ -167,7 +167,7 @@ module Padrino
167
167
  def stylesheet_link_tag(*sources)
168
168
  options = sources.extract_options!.symbolize_keys
169
169
  options.reverse_merge!(:media => 'screen', :rel => 'stylesheet', :type => 'text/css')
170
- sources.collect { |source|
170
+ sources.flatten.map { |source|
171
171
  tag(:link, options.reverse_merge(:href => asset_path(:css, source)))
172
172
  }.join("\n")
173
173
  end
@@ -184,7 +184,7 @@ module Padrino
184
184
  def javascript_include_tag(*sources)
185
185
  options = sources.extract_options!.symbolize_keys
186
186
  options.reverse_merge!(:type => 'text/javascript', :content => "")
187
- sources.collect { |source|
187
+ sources.flatten.map { |source|
188
188
  tag(:script, options.reverse_merge(:src => asset_path(:js, source)))
189
189
  }.join("\n")
190
190
  end
@@ -202,7 +202,7 @@ module Padrino
202
202
  # Returns the object's models name
203
203
  # => user_assignment
204
204
  def object_model_name(explicit_object=object)
205
- explicit_object.is_a?(Symbol) ? explicit_object : explicit_object.class.to_s.underscore.gsub('/', '-')
205
+ explicit_object.is_a?(Symbol) ? explicit_object : explicit_object.class.to_s.underscore.gsub(/\//, '_')
206
206
  end
207
207
 
208
208
  # Returns the class type for the given object
@@ -47,7 +47,7 @@ module Padrino
47
47
  options["accept-charset"] ||= "UTF-8"
48
48
  inner_form_html = hidden_form_method_field(desired_method)
49
49
  inner_form_html += capture_html(&block)
50
- concat_content content_tag('form', inner_form_html, options)
50
+ concat_content content_tag(:form, inner_form_html, options)
51
51
  end
52
52
 
53
53
  ##
@@ -77,7 +77,7 @@ module Padrino
77
77
  legend_text = args[0].is_a?(String) ? args.first : nil
78
78
  legend_html = legend_text.blank? ? '' : content_tag(:legend, legend_text)
79
79
  field_set_content = legend_html + capture_html(&block)
80
- concat_content content_tag('fieldset', field_set_content, options)
80
+ concat_content content_tag(:fieldset, field_set_content, options)
81
81
  end
82
82
 
83
83
  ##
@@ -105,7 +105,7 @@ module Padrino
105
105
  #
106
106
  def error_messages_for(*objects)
107
107
  options = objects.extract_options!.symbolize_keys
108
- objects = objects.collect {|object_name| object_name.is_a?(Symbol) ? instance_variable_get("@#{object_name}") : object_name }.compact
108
+ objects = objects.map {|object_name| object_name.is_a?(Symbol) ? instance_variable_get("@#{object_name}") : object_name }.compact
109
109
  count = objects.inject(0) {|sum, object| sum + object.errors.size }
110
110
 
111
111
  unless count.zero?
@@ -125,13 +125,13 @@ module Padrino
125
125
  header_message = if options.include?(:header_message)
126
126
  options[:header_message]
127
127
  else
128
- object_name = options[:object_name].to_s.underscore.gsub('_', ' ')
128
+ object_name = options[:object_name].to_s.underscore.gsub(/\//, ' ')
129
129
  object_name = I18n.t(:name, :default => object_name.humanize, :scope => [:models, object_name], :count => 1)
130
130
  locale.t :header, :count => count, :model => object_name
131
131
  end
132
132
  message = options.include?(:message) ? options[:message] : locale.t(:body)
133
133
  error_messages = objects.map { |object|
134
- object_name = options[:object_name].to_s.underscore.gsub('_', ' ')
134
+ object_name = options[:object_name].to_s.underscore.gsub(/\//, ' ')
135
135
  object.errors.map { |f, msg|
136
136
  field = I18n.t(f, :default => f.to_s.humanize, :scope => [:models, object_name, :attributes])
137
137
  content_tag(:li, "%s %s" % [field, msg])
@@ -237,7 +237,7 @@ module Padrino
237
237
  # text_area_tag :username, :class => 'long', :value => "Demo?"
238
238
  #
239
239
  def text_area_tag(name, options={})
240
- options.reverse_merge!(:name => name)
240
+ options.reverse_merge!(:name => name, :rows => "", :cols => "")
241
241
  content_tag(:textarea, options.delete(:value).to_s, options)
242
242
  end
243
243
 
@@ -254,7 +254,7 @@ module Padrino
254
254
  end
255
255
 
256
256
  ##
257
- # Constructs a check_box from the given options
257
+ # Constructs a select from the given options
258
258
  #
259
259
  # ==== Examples
260
260
  #
@@ -263,13 +263,27 @@ module Padrino
263
263
  # select_tag(:favorite_color, :options => ['red', 'yellow'], :selected => 'green1')
264
264
  # select_tag(:country, :collection => @countries, :fields => [:name, :code], :include_blank => 'None')
265
265
  #
266
+ # # Optgroups can be generated using :grouped_options => (Hash or nested Array)
267
+ # grouped_options = [['Friends',['Yoda',['Obiwan',1]]],['Enemies',['Palpatine',['Darth Vader',3]]]]
268
+ # grouped_options = {'Friends' => ['Yoda',['Obiwan',1]],'Enemies' => ['Palpatine',['Darth Vader',3]]}
269
+ # select_tag(:color, :grouped_options => [['warm',['red','yellow']],['cool',['blue', 'purple']]])
270
+ #
271
+ # # Optgroups can be generated using :grouped_options => (Hash or nested Array)
272
+ # grouped_options = [['Friends',['Yoda',['Obiwan',1]]],['Enemies',['Palpatine',['Darth Vader',3]]]]
273
+ # grouped_options = {'Friends' => ['Yoda',['Obiwan',1]],'Enemies' => ['Palpatine',['Darth Vader',3]]}
274
+ # select_tag(:color, :grouped_options => [['warm',['red','yellow']],['cool',['blue', 'purple']]])
275
+ #
266
276
  def select_tag(name, options={})
267
277
  options.reverse_merge!(:name => name)
268
278
  collection, fields = options.delete(:collection), options.delete(:fields)
269
279
  options[:options] = options_from_collection(collection, fields) if collection
270
- blank = options.delete(:include_blank)
271
- options[:options].unshift(blank.is_a?(String) ? [blank, ''] : '') if blank
272
- select_options_html = options_for_select(options.delete(:options), options.delete(:selected))
280
+ prompt = options.delete(:include_blank)
281
+ select_options_html = if options[:options]
282
+ options_for_select(options.delete(:options), options.delete(:selected))
283
+ elsif options[:grouped_options]
284
+ grouped_options_for_select(options.delete(:grouped_options), options.delete(:selected), prompt)
285
+ end
286
+ select_options_html = select_options_html.unshift(blank_option(prompt)) if select_options_html.is_a?(Array)
273
287
  options.merge!(:name => "#{options[:name]}[]") if options[:multiple]
274
288
  content_tag(:select, select_options_html, options)
275
289
  end
@@ -350,7 +364,7 @@ module Padrino
350
364
  # fields is an array containing the fields to display from each item in the collection
351
365
  #
352
366
  def options_from_collection(collection, fields)
353
- collection.collect { |item| [ item.send(fields.first), item.send(fields.last) ] }
367
+ collection.map { |item| [ item.send(fields.first), item.send(fields.last) ] }
354
368
  end
355
369
 
356
370
  #
@@ -358,12 +372,43 @@ module Padrino
358
372
  #
359
373
  def options_for_select(option_items, selected_value=nil)
360
374
  return '' if option_items.blank?
361
- option_items.collect do |caption, value|
375
+ option_items.map do |caption, value|
362
376
  value ||= caption
363
377
  content_tag(:option, caption, :value => value, :selected => option_is_selected?(value, caption, selected_value))
364
378
  end
365
379
  end
366
380
 
381
+ #
382
+ # Returns the optgroups with options tags for a select based on the given :grouped_options items
383
+ #
384
+ def grouped_options_for_select(collection,selected=nil,prompt=false)
385
+ if collection.is_a?(Hash)
386
+ collection.map do |key, value|
387
+ content_tag :optgroup, :label => key do
388
+ options_for_select(value, selected)
389
+ end
390
+ end
391
+ elsif collection.is_a?(Array)
392
+ collection.map do |optgroup|
393
+ content_tag :optgroup, :label => optgroup.first do
394
+ options_for_select(optgroup.last, selected)
395
+ end
396
+ end
397
+ end
398
+ end
399
+
400
+ #
401
+ # Returns the blank option serving as a prompt if passed
402
+ #
403
+ def blank_option(prompt)
404
+ return unless prompt
405
+ case prompt
406
+ when String then content_tag(:option, prompt, :value => '')
407
+ when Array then content_tag(:option, prompt.first, :value => prompt.last)
408
+ else content_tag(:option, '', :value => '')
409
+ end
410
+ end
411
+
367
412
  private
368
413
  ##
369
414
  # Returns the FormBuilder class to use based on all available setting sources
@@ -28,21 +28,23 @@ module Padrino
28
28
 
29
29
  ##
30
30
  # Returns text transformed into HTML using simple formatting rules. Two or more consecutive newlines(\n\n) are considered
31
- # as a paragraph and wrapped in <p> tags. One newline (\n) is considered as a linebreak and a <br /> tag is appended.
31
+ # as a paragraph and wrapped in <p> or your own tags. One newline (\n) is considered as a linebreak and a <br /> tag is appended.
32
32
  # This method does not remove the newlines from the text.
33
33
  #
34
34
  # ==== Examples
35
35
  #
36
36
  # simple_format("hello\nworld") # => "<p>hello<br/>world</p>"
37
+ # simple_format("hello\nworld", :tag => :div, :class => :foo) # => "<div class="foo">hello<br/>world</div>"
37
38
  #
38
- def simple_format(text, html_options={})
39
- start_tag = tag('p', html_options.merge(:open => true))
39
+ def simple_format(text, options={})
40
+ t = options.delete(:tag) || :p
41
+ start_tag = tag(t, options.merge(:open => true))
40
42
  text = text.to_s.dup
41
43
  text.gsub!(/\r\n?/, "\n") # \r\n and \r -> \n
42
- text.gsub!(/\n\n+/, "</p>\n\n#{start_tag}") # 2+ newline -> paragraph
44
+ text.gsub!(/\n\n+/, "</#{t}>\n\n#{start_tag}") # 2+ newline -> paragraph
43
45
  text.gsub!(/([^\n]\n)(?=[^\n])/, '\1<br />') # 1 newline -> br
44
46
  text.insert 0, start_tag
45
- text << "</p>"
47
+ text << "</#{t}>"
46
48
  end
47
49
 
48
50
  ##
@@ -89,7 +91,7 @@ module Padrino
89
91
  end
90
92
  options.reverse_merge!(:line_width => 80)
91
93
 
92
- text.split("\n").collect do |line|
94
+ text.split("\n").map do |line|
93
95
  line.length > options[:line_width] ? line.gsub(/(.{1,#{options[:line_width]}})(\s+|$)/, "\\1\n").strip : line
94
96
  end * "\n"
95
97
  end
@@ -1,6 +1,25 @@
1
1
  module Padrino
2
2
  module Helpers
3
3
  module OutputHelpers
4
+
5
+ def self.included(base) #:nodoc:
6
+ base.send(:include, SinatraCurrentEngine) unless base.method_defined?(:current_engine)
7
+ end
8
+
9
+ ##
10
+ # Module used to detect in vanilla sinatra apps the current engine
11
+ #
12
+ module SinatraCurrentEngine
13
+ attr_reader :current_engine
14
+
15
+ def render(engine, *) #:nodoc:
16
+ @current_engine, engine_was = engine, @current_engine
17
+ output = super
18
+ @current_engine = engine_was
19
+ output
20
+ end
21
+ end
22
+
4
23
  ##
5
24
  # Captures the html from a block of template code for any available handler
6
25
  #
@@ -9,7 +28,8 @@ module Padrino
9
28
  # capture_html(&block) => "...html..."
10
29
  #
11
30
  def capture_html(*args, &block)
12
- handler = self.find_proper_handler
31
+ handler = find_proper_handler
32
+ captured_html = ""
13
33
  if handler && handler.is_type? && handler.block_is_type?(block)
14
34
  captured_html = handler.capture_from_template(*args, &block)
15
35
  end
@@ -17,6 +37,7 @@ module Padrino
17
37
  captured_html = block_given? && block.call(*args) if captured_html.blank?
18
38
  captured_html
19
39
  end
40
+ alias :capture :capture_html
20
41
 
21
42
  ##
22
43
  # Outputs the given text to the templates buffer directly
@@ -26,13 +47,14 @@ module Padrino
26
47
  # concat_content("This will be output to the template buffer")
27
48
  #
28
49
  def concat_content(text="")
29
- handler = self.find_proper_handler
50
+ handler = find_proper_handler
30
51
  if handler && handler.is_type?
31
52
  handler.concat_to_template(text)
32
53
  else # theres no template to concat, return the text directly
33
54
  text
34
55
  end
35
56
  end
57
+ alias :concat :concat_content
36
58
 
37
59
  ##
38
60
  # Returns true if the block is from a supported template type; false otherwise.
@@ -43,7 +65,7 @@ module Padrino
43
65
  # block_is_template?(block)
44
66
  #
45
67
  def block_is_template?(block)
46
- handler = self.find_proper_handler
68
+ handler = find_proper_handler
47
69
  block && handler && handler.block_is_type?(block)
48
70
  end
49
71
 
@@ -75,9 +97,7 @@ module Padrino
75
97
  def yield_content(key, *args)
76
98
  blocks = content_blocks[key.to_sym]
77
99
  return nil if blocks.empty?
78
- blocks.map { |content|
79
- capture_html(*args, &content)
80
- }.join
100
+ blocks.map { |content| capture_html(*args, &content) }.join
81
101
  end
82
102
 
83
103
  protected
@@ -89,7 +109,7 @@ module Padrino
89
109
  # content_blocks[:name] => ['...', '...']
90
110
  #
91
111
  def content_blocks
92
- @content_blocks ||= Hash.new {|h,k| h[k] = [] }
112
+ @content_blocks ||= Hash.new { |h,k| h[k] = [] }
93
113
  end
94
114
 
95
115
  ##
@@ -101,7 +121,7 @@ module Padrino
101
121
  # find_proper_handler => <OutputHelpers::HamlHandler>
102
122
  #
103
123
  def find_proper_handler
104
- OutputHelpers.handlers.map { |h| h.new(self) }.find { |h| h.is_type? }
124
+ OutputHelpers.handlers.map { |h| h.new(self) }.find { |h| h.engines.include?(current_engine) && h.is_type? }
105
125
  end
106
126
  end # OutputHelpers
107
127
  end # Helpers
@@ -1,9 +1,6 @@
1
1
  module Padrino
2
2
  module Helpers
3
-
4
3
  module OutputHelpers
5
- @template_handlers = []
6
-
7
4
  ##
8
5
  # Returns the list of all available template handlers
9
6
  #
@@ -12,7 +9,7 @@ module Padrino
12
9
  # OutputHelpers.handlers => [<OutputHelpers::HamlHandler>, <OutputHelpers::ErbHandler>]
13
10
  #
14
11
  def self.handlers
15
- @template_handlers
12
+ @_template_handlers ||= []
16
13
  end
17
14
 
18
15
  ##
@@ -38,12 +35,23 @@ module Padrino
38
35
  #
39
36
  # ==== Examples
40
37
  #
41
- # @handler.template_extension => "erubis"
38
+ # @handler.template_extension => "erb"
42
39
  #
43
40
  def template_extension
44
41
  caller.find { |c| c =~ /\/views\// }[/\.([\w]*?)\:/, 1] rescue nil
45
- # "/some/path/app/views/posts/foo.html.erubis:3:in `evaluate_source'"
46
- # => "erubis"
42
+ # "/some/path/app/views/posts/foo.html.erb:3:in `evaluate_source'"
43
+ # => "erb"
44
+ end
45
+
46
+ ##
47
+ # Returns an array of engines used for the template
48
+ #
49
+ # ==== Examples
50
+ #
51
+ # @handler.engines => [:erb, :erubis]
52
+ #
53
+ def engines
54
+ # Implemented in subclass
47
55
  end
48
56
 
49
57
  ##
@@ -91,6 +99,5 @@ module Padrino
91
99
  end
92
100
  end # AbstractHandler
93
101
  end # OutputHelpers
94
-
95
- end
96
- end
102
+ end # Helpers
103
+ end # Padrino
@@ -1,6 +1,5 @@
1
1
  module Padrino
2
2
  module Helpers
3
-
4
3
  module OutputHelpers
5
4
  class ErbHandler < AbstractHandler
6
5
  attr_reader :output_buffer
@@ -18,7 +17,7 @@ module Padrino
18
17
  # @handler.is_type? => true
19
18
  #
20
19
  def is_type?
21
- self.output_buffer.present?
20
+ !self.output_buffer.nil?
22
21
  end
23
22
 
24
23
  # Captures the html from a block of template code for this handler
@@ -28,7 +27,11 @@ module Padrino
28
27
  # @handler.capture_from_template(&block) => "...html..."
29
28
  #
30
29
  def capture_from_template(*args, &block)
31
- erb_with_output_buffer { block_given? && block.call(*args) }
30
+ self.output_buffer, _buf_was = "", self.output_buffer
31
+ block.call(*args)
32
+ ret = eval("@_out_buf", block.binding)
33
+ self.output_buffer = _buf_was
34
+ ret
32
35
  end
33
36
 
34
37
  ##
@@ -39,42 +42,38 @@ module Padrino
39
42
  # @handler.concat_to_template("This will be output to the template buffer")
40
43
  #
41
44
  def concat_to_template(text="")
42
- self.output_buffer << text if self.is_type? && text
45
+ self.output_buffer << text if is_type? && text
43
46
  nil
44
47
  end
45
48
 
46
- if RUBY_VERSION < '1.9.0'
47
- # Check whether we're called from an erb template.
48
- # We'd return a string in any other case, but erb <%= ... %>
49
- # can't take an <% end %> later on, so we have to use <% ... %>
50
- # and implicitly concat.
51
- def block_is_type?(block)
52
- self.is_type? || (block && eval('defined? __in_erb_template', block))
53
- end
54
- else
55
- def block_is_type?(block)
56
- self.is_type? || (block && eval('defined? __in_erb_template', block.binding))
57
- end
49
+ ##
50
+ # Returns true if the block given is of the handler's template type; false otherwise.
51
+ #
52
+ # ==== Examples
53
+ #
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
58
  end
59
59
 
60
- protected
61
-
62
60
  ##
63
- # Used to direct the buffer for the erb capture
61
+ # Returns an array of engines used for the template
62
+ #
63
+ # ==== Examples
64
64
  #
65
- def erb_with_output_buffer(buf = '')
66
- self.output_buffer, old_buffer = buf, self.output_buffer
67
- yield
68
- buf
69
- ensure
70
- self.output_buffer = old_buffer
65
+ # @handler.engines => [:erb, :erubis]
66
+ #
67
+ def engines
68
+ @_engines ||= [:erb, :erubis]
71
69
  end
72
70
 
73
- def output_buffer=(val)
74
- template.instance_variable_set(:@_out_buf, val)
75
- end
76
- end # ErbHandler
77
- OutputHelpers.register(ErbHandler)
71
+ protected
72
+ def output_buffer=(val)
73
+ template.instance_variable_set(:@_out_buf, val)
74
+ end
75
+ end # ErbHandler
76
+ OutputHelpers.register(ErbHandler)
78
77
  end # OutputHelpers
79
- end
80
- end
78
+ end # Helpers
79
+ end # Padrino