forme 1.12.0 → 2.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG +54 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +228 -206
- data/Rakefile +1 -7
- data/lib/forme/bs3.rb +23 -9
- data/lib/forme/erb.rb +13 -25
- data/lib/forme/form.rb +146 -149
- data/lib/forme/input.rb +1 -1
- data/lib/forme/rails.rb +39 -83
- data/lib/forme/raw.rb +2 -2
- data/lib/forme/tag.rb +3 -12
- data/lib/forme/template.rb +110 -0
- data/lib/forme/transformers/error_handler.rb +10 -10
- data/lib/forme/transformers/formatter.rb +32 -34
- data/lib/forme/transformers/helper.rb +0 -1
- data/lib/forme/transformers/inputs_wrapper.rb +4 -4
- data/lib/forme/version.rb +2 -2
- data/lib/forme.rb +13 -2
- data/lib/roda/plugins/forme.rb +1 -1
- data/lib/roda/plugins/forme_erubi_capture.rb +57 -0
- data/lib/roda/plugins/forme_route_csrf.rb +16 -34
- data/lib/roda/plugins/forme_set.rb +39 -76
- data/lib/sequel/plugins/forme.rb +45 -54
- data/lib/sequel/plugins/forme_i18n.rb +3 -1
- data/lib/sequel/plugins/forme_set.rb +2 -4
- data/spec/all.rb +1 -1
- data/spec/bs3_reference_spec.rb +291 -314
- data/spec/bs3_sequel_plugin_spec.rb +155 -155
- data/spec/bs3_spec.rb +247 -206
- data/spec/erb_helper.rb +69 -58
- data/spec/erubi_capture_helper.rb +198 -0
- data/spec/forme_coverage.rb +1 -0
- data/spec/forme_spec.rb +438 -377
- data/spec/rails_integration_spec.rb +21 -11
- data/spec/roda_integration_spec.rb +136 -70
- data/spec/sequel_helper.rb +3 -2
- data/spec/sequel_i18n_helper.rb +1 -1
- data/spec/sequel_i18n_plugin_spec.rb +6 -6
- data/spec/sequel_plugin_spec.rb +262 -150
- data/spec/sequel_set_plugin_spec.rb +9 -3
- data/spec/shared_erb_specs.rb +71 -0
- data/spec/sinatra_integration_spec.rb +31 -6
- data/spec/spec_helper.rb +21 -8
- metadata +8 -6
- data/lib/forme/erb_form.rb +0 -74
- data/lib/forme/sinatra.rb +0 -17
data/lib/forme/rails.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen-string-literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require_relative 'template'
|
4
4
|
|
5
5
|
class ActiveSupport::SafeBuffer
|
6
6
|
include Forme::Raw
|
@@ -8,104 +8,60 @@ end
|
|
8
8
|
|
9
9
|
module Forme
|
10
10
|
module Rails
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
add_hidden_tag do |tag|
|
23
|
-
if (form = tag.form) && (template = form.template) && template.protect_against_forgery? && (tag.attr[:method] || tag.attr['method']).to_s.upcase == 'POST'
|
24
|
-
{template.request_forgery_protection_token=>template.form_authenticity_token}
|
11
|
+
class TemplateForm < ::Forme::Template::Form
|
12
|
+
%w'inputs tag subform'.each do |meth|
|
13
|
+
class_eval(<<-END, __FILE__, __LINE__+1)
|
14
|
+
def #{meth}(*)
|
15
|
+
if block_given?
|
16
|
+
@scope.send(:with_output_buffer){super}
|
17
|
+
else
|
18
|
+
@scope.raw(super)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
END
|
25
22
|
end
|
26
|
-
end
|
27
|
-
|
28
|
-
# Subclass used when using Forme/Rails ERB integration,
|
29
|
-
# handling integration with the view template.
|
30
|
-
class Form < ::Forme::Form
|
31
|
-
# The Rails template that created this form.
|
32
|
-
attr_reader :template
|
33
23
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
24
|
+
%w'button input'.each do |meth|
|
25
|
+
class_eval(<<-END, __FILE__, __LINE__+1)
|
26
|
+
def #{meth}(*)
|
27
|
+
@scope.raw(super)
|
28
|
+
end
|
29
|
+
END
|
38
30
|
end
|
39
31
|
|
40
|
-
# Serialize and mark as already escaped the string version of
|
41
|
-
# the input.
|
42
32
|
def emit(tag)
|
43
|
-
|
33
|
+
@scope.output_buffer << @scope.raw(tag)
|
44
34
|
end
|
35
|
+
end
|
45
36
|
|
46
|
-
|
47
|
-
|
48
|
-
|
37
|
+
ERB = Template::Helper.clone
|
38
|
+
module ERB
|
39
|
+
alias _forme form
|
40
|
+
remove_method :form
|
41
|
+
|
42
|
+
def forme(*a, &block)
|
49
43
|
if block_given?
|
50
|
-
|
51
|
-
else
|
52
|
-
template.send(:with_output_buffer){super}
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
# If a block is not given, emit the inputs into the current output
|
57
|
-
# buffer.
|
58
|
-
def _inputs(inputs=[], opts={}) # :nodoc:
|
59
|
-
if block_given? && !opts[:subform]
|
60
|
-
super
|
44
|
+
with_output_buffer{_forme(*a, &block)}
|
61
45
|
else
|
62
|
-
|
46
|
+
raw(_forme(*a, &block))
|
63
47
|
end
|
64
48
|
end
|
65
49
|
|
66
|
-
|
67
|
-
def input(*)
|
68
|
-
super.to_s
|
69
|
-
end
|
70
|
-
|
71
|
-
# Return a string version of the button that is already marked as safe.
|
72
|
-
def button(*)
|
73
|
-
super.to_s
|
74
|
-
end
|
75
|
-
|
76
|
-
# Use the template's raw method to mark the given string as html safe.
|
77
|
-
def raw_output(s)
|
78
|
-
template.raw(s)
|
79
|
-
end
|
50
|
+
private
|
80
51
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
template.send(:with_output_buffer){tag_(type, attr, children, &block)}
|
88
|
-
else
|
89
|
-
_tag(type, attr, children).to_s
|
52
|
+
remove_method :_forme_form_options
|
53
|
+
def _forme_form_options(obj, attr, opts)
|
54
|
+
if protect_against_forgery?
|
55
|
+
opts[:_before_post] = lambda do |form|
|
56
|
+
form.tag(:input, :type=>:hidden, :name=>request_forgery_protection_token, :value=>form_authenticity_token)
|
57
|
+
end
|
90
58
|
end
|
91
59
|
end
|
92
|
-
|
93
|
-
def tag_(type, attr={}, children=[]) # :nodoc:
|
94
|
-
tag = _tag(type, attr, children)
|
95
|
-
emit(serialize_open(tag))
|
96
|
-
Array(tag.children).each{|c| emit(c)}
|
97
|
-
yield self if block_given?
|
98
|
-
emit(serialize_close(tag))
|
99
|
-
end
|
100
|
-
end
|
101
60
|
|
102
|
-
|
103
|
-
#
|
104
|
-
|
105
|
-
|
106
|
-
h = {:template=>self, :hidden_tags=>Forme::Rails::HIDDEN_TAGS}
|
107
|
-
(obj.is_a?(Hash) ? attr = attr.merge(h) : opts = opts.merge(h))
|
108
|
-
Form.form(obj, attr, opts, &block)
|
61
|
+
remove_method :_forme_form_class
|
62
|
+
# The class to use for forms
|
63
|
+
def _forme_form_class
|
64
|
+
TemplateForm
|
109
65
|
end
|
110
66
|
end
|
111
67
|
end
|
data/lib/forme/raw.rb
CHANGED
@@ -2,12 +2,12 @@
|
|
2
2
|
|
3
3
|
module Forme
|
4
4
|
# Empty module for marking objects as "raw", where they will no longer
|
5
|
-
#
|
5
|
+
# HTML escaped by the default serializer.
|
6
6
|
module Raw
|
7
7
|
end
|
8
8
|
|
9
9
|
# A String subclass that includes Raw, which will cause the default
|
10
|
-
# serializer to no longer
|
10
|
+
# serializer to no longer HTML escape the string.
|
11
11
|
class RawString < ::String
|
12
12
|
include Raw
|
13
13
|
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
|
5
|
-
#
|
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
|
-
|
34
|
+
Forme.transform(:serializer, @opts, @form.opts, self)
|
44
35
|
end
|
45
36
|
|
46
37
|
private
|
@@ -0,0 +1,110 @@
|
|
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
|
+
# Does nothing by default.
|
106
|
+
def _forme_form_options(obj, attr, opts)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -49,17 +49,17 @@ module Forme
|
|
49
49
|
Forme.register_transformer(:error_handler, :after_legend, new)
|
50
50
|
|
51
51
|
def call(tag, input)
|
52
|
-
|
53
|
-
|
54
|
-
|
52
|
+
if tag.is_a?(Array) && tag.first.is_a?(Tag) && tag.first.type == :legend
|
53
|
+
first_input = input.opts[:first_input]
|
54
|
+
attr = first_input.opts[:attr] ||= {}
|
55
|
+
Forme.attr_classes(attr, 'error')
|
56
|
+
attr['aria-invalid'] = 'true'
|
57
|
+
attr['aria-describedby'] = input.opts[:error_id] = "#{first_input.opts[:id]}_error_message"
|
55
58
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
attr['aria-describedby'] = input.opts[:error_id] = "#{first_input.opts[:id]}_error_message"
|
61
|
-
|
62
|
-
tag.insert(1, error_tag(input))
|
59
|
+
tag.insert(1, error_tag(input))
|
60
|
+
else
|
61
|
+
super
|
62
|
+
end
|
63
63
|
end
|
64
64
|
end
|
65
65
|
end
|
@@ -220,7 +220,7 @@ module Forme
|
|
220
220
|
end
|
221
221
|
|
222
222
|
def _format_set(type, tag_attrs={})
|
223
|
-
raise Error, "can't have radioset with no options" unless @opts[:optgroups] || @opts[:options]
|
223
|
+
raise Error, "can't have radioset or checkboxset with no options" unless @opts[:optgroups] || @opts[:options]
|
224
224
|
key = @opts[:key]
|
225
225
|
name = @opts[:name]
|
226
226
|
id = @opts[:id]
|
@@ -312,7 +312,9 @@ module Forme
|
|
312
312
|
Forme.attr_classes(@attr, 'error')
|
313
313
|
@attr["aria-invalid"] = "true"
|
314
314
|
if @opts.fetch(:error_handler, true)
|
315
|
-
|
315
|
+
if @opts[:error_id]
|
316
|
+
@attr['aria-describedby'] ||= @opts[:error_id]
|
317
|
+
else
|
316
318
|
if id = @attr[:id] || @attr['id']
|
317
319
|
error_id = @attr['aria-describedby'] ||= "#{id}_error_message"
|
318
320
|
@opts[:error_id] = error_id
|
@@ -397,9 +399,7 @@ module Forme
|
|
397
399
|
|
398
400
|
def set_error_from_namespaced_errors(namespaces, errors, key)
|
399
401
|
namespaces.each do |ns|
|
400
|
-
|
401
|
-
return unless e
|
402
|
-
errors = e
|
402
|
+
return unless errors = errors[ns] || errors[ns.to_s]
|
403
403
|
end
|
404
404
|
|
405
405
|
@opts[:error] = errors.fetch(key){errors.fetch(key.to_s){return}}
|
@@ -432,38 +432,36 @@ module Forme
|
|
432
432
|
# Iterate over the given options, yielding the option text, value, whether it is selected, and any attributes.
|
433
433
|
# The block should return an appropriate tag object.
|
434
434
|
def process_select_options(os)
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
sel = @opts[:selected] || @attr.delete(:value)
|
439
|
-
|
440
|
-
if @opts[:multiple]
|
441
|
-
sel = Array(sel)
|
442
|
-
cmp = lambda{|v| sel.include?(v)}
|
443
|
-
else
|
444
|
-
cmp = lambda{|v| v == sel}
|
445
|
-
end
|
435
|
+
vm = @opts[:value_method]
|
436
|
+
tm = @opts[:text_method]
|
437
|
+
sel = @opts[:selected] || @attr.delete(:value)
|
446
438
|
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
text = x.first
|
454
|
-
val = x.last
|
455
|
-
|
456
|
-
if val.is_a?(Hash)
|
457
|
-
value = val[:value]
|
458
|
-
attr.merge!(val)
|
459
|
-
val = value
|
460
|
-
end
|
461
|
-
else
|
462
|
-
text = x
|
463
|
-
end
|
439
|
+
if @opts[:multiple]
|
440
|
+
sel = Array(sel)
|
441
|
+
cmp = lambda{|v| sel.include?(v)}
|
442
|
+
else
|
443
|
+
cmp = lambda{|v| v == sel}
|
444
|
+
end
|
464
445
|
|
465
|
-
|
446
|
+
os.map do |x|
|
447
|
+
attr = {}
|
448
|
+
if tm
|
449
|
+
text = x.send(tm)
|
450
|
+
val = x.send(vm) if vm
|
451
|
+
elsif x.is_a?(Array)
|
452
|
+
text = x.first
|
453
|
+
val = x.last
|
454
|
+
|
455
|
+
if val.is_a?(Hash)
|
456
|
+
value = val[:value]
|
457
|
+
attr.merge!(val)
|
458
|
+
val = value
|
459
|
+
end
|
460
|
+
else
|
461
|
+
text = x
|
466
462
|
end
|
463
|
+
|
464
|
+
yield [text, val, !val.nil? ? cmp.call(val) : cmp.call(text), attr]
|
467
465
|
end
|
468
466
|
end
|
469
467
|
|
@@ -15,7 +15,7 @@ module Forme
|
|
15
15
|
Forme.attr_classes(attr, 'inputs')
|
16
16
|
if legend = opts[:legend]
|
17
17
|
form.tag(:fieldset, attr) do
|
18
|
-
form.
|
18
|
+
form.tag(:legend, opts[:legend_attr], legend)
|
19
19
|
yield
|
20
20
|
end
|
21
21
|
else
|
@@ -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.
|
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.
|
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.
|
91
|
+
form.tag(:tr, {}, labels.map{|l| form._tag(:th, {}, l)})
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
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 =
|
6
|
+
MAJOR = 2
|
7
7
|
|
8
8
|
# The minor version of Forme, updated for new feature releases of Forme.
|
9
|
-
MINOR =
|
9
|
+
MINOR = 2
|
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
@@ -162,5 +162,16 @@ module Forme
|
|
162
162
|
end
|
163
163
|
end
|
164
164
|
|
165
|
-
|
166
|
-
|
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'
|
data/lib/roda/plugins/forme.rb
CHANGED
@@ -0,0 +1,57 @@
|
|
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
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
register_plugin(:forme_erubi_capture, FormeErubiCapture)
|
56
|
+
end
|
57
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen-string-literal: true
|
2
2
|
|
3
|
-
|
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
|
-
|
17
|
-
|
18
|
-
|
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
|
26
19
|
|
27
|
-
|
20
|
+
# Add the csrf and hidden tags options if needed.
|
21
|
+
def _forme_form_options(obj, attr, opts)
|
22
|
+
super
|
23
|
+
|
24
|
+
apply_csrf = opts[:csrf]
|
28
25
|
|
29
26
|
if apply_csrf || apply_csrf.nil?
|
30
|
-
unless 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,32 +36,17 @@ class Roda
|
|
39
36
|
end
|
40
37
|
|
41
38
|
if apply_csrf
|
42
|
-
token = if
|
43
|
-
csrf_token(csrf_path(
|
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
|
-
|
49
|
-
|
50
|
-
|
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
|
51
49
|
end
|
52
|
-
|
53
|
-
options[:output] = @_out_buf if block
|
54
|
-
_forme_form_options(options)
|
55
|
-
_forme_form_class.form(obj, attr, opts, &block)
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
# The class to use for forms
|
61
|
-
def _forme_form_class
|
62
|
-
::Forme::ERB::Form
|
63
|
-
end
|
64
|
-
|
65
|
-
# The options to use for forms. Any changes should mutate this hash to set options.
|
66
|
-
def _forme_form_options(options)
|
67
|
-
options
|
68
50
|
end
|
69
51
|
end
|
70
52
|
end
|