padrino-helpers 0.11.3 → 0.11.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/README.rdoc +1 -1
  3. data/lib/padrino-helpers.rb +3 -5
  4. data/lib/padrino-helpers/asset_tag_helpers.rb +32 -40
  5. data/lib/padrino-helpers/breadcrumb_helpers.rb +21 -39
  6. data/lib/padrino-helpers/form_builder/abstract_form_builder.rb +121 -118
  7. data/lib/padrino-helpers/form_builder/standard_form_builder.rb +6 -9
  8. data/lib/padrino-helpers/form_helpers.rb +190 -193
  9. data/lib/padrino-helpers/format_helpers.rb +29 -42
  10. data/lib/padrino-helpers/locale/cs.yml +14 -14
  11. data/lib/padrino-helpers/locale/da.yml +1 -1
  12. data/lib/padrino-helpers/locale/de.yml +1 -1
  13. data/lib/padrino-helpers/locale/en.yml +16 -16
  14. data/lib/padrino-helpers/locale/es.yml +16 -16
  15. data/lib/padrino-helpers/locale/fr.yml +1 -2
  16. data/lib/padrino-helpers/locale/hu.yml +16 -16
  17. data/lib/padrino-helpers/locale/it.yml +2 -2
  18. data/lib/padrino-helpers/locale/ja.yml +16 -16
  19. data/lib/padrino-helpers/locale/lv.yml +16 -16
  20. data/lib/padrino-helpers/locale/nl.yml +1 -1
  21. data/lib/padrino-helpers/locale/no.yml +1 -1
  22. data/lib/padrino-helpers/locale/pl.yml +7 -7
  23. data/lib/padrino-helpers/locale/pt_br.yml +16 -16
  24. data/lib/padrino-helpers/locale/ro.yml +16 -16
  25. data/lib/padrino-helpers/locale/ru.yml +16 -16
  26. data/lib/padrino-helpers/locale/sv.yml +16 -16
  27. data/lib/padrino-helpers/locale/tr.yml +16 -16
  28. data/lib/padrino-helpers/locale/uk.yml +16 -16
  29. data/lib/padrino-helpers/locale/zh_cn.yml +16 -16
  30. data/lib/padrino-helpers/locale/zh_tw.yml +16 -16
  31. data/lib/padrino-helpers/number_helpers.rb +10 -15
  32. data/lib/padrino-helpers/output_helpers.rb +49 -57
  33. data/lib/padrino-helpers/output_helpers/abstract_handler.rb +16 -18
  34. data/lib/padrino-helpers/output_helpers/erb_handler.rb +11 -12
  35. data/lib/padrino-helpers/output_helpers/haml_handler.rb +9 -9
  36. data/lib/padrino-helpers/output_helpers/slim_handler.rb +11 -13
  37. data/lib/padrino-helpers/render_helpers.rb +5 -6
  38. data/lib/padrino-helpers/tag_helpers.rb +18 -21
  39. data/lib/padrino-helpers/translation_helpers.rb +4 -6
  40. data/test/fixtures/markup_app/app.rb +7 -3
  41. data/test/fixtures/render_app/app.rb +1 -0
  42. data/test/test_asset_tag_helpers.rb +1 -1
  43. data/test/test_form_builder.rb +5 -6
  44. data/test/test_form_helpers.rb +24 -12
  45. data/test/test_format_helpers.rb +3 -3
  46. data/test/test_number_helpers.rb +4 -0
  47. data/test/test_output_helpers.rb +1 -1
  48. data/test/test_render_helpers.rb +1 -1
  49. data/test/test_tag_helpers.rb +1 -1
  50. metadata +9 -15
@@ -1,7 +1,7 @@
1
1
  module Padrino
2
2
  module Helpers
3
- module FormBuilder # @private
4
- class AbstractFormBuilder # @private
3
+ module FormBuilder
4
+ class AbstractFormBuilder
5
5
  attr_accessor :template, :object, :multipart
6
6
 
7
7
  def initialize(template, object, options={})
@@ -12,37 +12,32 @@ module Padrino
12
12
  raise "FormBuilder object must not be a nil value. If there's no object, use a symbol instead! (i.e :user)" unless object
13
13
  end
14
14
 
15
- # f.error_messages
16
15
  def error_messages(*params)
17
16
  params.unshift object
18
17
  @template.error_messages_for(*params)
19
18
  end
20
19
 
21
- # f.error_message_on(field)
22
20
  def error_message_on(field, options={})
23
21
  @template.error_message_on(object, field, options)
24
22
  end
25
23
 
26
- # f.label :username, :caption => "Nickname"
27
24
  def label(field, options={}, &block)
28
25
  options.reverse_merge!(:caption => "#{field_human_name(field)}: ")
29
26
  @template.label_tag(field_id(field), options, &block)
30
27
  end
31
28
 
32
- # f.hidden_field :session_id, :value => "45"
33
29
  def hidden_field(field, options={})
34
30
  options.reverse_merge!(:value => field_value(field), :id => field_id(field))
35
31
  @template.hidden_field_tag field_name(field), options
36
32
  end
37
33
 
38
- # f.text_field :username, :value => "(blank)", :id => 'username'
39
34
  def text_field(field, options={})
40
35
  options.reverse_merge!(:value => field_value(field), :id => field_id(field))
41
36
  options.merge!(:class => field_error(field, options))
42
37
  @template.text_field_tag field_name(field), options
43
38
  end
44
39
 
45
- def number_field(field, options={})
40
+ def number_field(field, options={})
46
41
  options.reverse_merge!(:value => field_value(field), :id => field_id(field))
47
42
  options.merge!(:class => field_error(field, options))
48
43
  @template.number_field_tag field_name(field), options
@@ -73,35 +68,28 @@ module Padrino
73
68
  @template.url_field_tag field_name(field), options
74
69
  end
75
70
 
76
- # f.text_area :summary, :value => "(enter summary)", :id => 'summary'
77
71
  def text_area(field, options={})
78
72
  options.reverse_merge!(:value => field_value(field), :id => field_id(field))
79
73
  options.merge!(:class => field_error(field, options))
80
74
  @template.text_area_tag field_name(field), options
81
75
  end
82
76
 
83
- # f.password_field :password, :id => 'password'
84
77
  def password_field(field, options={})
85
78
  options.reverse_merge!(:value => field_value(field), :id => field_id(field))
86
79
  options.merge!(:class => field_error(field, options))
87
80
  @template.password_field_tag field_name(field), options
88
81
  end
89
82
 
90
- # f.select :color, :options => ['red', 'green'], :include_blank => true
91
- # f.select :color, :collection => @colors, :fields => [:name, :id]
92
83
  def select(field, options={})
93
84
  options.reverse_merge!(:id => field_id(field), :selected => field_value(field))
94
85
  options.merge!(:class => field_error(field, options))
95
86
  @template.select_tag field_name(field), options
96
87
  end
97
88
 
98
- # f.check_box_group :color, :options => ['red', 'green', 'blue'], :selected => ['red', 'blue']
99
- # f.check_box_group :color, :collection => @colors, :fields => [:name, :id]
100
89
  def check_box_group(field, options={})
101
90
  selected_values = Array(options[:selected] || field_value(field))
102
91
  if options[:collection]
103
92
  fields = options[:fields] || [:name, :id]
104
- # don't use map!, it will break some orms
105
93
  selected_values = selected_values.map{ |v| (v.respond_to?(fields[0]) ? v.send(fields[1]) : v).to_s }
106
94
  end
107
95
  labeled_group( field, options ) do |variant|
@@ -109,8 +97,6 @@ module Padrino
109
97
  end
110
98
  end
111
99
 
112
- # f.radio_button_group :color, :options => ['red', 'green']
113
- # f.radio_button_group :color, :collection => @colors, :fields => [:name, :id], :selected => @colors.first
114
100
  def radio_button_group(field, options={})
115
101
  fields = options[:fields] || [:name, :id]
116
102
  selected_value = options[:selected] || field_value(field)
@@ -120,7 +106,6 @@ module Padrino
120
106
  end
121
107
  end
122
108
 
123
- # f.check_box :remember_me, :value => 'true', :uncheck_value => '0'
124
109
  def check_box(field, options={})
125
110
  html = ActiveSupport::SafeBuffer.new
126
111
  unchecked_value = options.delete(:uncheck_value) || '0'
@@ -130,14 +115,12 @@ module Padrino
130
115
  html << @template.check_box_tag(field_name(field), options)
131
116
  end
132
117
 
133
- # f.radio_button :gender, :value => 'male'
134
118
  def radio_button(field, options={})
135
119
  options.reverse_merge!(:id => field_id(field, options[:value]))
136
120
  options.reverse_merge!(:checked => true) if values_matches_field?(field, options[:value])
137
121
  @template.radio_button_tag field_name(field), options
138
122
  end
139
123
 
140
- # f.file_field :photo, :class => 'avatar'
141
124
  def file_field(field, options={})
142
125
  self.multipart = true
143
126
  options.reverse_merge!(:id => field_id(field))
@@ -145,19 +128,18 @@ module Padrino
145
128
  @template.file_field_tag field_name(field), options
146
129
  end
147
130
 
148
- # f.submit "Update", :class => 'large'
149
131
  def submit(*args)
150
132
  options = args[-1].is_a?(Hash) ? args.pop : {}
151
133
  caption = args.length >= 1 ? args.shift : "Submit"
152
134
  @template.submit_tag caption, options
153
135
  end
154
136
 
155
- # f.image_submit "buttons/submit.png", :class => 'large'
156
137
  def image_submit(source, options={})
157
138
  @template.image_submit_tag source, options
158
139
  end
159
140
 
160
- # Supports nested fields for a child model within a form
141
+ ##
142
+ # Supports nested fields for a child model within a form.
161
143
  # f.fields_for :addresses
162
144
  # f.fields_for :addresses, address
163
145
  # f.fields_for :addresses, @addresses
@@ -166,7 +148,7 @@ module Padrino
166
148
  include_index = default_collection.respond_to?(:each)
167
149
  nested_options = { :parent => self, :association => child_association }
168
150
  nested_objects = instance_or_collection ? Array(instance_or_collection) : Array(default_collection)
169
- result = nested_objects.each_with_index.map do |child_instance, index|
151
+ nested_objects.each_with_index.map do |child_instance, index|
170
152
  nested_options[:index] = include_index ? index : nil
171
153
  @template.fields_for(child_instance, { :nested => nested_options }, &block)
172
154
  end.join("\n").html_safe
@@ -177,112 +159,133 @@ module Padrino
177
159
  end
178
160
 
179
161
  protected
180
- # Returns the known field types for a formbuilder
181
- def self.field_types
182
- [:hidden_field, :text_field, :text_area, :password_field, :file_field, :radio_button, :check_box, :select]
183
- end
162
+ # Returns the known field types for a Formbuilder.
163
+ def self.field_types
164
+ [:hidden_field, :text_field, :text_area, :password_field, :file_field, :radio_button, :check_box, :select]
165
+ end
184
166
 
185
- # Returns true if the value matches the value in the field
186
- # field_has_value?(:gender, 'male')
187
- def values_matches_field?(field, value)
188
- value.present? && (field_value(field).to_s == value.to_s || field_value(field).to_s == 'true')
189
- end
167
+ ##
168
+ # Returns true if the value matches the value in the field.
169
+ # field_has_value?(:gender, 'male')
170
+ def values_matches_field?(field, value)
171
+ value.present? && (field_value(field).to_s == value.to_s || field_value(field).to_s == 'true')
172
+ end
190
173
 
191
- # Add a :invalid css class to the field if it contain an error
192
- def field_error(field, options)
193
- error = @object.errors[field] rescue nil
194
- error.blank? ? options[:class] : [options[:class], :invalid].flatten.compact.join(" ")
195
- end
174
+ ##
175
+ # Add a :invalid css class to the field if it contain an error.
176
+ #
177
+ def field_error(field, options)
178
+ error = @object.errors[field] rescue nil
179
+ error.blank? ? options[:class] : [options[:class], :invalid].flatten.compact.join(" ")
180
+ end
196
181
 
197
- # Returns the human name of the field. Look that use builtin I18n.
198
- def field_human_name(field)
199
- I18n.translate("#{object_model_name}.attributes.#{field}", :count => 1, :default => field.to_s.humanize, :scope => :models)
200
- end
182
+ ##
183
+ # Returns the human name of the field. Look that use builtin I18n.
184
+ #
185
+ def field_human_name(field)
186
+ I18n.translate("#{object_model_name}.attributes.#{field}", :count => 1, :default => field.to_s.humanize, :scope => :models)
187
+ end
201
188
 
202
- # Returns the name for the given field
203
- # field_name(:username) => "user[username]"
204
- # field_name(:number) => "user[telephone_attributes][number]"
205
- # field_name(:street) => "user[addresses_attributes][0][street]"
206
- def field_name(field=nil)
207
- result = field_result
208
- result << field_name_fragment if nested_form?
209
- result << "[#{field}]" unless field.blank?
210
- result.flatten.join
211
- end
189
+ ##
190
+ # Returns the name for the given field.
191
+ # field_name(:username) => "user[username]"
192
+ # field_name(:number) => "user[telephone_attributes][number]"
193
+ # field_name(:street) => "user[addresses_attributes][0][street]"
194
+ def field_name(field=nil)
195
+ result = field_result
196
+ result << field_name_fragment if nested_form?
197
+ result << "[#{field}]" unless field.blank?
198
+ result.flatten.join
199
+ end
212
200
 
213
- # Returns the id for the given field
214
- # field_id(:username) => "user_username"
215
- # field_id(:gender, :male) => "user_gender_male"
216
- # field_name(:number) => "user_telephone_attributes_number"
217
- # field_name(:street) => "user_addresses_attributes_0_street"
218
- def field_id(field=nil, value=nil)
219
- result = []
220
- result << "#{@options[:namespace]}_" if @options[:namespace] && root_form?
221
- result << field_result
222
- result << field_id_fragment if nested_form?
223
- result << "_#{field}" unless field.blank?
224
- result << "_#{value}" unless value.blank?
225
- result.flatten.join
226
- end
201
+ ##
202
+ # Returns the id for the given field.
203
+ # field_id(:username) => "user_username"
204
+ # field_id(:gender, :male) => "user_gender_male"
205
+ # field_name(:number) => "user_telephone_attributes_number"
206
+ # field_name(:street) => "user_addresses_attributes_0_street"
207
+ def field_id(field=nil, value=nil)
208
+ result = []
209
+ result << "#{@options[:namespace]}_" if @options[:namespace] && root_form?
210
+ result << field_result
211
+ result << field_id_fragment if nested_form?
212
+ result << "_#{field}" unless field.blank?
213
+ result << "_#{value}" unless value.blank?
214
+ result.flatten.join
215
+ end
227
216
 
228
- # Returns the child object if it exists
229
- def nested_object_id
230
- nested_form? && object.respond_to?(:new_record?) && !object.new_record? && object.id
231
- end
217
+ ##
218
+ # Returns the child object if it exists.
219
+ #
220
+ def nested_object_id
221
+ nested_form? && object.respond_to?(:new_record?) && !object.new_record? && object.id
222
+ end
232
223
 
233
- # Returns true if this form object is nested in a parent form
234
- def nested_form?
235
- @options[:nested] && @options[:nested][:parent] && @options[:nested][:parent].respond_to?(:object)
236
- end
224
+ ##
225
+ # Returns true if this form object is nested in a parent form.
226
+ #
227
+ def nested_form?
228
+ @options[:nested] && @options[:nested][:parent] && @options[:nested][:parent].respond_to?(:object)
229
+ end
237
230
 
238
- # Returns the value for the object's field
239
- # field_value(:username) => "Joey"
240
- def field_value(field)
241
- @object && @object.respond_to?(field) ? @object.send(field) : ""
242
- end
231
+ ##
232
+ # Returns the value for the object's field.
233
+ #
234
+ def field_value(field)
235
+ @object && @object.respond_to?(field) ? @object.send(field) : ""
236
+ end
243
237
 
244
- # explicit_object is either a symbol or a record
245
- # Returns a new record of the type specified in the object
246
- def build_object(object_or_symbol)
247
- object_or_symbol.is_a?(Symbol) ? @template.instance_variable_get("@#{object_or_symbol}") || object_class(object_or_symbol).new : object_or_symbol
248
- end
238
+ ##
239
+ # Returns a new record of the type specified in the object
240
+ #
241
+ def build_object(object_or_symbol)
242
+ object_or_symbol.is_a?(Symbol) ? @template.instance_variable_get("@#{object_or_symbol}") || object_class(object_or_symbol).new : object_or_symbol
243
+ end
249
244
 
250
- # Returns the object's models name
251
- # => user_assignment
252
- def object_model_name(explicit_object=object)
253
- explicit_object.is_a?(Symbol) ? explicit_object : explicit_object.class.to_s.underscore.gsub(/\//, '_')
254
- end
245
+ ##
246
+ # Returns the object's models name.
247
+ #
248
+ def object_model_name(explicit_object=object)
249
+ explicit_object.is_a?(Symbol) ? explicit_object : explicit_object.class.to_s.underscore.gsub(/\//, '_')
250
+ end
255
251
 
256
- # Returns the class type for the given object
257
- def object_class(explicit_object)
258
- explicit_object.is_a?(Symbol) ? explicit_object.to_s.camelize.constantize : explicit_object.class
259
- end
252
+ ##
253
+ # Returns the class type for the given object.
254
+ #
255
+ def object_class(explicit_object)
256
+ explicit_object.is_a?(Symbol) ? explicit_object.to_s.camelize.constantize : explicit_object.class
257
+ end
260
258
 
261
- # Returns true if this form is the top-level (not nested)
262
- def root_form?
263
- !nested_form?
264
- end
259
+ ##
260
+ # Returns true if this form is the top-level (not nested).
261
+ #
262
+ def root_form?
263
+ !nested_form?
264
+ end
265
265
 
266
- # Builds a group of labels for radios or checkboxes
267
- def labeled_group(field, options={})
268
- options.reverse_merge!(:id => field_id(field), :selected => field_value(field))
269
- options.merge!(:class => field_error(field, options))
270
- variants = case
271
- when options[:options]
272
- options[:options].map{ |caption, value| [caption.to_s, (value||caption).to_s] }
273
- when options[:collection]
274
- fields = options[:fields] || [:name, :id]
275
- options[:collection].map{ |variant| [variant.send(fields.first).to_s, variant.send(fields.last).to_s] }
276
- else
277
- []
278
- end
279
- variants.inject(''.html_safe) do |html, variant|
280
- variant[2] = "#{field_id(field)}_#{variant[1]}"
281
- html << @template.label_tag("#{field_name(field)}[]", :for => variant[2], :caption => "#{yield(variant)} #{variant[0]}")
282
- end
266
+ ##
267
+ # Builds a group of labels for radios or checkboxes.
268
+ #
269
+ def labeled_group(field, options={})
270
+ options.reverse_merge!(:id => field_id(field), :selected => field_value(field))
271
+ options.merge!(:class => field_error(field, options))
272
+ variants = case
273
+ when options[:options]
274
+ options[:options].map{ |caption, value| [caption.to_s, (value||caption).to_s] }
275
+ when options[:collection]
276
+ fields = options[:fields] || [:name, :id]
277
+ options[:collection].map{ |variant| [variant.send(fields.first).to_s, variant.send(fields.last).to_s] }
278
+ else
279
+ []
280
+ end
281
+ variants.inject(''.html_safe) do |html, variant|
282
+ variant[2] = "#{field_id(field)}_#{variant[1]}"
283
+ html << @template.label_tag("#{field_name(field)}[]", :for => variant[2], :caption => "#{yield(variant)} #{variant[0]}")
283
284
  end
285
+ end
284
286
 
285
287
  private
288
+
286
289
  def field_result
287
290
  result = []
288
291
  result << object_model_name if root_form?
@@ -308,7 +311,7 @@ module Padrino
308
311
  :attributes_name => "#{@options[:nested][:association]}_attributes"
309
312
  }
310
313
  end
311
- end # AbstractFormBuilder
312
- end # FormBuilder
313
- end # Helpers
314
- end # Padrino
314
+ end
315
+ end
316
+ end
317
+ end
@@ -2,9 +2,8 @@ require File.expand_path(File.dirname(__FILE__) + '/abstract_form_builder') unle
2
2
 
3
3
  module Padrino
4
4
  module Helpers
5
- module FormBuilder # @private
6
- class StandardFormBuilder < AbstractFormBuilder # @private
7
-
5
+ module FormBuilder
6
+ class StandardFormBuilder < AbstractFormBuilder
8
7
  ##
9
8
  # StandardFormBuilder
10
9
  #
@@ -26,18 +25,16 @@ module Padrino
26
25
  EOF
27
26
  end
28
27
 
29
- # submit_block("Update")
30
28
  def submit_block(caption, options={})
31
29
  submit_html = self.submit(caption, options)
32
30
  @template.content_tag(:p, submit_html)
33
31
  end
34
32
 
35
- # image_submit_block("submit.png")
36
33
  def image_submit_block(source, options={})
37
34
  submit_html = self.image_submit(source, options)
38
35
  @template.content_tag(:p, submit_html)
39
36
  end
40
- end # StandardFormBuilder
41
- end # FormBuilder
42
- end # Helpers
43
- end # Padrino
37
+ end
38
+ end
39
+ end
40
+ end
@@ -7,16 +7,16 @@ module Padrino
7
7
  #
8
8
  module FormHelpers
9
9
  ##
10
- # Constructs a form for object using given or default form_builder
10
+ # Constructs a form for object using given or default form_builder.
11
11
  #
12
12
  # @param [Object] object
13
13
  # The object for which the form is being built.
14
- # @param [String] url
14
+ # @param [String] URL
15
15
  # The url this form will submit to.
16
16
  # @param [Hash] settings
17
17
  # The settings associated with this form.
18
18
  # Accepts a :namespace option that will be prepended to the id attributes of the form's elements.
19
- # Also accepts html options.
19
+ # Also accepts HTML options.
20
20
  # @option settings [String] :builder ("StandardFormBuilder")
21
21
  # The FormBuilder class to use such as StandardFormBuilder.
22
22
  # @param [Proc] block
@@ -30,7 +30,6 @@ module Padrino
30
30
  # form_for :user, '/register' do |f| ... end
31
31
  # form_for @user, '/register', :id => 'register' do |f| ... end
32
32
  #
33
- # @api public
34
33
  def form_for(object, url, settings={}, &block)
35
34
  instance = builder_instance(object, settings)
36
35
  html = capture_html(instance, &block)
@@ -40,13 +39,13 @@ module Padrino
40
39
  end
41
40
 
42
41
  ##
43
- # Constructs form fields for an object using given or default form_builder
44
- # Used within an existing form to allow alternate objects within one form
42
+ # Constructs form fields for an object using given or default form_builder.
43
+ # Used within an existing form to allow alternate objects within one form.
45
44
  #
46
45
  # @param [Object] object
47
46
  # The object for which the fields are being built.
48
47
  # @param [Hash] settings
49
- # The settings associated with these fields. Accepts html options.
48
+ # The settings associated with these fields. Accepts HTML options.
50
49
  # @param [Proc] block
51
50
  # The content inside this set of fields.
52
51
  #
@@ -56,7 +55,6 @@ module Padrino
56
55
  # fields_for @user.assignment do |assignment| ... end
57
56
  # fields_for :assignment do |assigment| ... end
58
57
  #
59
- # @api public
60
58
  def fields_for(object, settings={}, &block)
61
59
  instance = builder_instance(object, settings)
62
60
  fields_html = capture_html(instance, &block)
@@ -65,21 +63,20 @@ module Padrino
65
63
  end
66
64
 
67
65
  ##
68
- # Constructs a form without object based on options
66
+ # Constructs a form without object based on options.
69
67
  #
70
68
  # @param [String] url
71
- # The url this form will submit to.
69
+ # The URL this form will submit to.
72
70
  # @param [Hash] options
73
71
  # The html options associated with this form.
74
72
  # @param [Proc] block
75
73
  # The fields and content inside this form.
76
74
  #
77
- # @return [String] The html form with the specified options and input fields.
75
+ # @return [String] The HTML form with the specified options and input fields.
78
76
  #
79
77
  # @example
80
78
  # form_tag '/register', :class => "registration_form" do ... end
81
79
  #
82
- # @api public
83
80
  def form_tag(url, options={}, &block)
84
81
  desired_method = options[:method].to_s
85
82
  options.delete(:method) unless desired_method =~ /get|post/i
@@ -99,12 +96,12 @@ module Padrino
99
96
  end
100
97
 
101
98
  ##
102
- # Returns the hidden method field for 'put' and 'delete' forms
99
+ # Returns the hidden method field for 'put' and 'delete' forms.
103
100
  # Only 'get' and 'post' are allowed within browsers;
104
101
  # 'put' and 'delete' are just specified using hidden fields with form action still 'put'.
105
102
  #
106
103
  # @param [String] desired_method
107
- # The method this hidden field represents (i.e put or delete))
104
+ # The method this hidden field represents (i.e put or delete).
108
105
  #
109
106
  # @return [String] The hidden field representing the +desired_method+ for the form.
110
107
  #
@@ -112,14 +109,13 @@ module Padrino
112
109
  # # Generate: <input name="_method" value="delete" />
113
110
  # hidden_form_method_field('delete')
114
111
  #
115
- # @api semipublic
116
112
  def hidden_form_method_field(desired_method)
117
113
  return ActiveSupport::SafeBuffer.new if desired_method.blank? || desired_method.to_s =~ /get|post/i
118
114
  hidden_field_tag(:_method, :value => desired_method)
119
115
  end
120
116
 
121
117
  ##
122
- # Constructs a field_set to group fields with given options
118
+ # Constructs a field_set to group fields with given options.
123
119
  #
124
120
  # @overload field_set_tag(legend=nil, options={}, &block)
125
121
  # @param [String] legend The legend caption for the fieldset
@@ -135,7 +131,6 @@ module Padrino
135
131
  # field_set_tag(:class => "office-set") { }
136
132
  # field_set_tag("Office", :class => 'office-set') { }
137
133
  #
138
- # @api public
139
134
  def field_set_tag(*args, &block)
140
135
  options = args.extract_options!
141
136
  legend_text = args[0].is_a?(String) ? args.first : nil
@@ -145,13 +140,13 @@ module Padrino
145
140
  end
146
141
 
147
142
  ##
148
- # Constructs list html for the errors for a given symbol
143
+ # Constructs list HTML for the errors for a given symbol.
149
144
  #
150
145
  # @overload error_messages_for(*objects, options = {})
151
146
  # @param [Array<Object>] object Splat of objects to display errors for.
152
147
  # @param [Hash] options Error message display options.
153
148
  # @option options [String] :header_tag ("h2")
154
- # Used for the header of the error div
149
+ # Used for the header of the error div.
155
150
  # @option options [String] :id ("field-errors")
156
151
  # The id of the error div.
157
152
  # @option options [String] :class ("field-errors")
@@ -163,7 +158,7 @@ module Padrino
163
158
  # The object name to use in the header, or any text that you prefer.
164
159
  # If +:object_name+ is not set, the name of the first object will be used.
165
160
  # @option options [String] :header_message ("X errors prohibited this object from being saved")
166
- # The message in the header of the error div. Pass +nil+ or an empty string
161
+ # The message in the header of the error div. Pass +nil+ or an empty string
167
162
  # to avoid the header message altogether.
168
163
  # @option options [String] :message ("There were problems with the following fields:")
169
164
  # The explanation message after the header message and before
@@ -175,7 +170,6 @@ module Padrino
175
170
  # @example
176
171
  # error_messages_for :user
177
172
  #
178
- # @api public
179
173
  def error_messages_for(*objects)
180
174
  options = objects.extract_options!.symbolize_keys
181
175
  objects = objects.map { |object_name|
@@ -194,19 +188,19 @@ module Padrino
194
188
  end
195
189
  end
196
190
 
197
- options[:object_name] ||= objects.first.class
191
+ options[:object_name] ||= objects.first.class.to_s.underscore.gsub(/\//, ' ')
198
192
 
199
193
  I18n.with_options :locale => options[:locale], :scope => [:models, :errors, :template] do |locale|
200
194
  header_message = if options.include?(:header_message)
201
195
  options[:header_message]
202
196
  else
203
- object_name = options[:object_name].to_s.underscore.gsub(/\//, ' ')
197
+ object_name = options[:object_name]
204
198
  object_name = I18n.t(:name, :default => object_name.humanize, :scope => [:models, object_name], :count => 1)
205
199
  locale.t :header, :count => count, :model => object_name
206
200
  end
207
201
  message = options.include?(:message) ? options[:message] : locale.t(:body)
208
202
  error_messages = objects.map { |object|
209
- object_name = options[:object_name].to_s.underscore.gsub(/\//, ' ')
203
+ object_name = options[:object_name]
210
204
  object.errors.map { |f, msg|
211
205
  field = I18n.t(f, :default => f.to_s.humanize, :scope => [:models, object_name, :attributes])
212
206
  content_tag(:li, "%s %s" % [field, msg])
@@ -226,7 +220,8 @@ module Padrino
226
220
  end
227
221
 
228
222
  ##
229
- # Returns a string containing the error message attached to the +method+ on the +object+ if one exists.
223
+ # Returns a string containing the error message attached to the
224
+ # +method+ on the +object+ if one exists.
230
225
  #
231
226
  # @param [Object] object
232
227
  # The object to display the error for.
@@ -262,7 +257,7 @@ module Padrino
262
257
  I18n.t("ohm.errors.messages.#{error[0]}", :default => error[0].to_s)
263
258
  else
264
259
  # Array(error).first is necessary because some ORMs
265
- # give us an array others directly a value
260
+ # give us an array others directly a value.
266
261
  Array(error)[0]
267
262
  end
268
263
 
@@ -277,7 +272,7 @@ module Padrino
277
272
  end
278
273
 
279
274
  ##
280
- # Constructs a label tag from the given options
275
+ # Constructs a label tag from the given options.
281
276
  #
282
277
  # @param [String] name
283
278
  # The name of the field to label.
@@ -294,7 +289,6 @@ module Padrino
294
289
  # label_tag :username, :class => 'long-label'
295
290
  # label_tag :username, :class => 'long-label' do ... end
296
291
  #
297
- # @api public
298
292
  def label_tag(name, options={}, &block)
299
293
  options.reverse_merge!(:caption => "#{name.to_s.humanize}: ", :for => name)
300
294
  caption_text = options.delete(:caption).html_safe
@@ -309,7 +303,7 @@ module Padrino
309
303
  end
310
304
 
311
305
  ##
312
- # Creates a text field input with the given name and options
306
+ # Creates a text field input with the given name and options.
313
307
  #
314
308
  # @macro [new] text_field
315
309
  # @param [Symbol] name
@@ -338,22 +332,22 @@ module Padrino
338
332
  # @option options [Boolean] :spellcheck
339
333
  # Specifies whether or not the field should have it's spelling and grammar checked for errors.
340
334
  # @option options [Boolean] :draggable
341
- # Specifies whether or not the field is draggable. (true, false, :auto)
335
+ # Specifies whether or not the field is draggable. (true, false, :auto).
342
336
  # @option options [String] :pattern
343
337
  # Specifies the regular expression pattern that the field's value is checked against.
344
338
  # @option options [Symbol] :autocomplete
345
- # Specifies whether or not the field should have autocomplete enabled. (:on, :off)
339
+ # Specifies whether or not the field should have autocomplete enabled. (:on, :off).
346
340
  # @option options [Boolean] :autofocus
347
341
  # Specifies whether or not the field should automatically get focus when the page loads.
348
342
  # @option options [Boolean] :required
349
- # Specifies whether or not the field is required to be completeled before the form is submitted.
343
+ # Specifies whether or not the field is required to be completed before the form is submitted.
350
344
  # @option options [Boolean] :readonly
351
345
  # Specifies whether or not the field is read only.
352
346
  # @option options [Boolean] :disabled
353
347
  # Specifies whether or not the field is disabled.
354
348
  #
355
349
  # @return [String]
356
- # Generated HTML with specified +options+
350
+ # Generated HTML with specified +options+.
357
351
  #
358
352
  # @example
359
353
  # text_field_tag :first_name, :maxlength => 40, :required => true
@@ -365,13 +359,12 @@ module Padrino
365
359
  # text_field_tag :username, :placeholder => 'Your Username'
366
360
  # # => <input name="username" placeholder="Your Username" type="text" />
367
361
  #
368
- # @api public
369
362
  def text_field_tag(name, options={})
370
363
  input_tag(:text, options.reverse_merge!(:name => name))
371
364
  end
372
365
 
373
366
  ##
374
- # Creates a number field input with the given name and options
367
+ # Creates a number field input with the given name and options.
375
368
  #
376
369
  # @macro [new] number_field
377
370
  # @param [Symbol] name
@@ -400,11 +393,11 @@ module Padrino
400
393
  # @option options [Boolean] :spellcheck
401
394
  # Specifies whether or not the field should have it's spelling and grammar checked for errors.
402
395
  # @option options [Boolean] :draggable
403
- # Specifies whether or not the field is draggable. (true, false, :auto)
396
+ # Specifies whether or not the field is draggable. (true, false, :auto).
404
397
  # @option options [String] :pattern
405
398
  # Specifies the regular expression pattern that the field's value is checked against.
406
399
  # @option options [Symbol] :autocomplete
407
- # Specifies whether or not the field should have autocomplete enabled. (:on, :off)
400
+ # Specifies whether or not the field should have autocomplete enabled. (:on, :off).
408
401
  # @option options [Boolean] :autofocus
409
402
  # Specifies whether or not the field should automatically get focus when the page loads.
410
403
  # @option options [Boolean] :required
@@ -415,11 +408,11 @@ module Padrino
415
408
  # Specifies whether or not the field is disabled.
416
409
  #
417
410
  # @return [String]
418
- # Generated HTML with specified +options+
411
+ # Generated HTML with specified +options+.
419
412
  #
420
413
  # @example
421
- # number_field_tag :quanity, :class => 'numeric'
422
- # # => <input name="quanity" class="numeric" type="number" />
414
+ # number_field_tag :quantity, :class => 'numeric'
415
+ # # => <input name="quantity" class="numeric" type="number" />
423
416
  #
424
417
  # number_field_tag :zip_code, :pattern => /[0-9]{5}/
425
418
  # # => <input name="zip_code" pattern="[0-9]{5}" type="number" />
@@ -430,13 +423,12 @@ module Padrino
430
423
  # number_field_tag :age, :min => 18, :max => 120, :step => 1
431
424
  # # => <input name="age" min="18" max="120" step="1" type="number" />
432
425
  #
433
- # @api public
434
426
  def number_field_tag(name, options={})
435
427
  input_tag(:number, options.reverse_merge(:name => name))
436
428
  end
437
429
 
438
430
  ##
439
- # Creates a telephone field input with the given name and options
431
+ # Creates a telephone field input with the given name and options.
440
432
  #
441
433
  # @macro text_field
442
434
  #
@@ -452,14 +444,13 @@ module Padrino
452
444
  # # => <input name="work_phone" tabindex="2" type="tel" />
453
445
  # # => <input name="home_phone" tabindex="3" type="tel" />
454
446
  #
455
- # @api public
456
447
  def telephone_field_tag(name, options={})
457
448
  input_tag(:tel, options.reverse_merge(:name => name))
458
449
  end
459
450
  alias_method :phone_field_tag, :telephone_field_tag
460
451
 
461
452
  ##
462
- # Creates an email field input with the given name and options
453
+ # Creates an email field input with the given name and options.
463
454
  #
464
455
  # @macro text_field
465
456
  #
@@ -470,13 +461,12 @@ module Padrino
470
461
  # email_field_tag :email, :value => 'padrinorb@gmail.com', :readonly => true
471
462
  # # => <input name="email" value="padrinorb@gmail.com" readonly type="email" />
472
463
  #
473
- # @api public
474
464
  def email_field_tag(name, options={})
475
465
  input_tag(:email, options.reverse_merge(:name => name))
476
466
  end
477
467
 
478
468
  ##
479
- # Creates a search field input with the given name and options
469
+ # Creates a search field input with the given name and options.
480
470
  #
481
471
  # @macro text_field
482
472
  #
@@ -493,13 +483,12 @@ module Padrino
493
483
  # search_field_tag :search, :autofocus => true
494
484
  # # => <input name="search" autofocus type="search" />
495
485
  #
496
- # @api public
497
486
  def search_field_tag(name, options={})
498
487
  input_tag(:search, options.reverse_merge(:name => name))
499
488
  end
500
489
 
501
490
  ##
502
- # Creates a url field input with the given name and options
491
+ # Creates a URL field input with the given name and options.
503
492
  #
504
493
  # @macro text_field
505
494
  #
@@ -510,43 +499,34 @@ module Padrino
510
499
  # url_field_tag :home_page, :class => 'string url'
511
500
  # <input name="home_page" class="string url", type="url" />
512
501
  #
513
- # @api public
514
502
  def url_field_tag(name, options={})
515
503
  input_tag(:url, options.reverse_merge(:name => name))
516
504
  end
517
505
 
518
506
  ##
519
- # Constructs a hidden field input from the given options
520
- #
521
- # @macro text_field
507
+ # Constructs a hidden field input from the given options.
522
508
  #
523
509
  # @example
524
510
  # hidden_field_tag :session_key, :value => "__secret__"
525
511
  #
526
- # @api public
527
512
  def hidden_field_tag(name, options={})
528
513
  options.reverse_merge!(:name => name)
529
514
  input_tag(:hidden, options)
530
515
  end
531
516
 
532
517
  ##
533
- # Constructs a text area input from the given options
534
- #
535
- # @macro text_field
518
+ # Constructs a text area input from the given options.
536
519
  #
537
520
  # @example
538
521
  # text_area_tag :username, :class => 'long', :value => "Demo?"
539
522
  #
540
- # @api public
541
523
  def text_area_tag(name, options={})
542
524
  options.reverse_merge!(:name => name, :rows => "", :cols => "")
543
525
  content_tag(:textarea, options.delete(:value).to_s, options)
544
526
  end
545
527
 
546
528
  ##
547
- # Constructs a password field input from the given options
548
- #
549
- # @macro text_field
529
+ # Constructs a password field input from the given options.
550
530
  #
551
531
  # @example
552
532
  # password_field_tag :password, :class => 'long'
@@ -558,37 +538,29 @@ module Padrino
558
538
  end
559
539
 
560
540
  ##
561
- # Constructs a check_box from the given options
562
- #
563
- # @macro text_field
541
+ # Constructs a check_box from the given options.
564
542
  #
565
543
  # @example
566
544
  # check_box_tag :remember_me, :value => 'Yes'
567
545
  #
568
- # @api public
569
546
  def check_box_tag(name, options={})
570
547
  options.reverse_merge!(:name => name, :value => '1')
571
548
  input_tag(:checkbox, options)
572
549
  end
573
550
 
574
551
  ##
575
- # Constructs a radio_button from the given options
576
- #
577
- # @macro text_field
552
+ # Constructs a radio_button from the given options.
578
553
  #
579
554
  # @example
580
555
  # radio_button_tag :remember_me, :value => 'true'
581
556
  #
582
- # @api public
583
557
  def radio_button_tag(name, options={})
584
558
  options.reverse_merge!(:name => name)
585
559
  input_tag(:radio, options)
586
560
  end
587
561
 
588
562
  ##
589
- # Constructs a file field input from the given options
590
- #
591
- # @macro text_field
563
+ # Constructs a file field input from the given options.
592
564
  #
593
565
  # @example
594
566
  # file_field_tag :photo, :class => 'long'
@@ -601,7 +573,7 @@ module Padrino
601
573
  end
602
574
 
603
575
  ##
604
- # Constructs a select from the given options
576
+ # Constructs a select from the given options.
605
577
  #
606
578
  # @example
607
579
  # options = [['caption', 'value'], ['Green', 'green1'], ['Blue', 'blue1'], ['Black', "black1"]]
@@ -638,9 +610,8 @@ module Padrino
638
610
  # @option options [Boolean] :multiple (false)
639
611
  # Allow multiple options to be selected at once.
640
612
  #
641
- # @return [String] The html input field based on the +options+ specified
613
+ # @return [String] The HTML input field based on the +options+ specified.
642
614
  #
643
- # @api public
644
615
  def select_tag(name, options={})
645
616
  options.reverse_merge!(:name => name)
646
617
  collection, fields = options.delete(:collection), options.delete(:fields)
@@ -657,7 +628,7 @@ module Padrino
657
628
  end
658
629
 
659
630
  ##
660
- # Constructs a button input from the given options
631
+ # Constructs a button input from the given options.
661
632
  #
662
633
  # @param [String] caption
663
634
  # The caption for the button.
@@ -669,14 +640,13 @@ module Padrino
669
640
  # @example
670
641
  # button_tag "Cancel", :class => 'clear'
671
642
  #
672
- # @api public
673
643
  def button_tag(caption, options = {})
674
644
  options.reverse_merge!(:value => caption)
675
645
  input_tag(:button, options)
676
646
  end
677
647
 
678
648
  ##
679
- # Constructs a submit button from the given options
649
+ # Constructs a submit button from the given options.
680
650
  #
681
651
  # @param [String] caption (defaults to: +Submit+)
682
652
  # The caption for the submit button.
@@ -689,7 +659,6 @@ module Padrino
689
659
  # submit_tag "Create", :class => 'success'
690
660
  # submit_tag :class => 'btn'
691
661
  #
692
- # @api public
693
662
  def submit_tag(*args)
694
663
  options = args[-1].is_a?(Hash) ? args.pop : {}
695
664
  caption = args.length >= 1 ? args.shift : "Submit"
@@ -697,7 +666,8 @@ module Padrino
697
666
  input_tag(:submit, options)
698
667
  end
699
668
 
700
- # Constructs a submit button from the given options
669
+ ##
670
+ # Constructs a submit button from the given options.
701
671
  #
702
672
  # @param [String] source
703
673
  # The source image path for the button.
@@ -709,12 +679,12 @@ module Padrino
709
679
  # @example
710
680
  # submit_tag "Create", :class => 'success'
711
681
  #
712
- # @api public
713
682
  def image_submit_tag(source, options={})
714
683
  options.reverse_merge!(:src => image_path(source))
715
684
  input_tag(:image, options)
716
685
  end
717
686
 
687
+ ##
718
688
  # Constructs a hidden field containing a CSRF token.
719
689
  #
720
690
  # @param [String] token
@@ -725,17 +695,28 @@ module Padrino
725
695
  # @example
726
696
  # csrf_token_field
727
697
  #
728
- # @api public
729
698
  def csrf_token_field(token = nil)
730
- if defined? session
731
- token ||= (session[:csrf] ||= SecureRandom.hex(32))
732
- end
699
+ hidden_field_tag csrf_param, :value => csrf_token
700
+ end
733
701
 
734
- hidden_field_tag :authenticity_token, :value => token
702
+ ##
703
+ # Constructs meta tags `csrf-param` and `csrf-token` with the name of the
704
+ # cross-site request forgery protection parameter and token, respectively.
705
+ #
706
+ # @return [String] The meta tags with the CSRF token and the param your app expects it in.
707
+ #
708
+ # @example
709
+ # csrf_meta_tags
710
+ #
711
+ def csrf_meta_tags
712
+ if is_protected_from_csrf?
713
+ meta_tag(csrf_param, :name => 'csrf-param') <<
714
+ meta_tag(csrf_token, :name => 'csrf-token')
715
+ end
735
716
  end
736
717
 
737
718
  ##
738
- # Creates a form containing a single button that submits to the url.
719
+ # Creates a form containing a single button that submits to the URL.
739
720
  #
740
721
  # @overload button_to(name, url, options={})
741
722
  # @param [String] caption The text caption.
@@ -752,6 +733,8 @@ module Padrino
752
733
  # Instructs ujs handler to handle the submit as ajax.
753
734
  # @option options [Symbol] :method
754
735
  # Instructs ujs handler to use different http method (i.e :post, :delete).
736
+ # @option options [Hash] :submit_options
737
+ # Hash of any options, that you want to pass to submit_tag (i.e :id, :class)
755
738
  #
756
739
  # @return [String] Form and button html with specified +options+.
757
740
  #
@@ -763,22 +746,22 @@ module Padrino
763
746
  # # <input type="submit" value="Delete" />
764
747
  # # </form>
765
748
  #
766
- # @api public
767
749
  def button_to(*args, &block)
768
750
  name, url = args[0], args[1]
769
751
  options = args.extract_options!
770
752
  options['data-remote'] = 'true' if options.delete(:remote)
753
+ submit_options = options.delete(:submit_options) || {}
771
754
  if block_given?
772
755
  form_tag(url, options, &block)
773
756
  else
774
757
  form_tag(url, options.merge!(:not_concat => true)) do
775
- submit_tag(name)
758
+ submit_tag(name, submit_options)
776
759
  end
777
760
  end
778
761
  end
779
762
 
780
763
  ##
781
- # Constructs a range tag from the given options
764
+ # Constructs a range tag from the given options.
782
765
  #
783
766
  # @example
784
767
  # range_field_tag('ranger_with_min_max', :min => 1, :max => 50)
@@ -789,14 +772,13 @@ module Padrino
789
772
  # @param [Hash] options
790
773
  # The html options for the range field.
791
774
  # @option options [Integer] :min
792
- # The min range of the range field
775
+ # The min range of the range field.
793
776
  # @option options [Integer] :max
794
- # The max range of the range field
777
+ # The max range of the range field.
795
778
  # @option options [range] :range
796
- # The range, in lieu of :min and :max. See examples for details
779
+ # The range, in lieu of :min and :max. See examples for details.
797
780
  # @return [String] The html range field
798
781
  #
799
- # @api public
800
782
  def range_field_tag(name, options = {})
801
783
  options.reverse_merge!(:name => name)
802
784
  if range = options.delete(:range)
@@ -807,116 +789,131 @@ module Padrino
807
789
 
808
790
  protected
809
791
 
810
- ##
811
- # Returns an array of option items for a select field based on the given collection
812
- # fields is an array containing the fields to display from each item in the collection
813
- #
814
- def options_from_collection(collection, fields)
815
- collection.map { |item| [ item.send(fields.first), item.send(fields.last) ] }
816
- end
792
+ ##
793
+ # Returns an array of option items for a select field based on the given collection.
794
+ #
795
+ # @param [Array] fields
796
+ # fields is an array containing the fields to display from each item in the collection.
797
+ #
798
+ def options_from_collection(collection, fields)
799
+ collection.map { |item| [ item.send(fields.first), item.send(fields.last) ] }
800
+ end
817
801
 
818
- #
819
- # Returns the options tags for a select based on the given option items
820
- #
821
- def options_for_select(option_items, selected_value=nil)
822
- return [] if option_items.blank?
823
- option_items.map do |caption, value, disabled|
824
- value ||= caption
825
- disabled ||= false
826
- content_tag(:option, caption, :value => value, :selected => option_is_selected?(value, caption, selected_value), :disabled => disabled)
827
- end
802
+ ##
803
+ # Returns the options tags for a select based on the given option items.
804
+ #
805
+ def options_for_select(option_items, selected_value=nil)
806
+ 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)
828
811
  end
812
+ end
829
813
 
830
- #
831
- # Returns the optgroups with options tags for a select based on the given :grouped_options items
832
- #
833
- def grouped_options_for_select(collection, selected=nil, prompt=false)
834
- if collection.is_a?(Hash)
835
- collection.map do |key, value|
836
- # Hash format:
837
- # {:first => [1,2,3], :second => [4,5,6]}
838
- # or:
839
- # {:first => [[1,2,3], {:disabled => true}], :second => [4,5,6]}
840
- attributes_hash = value.last.is_a?(Hash) ? value.pop : nil
841
- disabled ||= attributes_hash && attributes_hash.include?(:disabled) ? attributes_hash[:disabled] : false
842
- content_tag :optgroup, options_for_select(value, selected), :label => key, :disabled => disabled
843
- end
844
- elsif collection.is_a?(Array)
845
- # Array format:
846
- # ["Option Label", [:option1, :option2, ...]]
814
+ ##
815
+ # Returns the optgroups with options tags for a select based on the given :grouped_options items.
816
+ #
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]}
847
822
  # or:
848
- # ["Option Label", [:option1, :option2, ...], true]
849
- # the last item tells if it is disabled or not. This is keeps it backwards compatible.
850
- collection.map do |optgroup|
851
- disabled ||= optgroup.count > 2 ? optgroup.pop : false
852
- content_tag :optgroup, options_for_select(optgroup.last, selected), :label => optgroup.first, :disabled => disabled
853
- end
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
854
827
  end
855
- end
856
-
857
- #
858
- # Returns the blank option serving as a prompt if passed
859
- #
860
- def blank_option(prompt)
861
- return unless prompt
862
- case prompt
863
- when String then content_tag(:option, prompt, :value => '')
864
- when Array then content_tag(:option, prompt.first, :value => prompt.last)
865
- else content_tag(:option, '', :value => '')
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
866
837
  end
867
838
  end
839
+ end
868
840
 
869
- private
870
- ##
871
- # Returns the FormBuilder class to use based on all available setting sources
872
- # If explicitly defined, returns that, otherwise returns defaults.
873
- #
874
- # @example
875
- # configured_form_builder_class(nil) => StandardFormBuilder
876
- #
877
- # @api private
878
- def configured_form_builder_class(explicit_builder=nil)
879
- default_builder = self.respond_to?(:settings) && self.settings.default_builder
880
- configured_builder = explicit_builder || default_builder || 'StandardFormBuilder'
881
- configured_builder = "Padrino::Helpers::FormBuilder::#{configured_builder}".constantize if configured_builder.is_a?(String)
882
- configured_builder
841
+ ##
842
+ # Returns the blank option serving as a prompt if passed.
843
+ #
844
+ def blank_option(prompt)
845
+ return unless prompt
846
+ 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 => '')
883
850
  end
851
+ end
884
852
 
885
- ##
886
- # Returns an initialized builder instance for the given object and settings
887
- #
888
- # @example
889
- # builder_instance(@account, :nested => { ... }) => <FormBuilder>
890
- #
891
- # @api private
892
- def builder_instance(object, settings={})
893
- builder_class = configured_form_builder_class(settings.delete(:builder))
894
- builder_class.new(self, object, settings)
895
- end
853
+ ##
854
+ # Returns whether the application is being protected from CSRF. Defaults to true.
855
+ #
856
+ def is_protected_from_csrf?
857
+ defined?(settings) ? settings.protect_from_csrf : true
858
+ end
896
859
 
897
- ##
898
- # Returns whether the option should be selected or not
899
- #
900
- # @example
901
- # option_is_selected?("red", "Red", ["red", "blue"]) => true
902
- # option_is_selected?("red", "Red", ["green", "blue"]) => false
903
- #
904
- # @api private
905
- def option_is_selected?(value, caption, selected_values)
906
- Array(selected_values).any? do |selected|
907
- [value.to_s, caption.to_s].include?(selected.to_s)
908
- end
909
- end
860
+ ##
861
+ # Returns the current CSRF token (based on the session). If it doesn't exist,
862
+ # it will create one and assign it to the session's `csrf` key.
863
+ #
864
+ def csrf_token
865
+ session[:csrf] ||= SecureRandom.hex(32) if defined?(session)
866
+ end
867
+
868
+ ##
869
+ # Returns the param/field name in which your CSRF token should be expected by your
870
+ # controllers. Defaults to `authenticity_token`.
871
+ #
872
+ # Set this in your application with `set :csrf_param, :something_else`.
873
+ #
874
+ def csrf_param
875
+ defined?(settings) && settings.respond_to?(:csrf_param) ?
876
+ settings.csrf_param : :authenticity_token
877
+ end
878
+
879
+ private
880
+ ##
881
+ # Returns the FormBuilder class to use based on all available setting sources
882
+ # If explicitly defined, returns that, otherwise returns defaults.
883
+ #
884
+ # @example
885
+ # configured_form_builder_class(nil) => StandardFormBuilder
886
+ #
887
+ def configured_form_builder_class(explicit_builder=nil)
888
+ default_builder = self.respond_to?(:settings) && self.settings.default_builder
889
+ configured_builder = explicit_builder || default_builder || 'StandardFormBuilder'
890
+ configured_builder = "Padrino::Helpers::FormBuilder::#{configured_builder}".constantize if configured_builder.is_a?(String)
891
+ configured_builder
892
+ end
893
+
894
+ ##
895
+ # Returns an initialized builder instance for the given object and settings.
896
+ #
897
+ # @example
898
+ # builder_instance(@account, :nested => { ... }) => <FormBuilder>
899
+ #
900
+ def builder_instance(object, settings={})
901
+ builder_class = configured_form_builder_class(settings.delete(:builder))
902
+ builder_class.new(self, object, settings)
903
+ end
910
904
 
911
- ##
912
- # Returns whether the application is being protected from csrf
913
- #
914
- def is_protected_from_csrf?
915
- return true unless defined? app
916
- return true unless app.respond_to?(:protect_from_csrf)
917
- return true if app.protect_from_csrf == nil
918
- app.protect_from_csrf
905
+ ##
906
+ # Returns whether the option should be selected or not.
907
+ #
908
+ # @example
909
+ # option_is_selected?("red", "Red", ["red", "blue"]) => true
910
+ # option_is_selected?("red", "Red", ["green", "blue"]) => false
911
+ #
912
+ def option_is_selected?(value, caption, selected_values)
913
+ Array(selected_values).any? do |selected|
914
+ [value.to_s, caption.to_s].include?(selected.to_s)
919
915
  end
920
- end # FormHelpers
921
- end # Helpers
922
- end # Padrino
916
+ end
917
+ end
918
+ end
919
+ end