forme 1.9.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +70 -0
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +396 -202
  5. data/lib/forme/bs3.rb +19 -5
  6. data/lib/forme/erb.rb +18 -16
  7. data/lib/forme/form.rb +151 -118
  8. data/lib/forme/input.rb +1 -1
  9. data/lib/forme/rails.rb +41 -72
  10. data/lib/forme/raw.rb +2 -2
  11. data/lib/forme/sinatra.rb +6 -2
  12. data/lib/forme/tag.rb +3 -12
  13. data/lib/forme/template.rb +118 -0
  14. data/lib/forme/transformers/error_handler.rb +46 -1
  15. data/lib/forme/transformers/formatter.rb +36 -35
  16. data/lib/forme/transformers/helper.rb +0 -1
  17. data/lib/forme/transformers/inputs_wrapper.rb +6 -6
  18. data/lib/forme/transformers/labeler.rb +19 -0
  19. data/lib/forme/transformers/wrapper.rb +1 -1
  20. data/lib/forme/version.rb +2 -2
  21. data/lib/forme.rb +15 -2
  22. data/lib/roda/plugins/forme.rb +1 -1
  23. data/lib/roda/plugins/forme_erubi_capture.rb +62 -0
  24. data/lib/roda/plugins/forme_route_csrf.rb +16 -20
  25. data/lib/roda/plugins/forme_set.rb +177 -0
  26. data/lib/sequel/plugins/forme.rb +42 -55
  27. data/lib/sequel/plugins/forme_i18n.rb +3 -1
  28. data/lib/sequel/plugins/forme_set.rb +50 -28
  29. data/spec/all.rb +1 -1
  30. data/spec/bs3_reference_spec.rb +18 -18
  31. data/spec/bs3_sequel_plugin_spec.rb +7 -7
  32. data/spec/bs3_spec.rb +23 -11
  33. data/spec/erb_helper.rb +73 -58
  34. data/spec/erubi_capture_helper.rb +202 -0
  35. data/spec/forme_spec.rb +80 -29
  36. data/spec/rails_integration_spec.rb +47 -24
  37. data/spec/roda_integration_spec.rb +459 -48
  38. data/spec/sequel_helper.rb +0 -1
  39. data/spec/sequel_i18n_helper.rb +1 -1
  40. data/spec/sequel_i18n_plugin_spec.rb +3 -2
  41. data/spec/sequel_plugin_spec.rb +25 -8
  42. data/spec/sequel_set_plugin_spec.rb +10 -3
  43. data/spec/shared_erb_specs.rb +75 -0
  44. data/spec/sinatra_integration_spec.rb +5 -6
  45. data/spec/spec_helper.rb +23 -5
  46. metadata +30 -8
  47. data/lib/forme/erb_form.rb +0 -74
data/lib/forme/sinatra.rb CHANGED
@@ -1,6 +1,10 @@
1
1
  # frozen-string-literal: true
2
2
 
3
- require 'forme/erb'
3
+ if RUBY_VERSION >= '2'
4
+ warn('forme/sinatra and Forme::Sinatra::ERB are deprecated and will be removed in a future version, switch to forme/erb and Forme::ERB::Helper', :uplevel=>1)
5
+ end
6
+
7
+ require_relative 'erb'
4
8
 
5
9
  module Forme
6
10
  # For backwards compatibility only. New code should
@@ -11,7 +15,7 @@ module Forme
11
15
  module Sinatra
12
16
  ERB = Forme::ERB::Helper
13
17
  Erubis = ERB
14
- Form = Forme::ERB::Form
18
+ Form = Forme::Template::Form
15
19
  HIDDEN_TAGS = Forme::ERB::HIDDEN_TAGS
16
20
  end
17
21
  end
data/lib/forme/tag.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  module Forme
4
- # Low level abstract tag form, where each instance represents a
5
- # html tag with attributes and children.
4
+ # Low level abstract tag form, where each instance represents an
5
+ # HTML tag with attributes and children.
6
6
  class Tag
7
7
  # The +Form+ object related to the receiver.
8
8
  attr_reader :form
@@ -23,15 +23,6 @@ module Forme
23
23
  @children = parse_children(children)
24
24
  end
25
25
 
26
- # Adds a child to the array of receiver's children.
27
- def <<(child)
28
- if children
29
- children << child
30
- else
31
- @children = [child]
32
- end
33
- end
34
-
35
26
  # Create a new +Tag+ instance with the given arguments and block
36
27
  # related to the receiver's +form+.
37
28
  def tag(*a, &block)
@@ -40,7 +31,7 @@ module Forme
40
31
 
41
32
  # Return a string containing the serialized content of the receiver.
42
33
  def to_s
43
- form.raw_output(Forme.transform(:serializer, @opts, @form.opts, self))
34
+ Forme.transform(:serializer, @opts, @form.opts, self)
44
35
  end
45
36
 
46
37
  private
@@ -0,0 +1,118 @@
1
+ # frozen-string-literal: true
2
+
3
+ require_relative '../forme'
4
+
5
+ module Forme
6
+ module Template
7
+ class Form
8
+ def initialize(form, scope)
9
+ @form = form
10
+ @scope = scope
11
+ end
12
+
13
+ # Delegate calls by default to the wrapped form
14
+ def method_missing(*a, &block)
15
+ @form.public_send(*a, &block)
16
+ end
17
+
18
+ # If a block is given to inputs, tag, or subform,
19
+ # emit the already generated HTML for the form before yielding
20
+ # to the block, and after returning, emit any HTML generated
21
+ # after returning from the block.
22
+ %w'inputs tag subform'.each do |meth|
23
+ class_eval(<<-END, __FILE__, __LINE__+1)
24
+ def #{meth}(*a, &block)
25
+ return @form.#{meth}(*a) unless block
26
+
27
+ buffer = @form.to_s
28
+ offset = buffer.length
29
+ @form.#{meth}(*a) do
30
+ emit(buffer[offset, buffer.length])
31
+ yield self
32
+ offset = buffer.length
33
+ end
34
+ emit(buffer[offset, buffer.length])
35
+
36
+ nil
37
+ end
38
+ END
39
+ end
40
+
41
+ # Serialize the tag and inject it into the output.
42
+ def emit(tag)
43
+ return unless output = output()
44
+ output << tag
45
+ end
46
+
47
+ private
48
+
49
+ def output
50
+ @scope.instance_variable_get(:@_out_buf)
51
+ end
52
+ end
53
+
54
+ # This is the module used to add the Forme integration
55
+ # to ERB.
56
+ module Helper
57
+ # Create a +Form+ object tied to the current output buffer,
58
+ # using the standard ERB hidden tags.
59
+ def form(obj=nil, attr={}, opts={}, &block)
60
+ if obj.is_a?(Hash)
61
+ attribs = obj
62
+ options = attr = attr.dup
63
+ else
64
+ attribs = attr
65
+ options = opts = opts.dup
66
+ end
67
+
68
+ _forme_form_options(obj, attribs, options)
69
+ _forme_form(obj, attr, opts, &block)
70
+ end
71
+
72
+ private
73
+
74
+ def _forme_form(obj, attr, opts, &block)
75
+ if block_given?
76
+ erb_form = buffer = offset = nil
77
+ block = proc do
78
+ wrapped_form = erb_form.instance_variable_get(:@form)
79
+ buffer = wrapped_form.to_s
80
+ offset = buffer.length
81
+ erb_form.emit(buffer[0, buffer.length])
82
+ yield erb_form
83
+ offset = buffer.length
84
+ end
85
+
86
+ f, attr, block = _forme_wrapped_form_class.form_args(obj, attr, opts, &block)
87
+ erb_form = _forme_form_class.new(f, self)
88
+ erb_form.form(attr, &block)
89
+ erb_form.emit(buffer[offset, buffer.length])
90
+ else
91
+ _forme_wrapped_form_class.form(obj, attr, opts, &block)
92
+ end
93
+ end
94
+
95
+ def _forme_wrapped_form_class
96
+ ::Forme::Form
97
+ end
98
+
99
+ # The class to use for forms
100
+ def _forme_form_class
101
+ Form
102
+ end
103
+
104
+ # The options to use for forms. Any changes should mutate this hash to set options.
105
+ def _forme_form_options(obj, attr, opts)
106
+ if hidden_tags = _forme_form_hidden_tags
107
+ opts[:hidden_tags] ||= []
108
+ opts[:hidden_tags] += hidden_tags
109
+ end
110
+ opts[:hidden_tags_uplevel] = 1
111
+ end
112
+
113
+ def _forme_form_hidden_tags
114
+ nil
115
+ end
116
+ end
117
+ end
118
+ end
@@ -11,10 +11,55 @@ module Forme
11
11
 
12
12
  # Return tag with error message span tag after it.
13
13
  def call(tag, input)
14
+ [tag, error_tag(input)]
15
+ end
16
+
17
+ private
18
+
19
+ def error_tag(input)
14
20
  attr = input.opts[:error_attr]
15
21
  attr = attr ? attr.dup : {}
16
22
  Forme.attr_classes(attr, 'error_message')
17
- [tag, input.tag(:span, attr, input.opts[:error])]
23
+
24
+ if id = input.opts[:error_id]
25
+ unless attr['id'] || attr[:id]
26
+ attr['id'] = id
27
+ end
28
+ end
29
+
30
+ input.tag(:span, attr, input.opts[:error])
31
+ end
32
+ end
33
+
34
+ class ErrorHandler::Set < ErrorHandler
35
+ Forme.register_transformer(:error_handler, :set, new)
36
+
37
+ def call(tag, input)
38
+ return super unless last_input = input.opts[:last_input]
39
+
40
+ last_input.opts[:error] = input.opts[:error]
41
+ last_input.opts[:error_attr] = input.opts[:error_attr] if input.opts[:error_attr]
42
+ last_input.opts[:error_handler] = :default
43
+
44
+ tag
45
+ end
46
+ end
47
+
48
+ class ErrorHandler::AfterLegend < ErrorHandler
49
+ Forme.register_transformer(:error_handler, :after_legend, new)
50
+
51
+ def call(tag, input)
52
+ return super unless tag.is_a?(Array)
53
+ return super unless tag.first.is_a?(Tag)
54
+ return super unless tag.first.type == :legend
55
+
56
+ first_input = input.opts[:first_input]
57
+ attr = first_input.opts[:attr] ||= {}
58
+ Forme.attr_classes(attr, 'error')
59
+ attr['aria-invalid'] = 'true'
60
+ attr['aria-describedby'] = input.opts[:error_id] = "#{first_input.opts[:id]}_error_message"
61
+
62
+ tag.insert(1, error_tag(input))
18
63
  end
19
64
  end
20
65
  end
@@ -61,7 +61,6 @@ module Forme
61
61
  @attr = attr ? attr.dup : {}
62
62
  @opts = input.opts
63
63
  normalize_options
64
-
65
64
  tag = if html = input.opts[:html]
66
65
  html = html.call(input) if html.respond_to?(:call)
67
66
  form.raw(html)
@@ -158,9 +157,13 @@ module Forme
158
157
  ops = ops.merge(@opts[:select_options]) if @opts[:select_options]
159
158
  first_input = true
160
159
  format = DATE_SELECT_FORMAT
160
+ @opts[:select_labels] ||= {}
161
161
  order.map do |x|
162
162
  next x if x.is_a?(String)
163
- opts = @opts.merge(:label=>nil, :wrapper=>nil, :error=>nil, :name=>"#{name}[#{x}]", :value=>values[x], :options=>ops[x].map{|y| [sprintf(format, y), y]})
163
+ options = ops[x].map do |value, text|
164
+ [text || sprintf(format, value), value]
165
+ end
166
+ opts = @opts.merge(:label=>@opts[:select_labels][x], :wrapper=>nil, :error=>nil, :name=>"#{name}[#{x}]", :value=>values[x], :options=>options)
164
167
  opts[:id] = if first_input
165
168
  first_input = false
166
169
  id
@@ -221,23 +224,22 @@ module Forme
221
224
  key = @opts[:key]
222
225
  name = @opts[:name]
223
226
  id = @opts[:id]
224
- if @opts[:error]
225
- @opts[:set_error] = @opts.delete(:error)
226
- end
227
- if @opts[:label]
228
- @opts[:set_label] = @opts.delete(:label)
229
- end
227
+ @opts[:labeler] ||= :span
228
+ @opts[:error_handler] ||= :set
230
229
 
231
230
  tag_wrapper = Forme.transformer(:tag_wrapper, @opts.delete(:tag_wrapper), @input.form_opts) || :default
232
231
  tag_labeler = Forme.transformer(:labeler, @opts.delete(:tag_labeler), @input.form_opts) || :default
233
232
  wrapper = @opts.fetch(:wrapper){@opts[:wrapper] = @input.form_opts[:set_wrapper] || @input.form_opts[:wrapper]}
234
233
  wrapper = Forme.transformer(:wrapper, wrapper)
234
+ tag_label_attr = @opts[:tag_label_attr] || @opts[:label_attr]
235
235
 
236
- tags = process_select_optgroups(:_format_set_optgroup) do |label, value, sel, attrs|
236
+ first_input = nil
237
+ last_input = nil
238
+ ret = process_select_optgroups(:_format_set_optgroup) do |label, value, sel, attrs|
237
239
  value = label if value.nil?
238
240
  label_attr = {:class=>:option}
239
- label_attr.merge!(@opts[:label_attr]) if @opts[:label_attr]
240
- r_opts = attrs.merge(tag_attrs).merge(:label=>label||value, :label_attr=>label_attr, :wrapper=>tag_wrapper, :labeler=>tag_labeler)
241
+ label_attr.merge!(tag_label_attr) if tag_label_attr
242
+ r_opts = attrs.merge(tag_attrs).merge(:label=>label||value, :label_attr=>label_attr, :wrapper=>tag_wrapper, :labeler=>tag_labeler, :error=>nil, :error_attr=>nil)
241
243
  if r_opts[:value].nil?
242
244
  r_opts[:value] = value unless value.nil?
243
245
  end
@@ -255,31 +257,15 @@ module Forme
255
257
  r_opts[:key_id] ||= value
256
258
  end
257
259
 
258
- form._input(type, r_opts)
260
+ input = form._input(type, r_opts)
261
+ first_input ||= input
262
+ last_input = input
259
263
  end
260
264
 
261
- if @opts[:set_error]
262
- _add_set_error(tags)
263
- end
264
-
265
- tags.unshift(set_label) if @opts[:set_label]
266
-
267
- tags
268
- end
269
-
270
- def set_label
271
- form._tag(:span, {:class=>:label}, @opts[:set_label])
272
- end
265
+ @opts[:first_input] = first_input
266
+ @opts[:last_input] = last_input
273
267
 
274
- def _add_set_error(tags)
275
- if (last_input = tags.last) && last_input.is_a?(Input)
276
- last_input.opts[:error] = @opts[:set_error]
277
- last_input.opts[:error_attr] = @opts[:error_attr] if @opts[:error_attr]
278
- else
279
- attr = @opts[:error_attr] || {}
280
- Forme.attr_classes(attr, 'error_message')
281
- tags << form._tag(:span, attr, [@opts[:set_error]])
282
- end
268
+ ret
283
269
  end
284
270
 
285
271
  # Formats a textarea. Respects the following options:
@@ -321,7 +307,19 @@ module Forme
321
307
  handle_errors_option
322
308
 
323
309
  Forme.attr_classes(@attr, @opts[:class]) if @opts.has_key?(:class)
324
- Forme.attr_classes(@attr, 'error') if @opts[:error]
310
+
311
+ if @opts[:error]
312
+ Forme.attr_classes(@attr, 'error')
313
+ @attr["aria-invalid"] = "true"
314
+ if @opts.fetch(:error_handler, true)
315
+ unless @opts[:error_id]
316
+ if id = @attr[:id] || @attr['id']
317
+ error_id = @attr['aria-describedby'] ||= "#{id}_error_message"
318
+ @opts[:error_id] = error_id
319
+ end
320
+ end
321
+ end
322
+ end
325
323
 
326
324
  if data = opts[:data]
327
325
  data.each do |k, v|
@@ -540,8 +538,11 @@ module Forme
540
538
  end
541
539
 
542
540
  # Use a span with text instead of an input field.
541
+ # For hidden inputs, do not show anything
543
542
  def _format_input(type)
544
- tag(:span, {'class'=>'readonly-text'}, @attr[:value])
543
+ unless type.to_s == 'hidden'
544
+ tag(:span, {'class'=>'readonly-text'}, @attr[:value])
545
+ end
545
546
  end
546
547
 
547
548
  # Disabled radio button inputs.
@@ -16,4 +16,3 @@ module Forme
16
16
  end
17
17
  end
18
18
  end
19
-
@@ -10,16 +10,16 @@ module Forme
10
10
  # Wrap the inputs in a <fieldset>. If the :legend
11
11
  # option is given, add a <legend> tag as the first
12
12
  # child of the fieldset.
13
- def call(form, opts)
13
+ def call(form, opts, &block)
14
14
  attr = opts[:attr] ? opts[:attr].dup : {}
15
15
  Forme.attr_classes(attr, 'inputs')
16
16
  if legend = opts[:legend]
17
17
  form.tag(:fieldset, attr) do
18
- form.emit(form.tag(:legend, opts[:legend_attr], legend))
18
+ form.tag(:legend, opts[:legend_attr], legend)
19
19
  yield
20
20
  end
21
21
  else
22
- form.tag(:fieldset, attr, &Proc.new)
22
+ form.tag(:fieldset, attr, &block)
23
23
  end
24
24
  end
25
25
  end
@@ -32,7 +32,7 @@ module Forme
32
32
 
33
33
  # Wrap the inputs in a <fieldset> and a <ol> tag.
34
34
  def call(form, opts)
35
- super(form, opts){form.tag_(:ol){yield}}
35
+ super(form, opts){form.tag(:ol){yield}}
36
36
  end
37
37
  end
38
38
 
@@ -83,12 +83,12 @@ module Forme
83
83
  attr = opts[:attr] ? opts[:attr].dup : {}
84
84
  form.tag(:table, attr) do
85
85
  if legend = opts[:legend]
86
- form.emit(form.tag(:caption, opts[:legend_attr], legend))
86
+ form.tag(:caption, opts[:legend_attr], legend)
87
87
  end
88
88
 
89
89
  if (labels = opts[:labels]) && !labels.empty?
90
90
  form.tag(:thead) do
91
- form.emit(form.tag(:tr, {}, labels.map{|l| form._tag(:th, {}, l)}))
91
+ form.tag(:tr, {}, labels.map{|l| form._tag(:th, {}, l)})
92
92
  end
93
93
  end
94
94
 
@@ -77,4 +77,23 @@ module Forme
77
77
  t
78
78
  end
79
79
  end
80
+
81
+ class Labeler::Span
82
+ Forme.register_transformer(:labeler, :span, new)
83
+
84
+ def call(tag, input)
85
+ label_attr = input.opts[:label_attr]
86
+ label_attr = label_attr ? label_attr.dup : {}
87
+ Forme.attr_classes(label_attr, "label")
88
+ [input.tag(:span, label_attr, input.opts[:label]), tag]
89
+ end
90
+ end
91
+
92
+ class Labeler::Legend
93
+ Forme.register_transformer(:labeler, :legend, new)
94
+
95
+ def call(tag, input)
96
+ [input.tag(:legend, input.opts[:label_attr], input.opts[:label]), tag]
97
+ end
98
+ end
80
99
  end
@@ -23,7 +23,7 @@ module Forme
23
23
  input.tag(@type, input.opts[:wrapper_attr], super)
24
24
  end
25
25
 
26
- [:li, :p, :div, :span, :td].each do |x|
26
+ [:li, :p, :div, :span, :td, :fieldset].each do |x|
27
27
  Forme.register_transformer(:wrapper, x, new(x))
28
28
  end
29
29
  end
data/lib/forme/version.rb CHANGED
@@ -3,10 +3,10 @@
3
3
  module Forme
4
4
  # The major version of Forme, updated only for major changes that are
5
5
  # likely to require modification to apps using Forme.
6
- MAJOR = 1
6
+ MAJOR = 2
7
7
 
8
8
  # The minor version of Forme, updated for new feature releases of Forme.
9
- MINOR = 9
9
+ MINOR = 0
10
10
 
11
11
  # The patch version of Forme, updated only for bug fixes from the last
12
12
  # feature release.
data/lib/forme.rb CHANGED
@@ -10,6 +10,7 @@ module Forme
10
10
 
11
11
  begin
12
12
  require 'cgi/escape'
13
+ # :nocov:
13
14
  unless CGI.respond_to?(:escapeHTML) # work around for JRuby 9.1
14
15
  CGI = Object.new
15
16
  CGI.extend(defined?(::CGI::Escape) ? ::CGI::Escape : ::CGI::Util)
@@ -32,6 +33,7 @@ module Forme
32
33
  end
33
34
  end
34
35
  end
36
+ # :nocov:
35
37
 
36
38
  @default_add_blank_prompt = nil
37
39
  @default_config = :default
@@ -160,5 +162,16 @@ module Forme
160
162
  end
161
163
  end
162
164
 
163
- %w'form input tag raw version'.each{|f| require File.expand_path("../forme/#{f}", __FILE__)}
164
- %w'error_handler formatter helper inputs_wrapper labeler serializer wrapper'.each{|f| require File.expand_path("../forme/transformers/#{f}", __FILE__)}
165
+ require_relative 'forme/form'
166
+ require_relative 'forme/input'
167
+ require_relative 'forme/tag'
168
+ require_relative 'forme/raw'
169
+ require_relative 'forme/version'
170
+
171
+ require_relative 'forme/transformers/error_handler'
172
+ require_relative 'forme/transformers/formatter'
173
+ require_relative 'forme/transformers/helper'
174
+ require_relative 'forme/transformers/inputs_wrapper'
175
+ require_relative 'forme/transformers/labeler'
176
+ require_relative 'forme/transformers/serializer'
177
+ require_relative 'forme/transformers/wrapper'
@@ -1,6 +1,6 @@
1
1
  # frozen-string-literal: true
2
2
 
3
- require 'forme/erb'
3
+ require_relative '../../forme/erb'
4
4
 
5
5
  class Roda
6
6
  module RodaPlugins
@@ -0,0 +1,62 @@
1
+ # frozen-string-literal: true
2
+
3
+ require_relative '../../forme/template'
4
+
5
+ class Roda
6
+ module RodaPlugins
7
+ module FormeErubiCapture
8
+ def self.load_dependencies(app)
9
+ app.plugin :forme_route_csrf
10
+ app.plugin :capture_erb
11
+ app.plugin :inject_erb
12
+ end
13
+
14
+ class Form < ::Forme::Template::Form
15
+ %w'inputs tag subform'.each do |meth|
16
+ class_eval(<<-END, __FILE__, __LINE__+1)
17
+ def #{meth}(*)
18
+ if block_given?
19
+ @scope.capture_erb do
20
+ super
21
+ @scope.instance_variable_get(@scope.render_opts[:template_opts][:outvar])
22
+ end
23
+ else
24
+ super
25
+ end
26
+ end
27
+ END
28
+ end
29
+
30
+ def emit(tag)
31
+ @scope.inject_erb(tag)
32
+ end
33
+ end
34
+
35
+ module InstanceMethods
36
+ def form(*)
37
+ if block_given?
38
+ capture_erb do
39
+ super
40
+ instance_variable_get(render_opts[:template_opts][:outvar])
41
+ end
42
+ else
43
+ super
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def _forme_form_class
50
+ Form
51
+ end
52
+
53
+ def _forme_form_options(obj, attr, opts)
54
+ super
55
+ opts[:hidden_tags_uplevel] = 2
56
+ end
57
+ end
58
+ end
59
+
60
+ register_plugin(:forme_erubi_capture, FormeErubiCapture)
61
+ end
62
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen-string-literal: true
2
2
 
3
- require 'forme/erb_form'
3
+ require_relative '../../forme/template'
4
4
 
5
5
  class Roda
6
6
  module RodaPlugins
@@ -13,21 +13,18 @@ class Roda
13
13
  end
14
14
 
15
15
  module InstanceMethods
16
- # Create a +Form+ object tied to the current output buffer,
17
- # using the standard ERB hidden tags.
18
- def form(obj=nil, attr={}, opts={}, &block)
19
- if obj.is_a?(Hash)
20
- attribs = obj
21
- options = attr = attr.dup
22
- else
23
- attribs = attr
24
- options = opts = opts.dup
25
- end
16
+ include ::Forme::Template::Helper
17
+
18
+ private
19
+
20
+ # Add the csrf and hidden tags options if needed.
21
+ def _forme_form_options(obj, attr, opts)
22
+ super
26
23
 
27
- apply_csrf = options[:csrf]
24
+ apply_csrf = opts[:csrf]
28
25
 
29
26
  if apply_csrf || apply_csrf.nil?
30
- unless method = attribs[:method] || attribs['method']
27
+ unless method = attr[:method] || attr['method']
31
28
  if obj && !obj.is_a?(Hash) && obj.respond_to?(:forme_default_request_method)
32
29
  method = obj.forme_default_request_method
33
30
  end
@@ -39,18 +36,17 @@ class Roda
39
36
  end
40
37
 
41
38
  if apply_csrf
42
- token = if options.fetch(:use_request_specific_token){use_request_specific_csrf_tokens?}
43
- csrf_token(csrf_path(attribs[:action]), method)
39
+ token = if opts.fetch(:use_request_specific_token){use_request_specific_csrf_tokens?}
40
+ csrf_token(csrf_path(attr[:action]), method)
44
41
  else
45
42
  csrf_token
46
43
  end
47
44
 
48
- options[:hidden_tags] ||= []
49
- options[:hidden_tags] += [{csrf_field=>token}]
45
+ opts[:csrf] = [csrf_field, token]
46
+ opts[:_before] = lambda do |form|
47
+ form.tag(:input, :type=>:hidden, :name=>csrf_field, :value=>token)
48
+ end
50
49
  end
51
-
52
- options[:output] = @_out_buf if block
53
- ::Forme::ERB::Form.form(obj, attr, opts, &block)
54
50
  end
55
51
  end
56
52
  end