forme 0.7.0 → 0.8.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 +7 -0
- data/CHANGELOG +12 -0
- data/README.rdoc +1 -1
- data/lib/forme.rb +59 -10
- data/lib/forme/rails.rb +24 -3
- data/lib/forme/sinatra.rb +21 -4
- data/lib/forme/version.rb +1 -1
- data/lib/sequel/plugins/forme.rb +1 -1
- data/spec/forme_spec.rb +44 -0
- data/spec/rails_integration_spec.rb +13 -3
- data/spec/sequel_plugin_spec.rb +12 -1
- data/spec/sinatra_integration_spec.rb +19 -10
- metadata +10 -17
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 06d7e50cfae657572071affb86ef307636c65345
|
4
|
+
data.tar.gz: 5eef25b91f833f3a57caef3903d25886cb48f00d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a19e5579fc8f0bfe11c5136f2ecc69db057a23f76d08bc01aad4680c1ebeb9fbd27476a04d60265efe5de1d1e5ab0b16dd615f8bc0081c7b733ef9f188e31581
|
7
|
+
data.tar.gz: ba0fe6ba4e18fe182c0a93eb9b33f28e0d0f30729ec537f2a3b468d8b9db56a75d657aadb17b4c164a3128d901017d7460a7ce8ecd9bd8a923d5017bc1e4d051
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
=== 0.8.0 (2013-10-30)
|
2
|
+
|
3
|
+
* form calls without block or :inputs or :button options are now handled correctly in the Sinatra integration (jeremyevans)
|
4
|
+
|
5
|
+
* CSRF token tags are now automatically added to forms in Rails and Sinatra if using rack_csrf (jeremyevans) (#5)
|
6
|
+
|
7
|
+
* Form objects now support a :hidden_tags option for automatically adding hidden tags (jeremyevans)
|
8
|
+
|
9
|
+
* Sequel many_to_one associations with existing and required values no longer have a blank option added by default (jeremyevans)
|
10
|
+
|
11
|
+
* ActiveSupport::SafeBuffer objects are now automatically treated as raw in the Rails integration (jeremyevans)
|
12
|
+
|
1
13
|
=== 0.7.0 (2012-05-02)
|
2
14
|
|
3
15
|
* Support :label_position option in both of the labelers, can be set to :before or :after to override the default (jeremyevans)
|
data/README.rdoc
CHANGED
@@ -76,7 +76,7 @@ You can even do everything in a single method call:
|
|
76
76
|
|
77
77
|
= Basic Design
|
78
78
|
|
79
|
-
|
79
|
+
Internally, Forme builds an abstract syntax tree of objects that
|
80
80
|
represent the form. The abstract syntax tree goes through a
|
81
81
|
series of transformations that convert it from high level
|
82
82
|
abstract forms to low level abstract forms and finally to
|
data/lib/forme.rb
CHANGED
@@ -99,7 +99,7 @@ module Forme
|
|
99
99
|
# +obj+ or +block+, but not both. If +obj+ is given, should be
|
100
100
|
# either a +Class+ instance or it should respond to +call+. If a
|
101
101
|
# +Class+ instance is given, instances of that class should respond
|
102
|
-
# to +call+, and
|
102
|
+
# to +call+, and a new instance of that class should be used
|
103
103
|
# for each transformation.
|
104
104
|
def self.register_transformer(type, sym, obj=nil, &block)
|
105
105
|
raise Error, "Not a valid transformer type" unless TRANSFORMERS.has_key?(type)
|
@@ -145,6 +145,7 @@ module Forme
|
|
145
145
|
# :obj :: Sets the +obj+ attribute
|
146
146
|
# :error_handler :: Sets the +error_handler+ for the form
|
147
147
|
# :formatter :: Sets the +formatter+ for the form
|
148
|
+
# :hidden_tags :: Sets the hidden tags to automatically add to this form.
|
148
149
|
# :inputs_wrapper :: Sets the +inputs_wrapper+ for the form
|
149
150
|
# :labeler :: Sets the +labeler+ for the form
|
150
151
|
# :wrapper :: Sets the +wrapper+ for the form
|
@@ -175,6 +176,15 @@ module Forme
|
|
175
176
|
# Must respond to +call+ or be a registered symbol.
|
176
177
|
attr_reader :serializer
|
177
178
|
|
179
|
+
# The hidden tags to automatically add to the form. If set, this should be an
|
180
|
+
# array, where elements are one of the following types:
|
181
|
+
# String, Array, Forme::Tag :: Added directly as a child of the form tag.
|
182
|
+
# Hash :: Adds a hidden tag for each entry, with keys as the name of the hidden
|
183
|
+
# tag and values as the value of the hidden tag.
|
184
|
+
# Proc :: Will be called with the form tag object, and should return an instance
|
185
|
+
# of one of the handled types (or nil to not add a tag).
|
186
|
+
attr_reader :hidden_tags
|
187
|
+
|
178
188
|
# Create a +Form+ instance and yield it to the block,
|
179
189
|
# injecting the opening form tag before yielding and
|
180
190
|
# the closing form tag after yielding.
|
@@ -232,6 +242,7 @@ module Forme
|
|
232
242
|
end
|
233
243
|
config = CONFIGURATIONS[@opts[:config]||Forme.default_config]
|
234
244
|
TRANSFORMER_TYPES.each{|k| instance_variable_set(:"@#{k}", transformer(k, @opts.fetch(k, config[k])))}
|
245
|
+
@hidden_tags = @opts[:hidden_tags]
|
235
246
|
@nesting = []
|
236
247
|
end
|
237
248
|
|
@@ -285,7 +296,7 @@ module Forme
|
|
285
296
|
|
286
297
|
# Create a form tag with the given attributes.
|
287
298
|
def form(attr={}, &block)
|
288
|
-
tag(:form, attr, &block)
|
299
|
+
tag(:form, attr, method(:hidden_form_tags), &block)
|
289
300
|
end
|
290
301
|
|
291
302
|
# Formats the +input+ using the +formatter+.
|
@@ -429,6 +440,35 @@ module Forme
|
|
429
440
|
|
430
441
|
private
|
431
442
|
|
443
|
+
# Return array of hidden tags to use for this form,
|
444
|
+
# or nil if the form does not have hidden tags added automatically.
|
445
|
+
def hidden_form_tags(form_tag)
|
446
|
+
if hidden_tags
|
447
|
+
tags = []
|
448
|
+
hidden_tags.each do |hidden_tag|
|
449
|
+
hidden_tag = hidden_tag.call(form_tag) if hidden_tag.respond_to?(:call)
|
450
|
+
tags.concat(parse_hidden_tags(hidden_tag))
|
451
|
+
end
|
452
|
+
tags
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
# Handle various types of hidden tags for the form.
|
457
|
+
def parse_hidden_tags(hidden_tag)
|
458
|
+
case hidden_tag
|
459
|
+
when Array
|
460
|
+
hidden_tag
|
461
|
+
when Tag, String
|
462
|
+
[hidden_tag]
|
463
|
+
when Hash
|
464
|
+
hidden_tag.map{|k,v| _tag(:input, :type=>:hidden, :name=>k, :value=>v)}
|
465
|
+
when nil
|
466
|
+
[]
|
467
|
+
else
|
468
|
+
raise Error, "unhandled hidden_tag response: #{hidden_tag.inspect}"
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
432
472
|
# Extend +obj+ with +Serialized+ and associate it with the receiver, such
|
433
473
|
# that calling +to_s+ on the object will use the receiver's serializer
|
434
474
|
# to generate the resulting string.
|
@@ -530,15 +570,8 @@ module Forme
|
|
530
570
|
|
531
571
|
# Set the +form+, +type+, +attr+, and +children+.
|
532
572
|
def initialize(form, type, attr={}, children=nil)
|
533
|
-
case children
|
534
|
-
when Array
|
535
|
-
@children = children
|
536
|
-
when nil
|
537
|
-
@children = nil
|
538
|
-
else
|
539
|
-
@children = [children]
|
540
|
-
end
|
541
573
|
@form, @type, @attr = form, type, (attr||{})
|
574
|
+
@children = parse_children(children)
|
542
575
|
end
|
543
576
|
|
544
577
|
# Adds a child to the array of receiver's children.
|
@@ -560,6 +593,22 @@ module Forme
|
|
560
593
|
def to_s
|
561
594
|
form.serialize(self)
|
562
595
|
end
|
596
|
+
|
597
|
+
private
|
598
|
+
|
599
|
+
# Convert children constructor argument into the children to use for the tag.
|
600
|
+
def parse_children(children)
|
601
|
+
case children
|
602
|
+
when Array
|
603
|
+
children
|
604
|
+
when Proc, Method
|
605
|
+
parse_children(children.call(self))
|
606
|
+
when nil
|
607
|
+
nil
|
608
|
+
else
|
609
|
+
[children]
|
610
|
+
end
|
611
|
+
end
|
563
612
|
end
|
564
613
|
|
565
614
|
# Module that can extend objects associating them with a specific
|
data/lib/forme/rails.rb
CHANGED
@@ -1,7 +1,28 @@
|
|
1
1
|
require 'forme'
|
2
2
|
|
3
|
+
class ActiveSupport::SafeBuffer
|
4
|
+
include Forme::Raw
|
5
|
+
end
|
6
|
+
|
3
7
|
module Forme
|
4
|
-
module Rails
|
8
|
+
module Rails
|
9
|
+
HIDDEN_TAGS = []
|
10
|
+
|
11
|
+
# Add a hidden tag proc that will be used for all forms created via Forme::Rails::ERB#form.
|
12
|
+
# The block is yielded the Forme::Tag object for the form tag.
|
13
|
+
# The block should return either nil if hidden tag should be added, or a Forme::Tag object (or an array of them),
|
14
|
+
# or a hash with keys specifying the name of the tags and the values specifying the values of the tags .
|
15
|
+
def self.add_hidden_tag(&block)
|
16
|
+
HIDDEN_TAGS << block
|
17
|
+
end
|
18
|
+
|
19
|
+
# Add CSRF token tag by default for POST forms
|
20
|
+
add_hidden_tag do |tag|
|
21
|
+
if (form = tag.form) && (template = form.template) && template.protect_against_forgery? && tag.attr[:method].to_s.upcase == 'POST'
|
22
|
+
{template.request_forgery_protection_token=>template.form_authenticity_token}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
5
26
|
# Subclass used when using Forme/Rails ERB integration,
|
6
27
|
# handling integration with the view template.
|
7
28
|
class Form < ::Forme::Form
|
@@ -66,7 +87,7 @@ module Forme
|
|
66
87
|
def tag_(type, attr={}, children=[])
|
67
88
|
tag = _tag(type, attr, children)
|
68
89
|
emit(serializer.serialize_open(tag)) if serializer.respond_to?(:serialize_open)
|
69
|
-
Array(children).each{|c| emit(c)}
|
90
|
+
Array(tag.children).each{|c| emit(c)}
|
70
91
|
yield self if block_given?
|
71
92
|
emit(serializer.serialize_close(tag)) if serializer.respond_to?(:serialize_close)
|
72
93
|
end
|
@@ -90,7 +111,7 @@ module Forme
|
|
90
111
|
# opening attributes, third if provided is
|
91
112
|
# +Form+'s options.
|
92
113
|
def forme(obj=nil, attr={}, opts={}, &block)
|
93
|
-
h = {:template=>self}
|
114
|
+
h = {:template=>self, :hidden_tags=>Forme::Rails::HIDDEN_TAGS}
|
94
115
|
(obj.is_a?(Hash) ? attr = attr.merge(h) : opts = opts.merge(h))
|
95
116
|
Form.form(obj, attr, opts, &block)
|
96
117
|
end
|
data/lib/forme/sinatra.rb
CHANGED
@@ -1,7 +1,24 @@
|
|
1
1
|
require 'forme'
|
2
2
|
|
3
3
|
module Forme
|
4
|
-
module Sinatra
|
4
|
+
module Sinatra
|
5
|
+
HIDDEN_TAGS = []
|
6
|
+
|
7
|
+
# Add a hidden tag proc that will be used for all forms created via Forme::Sinatra::ERB#form.
|
8
|
+
# The block is yielded the Forme::Tag object for the form tag.
|
9
|
+
# The block should return either nil if hidden tag should be added, or a Forme::Tag object (or an array of them),
|
10
|
+
# or a hash with keys specifying the name of the tags and the values specifying the values of the tags .
|
11
|
+
def self.add_hidden_tag(&block)
|
12
|
+
HIDDEN_TAGS << block
|
13
|
+
end
|
14
|
+
|
15
|
+
# Add CSRF token tag by default for POST forms
|
16
|
+
add_hidden_tag do |tag|
|
17
|
+
if defined?(::Rack::Csrf) && (form = tag.form) && (env = form.opts[:env]) && tag.attr[:method].to_s.upcase == 'POST'
|
18
|
+
{::Rack::Csrf.field=>::Rack::Csrf.token(env)}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
5
22
|
# Subclass used when using Forme/Sinatra ERB integration.
|
6
23
|
# Handles integrating into the view template so that
|
7
24
|
# methods with blocks can inject strings into the output.
|
@@ -37,7 +54,7 @@ module Forme
|
|
37
54
|
if block
|
38
55
|
capture(block){super}
|
39
56
|
else
|
40
|
-
|
57
|
+
super
|
41
58
|
end
|
42
59
|
end
|
43
60
|
|
@@ -50,7 +67,7 @@ module Forme
|
|
50
67
|
if block
|
51
68
|
capture(block) do
|
52
69
|
emit(serializer.serialize_open(tag)) if serializer.respond_to?(:serialize_open)
|
53
|
-
children.each{|c| emit(c)}
|
70
|
+
Array(tag.children).each{|c| emit(c)}
|
54
71
|
yield self
|
55
72
|
emit(serializer.serialize_close(tag)) if serializer.respond_to?(:serialize_close)
|
56
73
|
end
|
@@ -92,7 +109,7 @@ module Forme
|
|
92
109
|
# +Form+'s options.
|
93
110
|
def form(obj=nil, attr={}, opts={}, &block)
|
94
111
|
if block
|
95
|
-
h = {:output=>@_out_buf}
|
112
|
+
h = {:output=>@_out_buf, :hidden_tags=>Forme::Sinatra::HIDDEN_TAGS, :env=>env}
|
96
113
|
(obj.is_a?(Hash) ? attr = attr.merge(h) : opts = opts.merge(h))
|
97
114
|
Form.form(obj, attr, opts, &block)
|
98
115
|
else
|
data/lib/forme/version.rb
CHANGED
data/lib/sequel/plugins/forme.rb
CHANGED
@@ -309,8 +309,8 @@ module Sequel # :nodoc:
|
|
309
309
|
wrapper ? wrapper.call(radios, _input(:radio, opts)) : radios
|
310
310
|
else
|
311
311
|
opts[:id] = form.namespaced_id(key) unless opts.has_key?(:id)
|
312
|
-
opts[:add_blank] = true if !opts.has_key?(:add_blank)
|
313
312
|
opts[:required] = true if !opts.has_key?(:required) && (sch = obj.model.db_schema[key]) && !sch[:allow_null]
|
313
|
+
opts[:add_blank] = true if !opts.has_key?(:add_blank) && !(opts[:required] && opts[:value])
|
314
314
|
handle_label(field)
|
315
315
|
::Forme.attr_classes(opts[:wrapper_attr], "required") if opts[:required]
|
316
316
|
_input(:select, opts)
|
data/spec/forme_spec.rb
CHANGED
@@ -246,6 +246,16 @@ describe "Forme plain forms" do
|
|
246
246
|
@f.tag(:textarea, {:name=>:foo}, :bar).to_s.should == '<textarea name="foo">bar</textarea>'
|
247
247
|
end
|
248
248
|
|
249
|
+
specify "#tag should accept children as procs" do
|
250
|
+
@f.tag(:div, {:class=>"foo"}, lambda{|t| t.form.tag(:input, :class=>t.attr[:class])}).to_s.should == '<div class="foo"><input class="foo"/></div>'
|
251
|
+
end
|
252
|
+
|
253
|
+
specify "#tag should accept children as methods" do
|
254
|
+
o = Object.new
|
255
|
+
def o.foo(t) t.form.tag(:input, :class=>t.attr[:class]) end
|
256
|
+
@f.tag(:div, {:class=>"foo"}, o.method(:foo)).to_s.should == '<div class="foo"><input class="foo"/></div>'
|
257
|
+
end
|
258
|
+
|
249
259
|
specify "should have an #inputs method for multiple inputs wrapped in a fieldset" do
|
250
260
|
@f.inputs([:textarea, :text]).to_s.should == '<fieldset class="inputs"><textarea></textarea><input type="text"/></fieldset>'
|
251
261
|
end
|
@@ -325,6 +335,10 @@ describe "Forme plain forms" do
|
|
325
335
|
@f.input(:checkbox, :labeler=>:explicit, :label=>'Foo', :value=>'foo', :name=>'a', :id=>'bar', :label_position=>:before).to_s.should == '<label for="bar">Foo</label><input id="bar_hidden" name="a" type="hidden" value="0"/><input id="bar" name="a" type="checkbox" value="foo"/>'
|
326
336
|
end
|
327
337
|
|
338
|
+
specify "inputs handle implicit labels or checkboxes without hidden fields with :label_position=>:before" do
|
339
|
+
@f.input(:checkbox, :label=>'Foo', :value=>'foo', :name=>'a', :id=>'bar', :label_position=>:before, :no_hidden=>true).to_s.should == '<label>Foo <input id="bar" name="a" type="checkbox" value="foo"/></label>'
|
340
|
+
end
|
341
|
+
|
328
342
|
specify "inputs should accept a :error_handler option to use a custom error_handler" do
|
329
343
|
@f.input(:textarea, :error_handler=>proc{|t, i| [t, "!!! #{i.opts[:error]}"]}, :error=>'bar', :id=>:foo).to_s.should == '<textarea class="error" id="foo"></textarea>!!! bar'
|
330
344
|
end
|
@@ -360,6 +374,36 @@ describe "Forme plain forms" do
|
|
360
374
|
end
|
361
375
|
end
|
362
376
|
|
377
|
+
describe "Forme::Form :hidden_tags option " do
|
378
|
+
before do
|
379
|
+
@f = Forme::Form.new
|
380
|
+
end
|
381
|
+
|
382
|
+
specify "should handle hash" do
|
383
|
+
Forme.form({}, :hidden_tags=>[{:a=>'b'}]).to_s.should == '<form><input name="a" type="hidden" value="b"/></form>'
|
384
|
+
end
|
385
|
+
|
386
|
+
specify "should handle array" do
|
387
|
+
Forme.form({}, :hidden_tags=>[["a ", "b"]]).to_s.should == '<form>a b</form>'
|
388
|
+
end
|
389
|
+
|
390
|
+
specify "should handle string" do
|
391
|
+
Forme.form({}, :hidden_tags=>["a "]).to_s.should == '<form>a </form>'
|
392
|
+
end
|
393
|
+
|
394
|
+
specify "should handle proc return hash" do
|
395
|
+
Forme.form({}, :hidden_tags=>[lambda{|tag| {:a=>'b'}}]).to_s.should == '<form><input name="a" type="hidden" value="b"/></form>'
|
396
|
+
end
|
397
|
+
|
398
|
+
specify "should handle proc return tag" do
|
399
|
+
Forme.form({:method=>'post'}, :hidden_tags=>[lambda{|tag| tag.form._tag(tag.attr[:method])}]).to_s.should == '<form method="post"><post></post></form>'
|
400
|
+
end
|
401
|
+
|
402
|
+
specify "should raise error for unhandled object" do
|
403
|
+
proc{Forme.form({}, :hidden_tags=>[Object.new])}.should raise_error
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
363
407
|
describe "Forme custom" do
|
364
408
|
specify "formatters can be specified as a proc" do
|
365
409
|
Forme::Form.new(:formatter=>proc{|i| i.form._tag(:textarea, i.opts.map{|k,v| [v.upcase, k.to_s.downcase]})}).input(:text, :name=>'foo').to_s.should == '<textarea FOO="name"></textarea>'
|
@@ -6,10 +6,12 @@ require 'action_controller/railtie'
|
|
6
6
|
require 'forme/rails'
|
7
7
|
|
8
8
|
class FormeRails < Rails::Application
|
9
|
-
config.secret_token = routes.append {
|
9
|
+
config.secret_token = routes.append { get ':action' , :controller=>'forme' }.inspect
|
10
10
|
config.active_support.deprecation = :stderr
|
11
11
|
config.middleware.delete(ActionDispatch::ShowExceptions)
|
12
|
-
config.
|
12
|
+
config.middleware.delete("Rack::Lock")
|
13
|
+
config.secret_key_base = 'foo'
|
14
|
+
config.eager_load = true
|
13
15
|
initialize!
|
14
16
|
end
|
15
17
|
|
@@ -139,6 +141,10 @@ END
|
|
139
141
|
def noblock
|
140
142
|
render :inline => "<%= forme([:foo, :bar], {:action=>'/baz'}, :inputs=>[:first], :button=>'xyz', :legend=>'123') %>"
|
141
143
|
end
|
144
|
+
|
145
|
+
def safe_buffer
|
146
|
+
render :inline => "<%= forme([:foo, :bar], {:action=>'/baz'}, :inputs=>[:first], :button=>'xyz', :legend=>'<b>foo</b>'.html_safe) %>"
|
147
|
+
end
|
142
148
|
end
|
143
149
|
|
144
150
|
describe "Forme Rails integration" do
|
@@ -174,7 +180,7 @@ describe "Forme Rails integration" do
|
|
174
180
|
end
|
175
181
|
|
176
182
|
specify "#form should correctly handle situation Sequel integration with subforms where multiple templates are used with same form object" do
|
177
|
-
sin_get('/nest_seq').should == "0 <form action=\"/baz\" class=\"forme album\" method=\"post\"
|
183
|
+
sin_get('/nest_seq').sub(%r{<input name=\"authenticity_token\" type=\"hidden\" value=\"([^\"]+)\"/>}, "<input name=\"authenticity_token\" type=\"hidden\" value=\"csrf\"/>").should == "0 <form action=\"/baz\" class=\"forme album\" method=\"post\"><input name=\"authenticity_token\" type=\"hidden\" value=\"csrf\"/> 1 <input id=\"album_artist_attributes_id\" name=\"album[artist_attributes][id]\" type=\"hidden\" value=\"2\"/><fieldset class=\"inputs\"><legend>Foo</legend><label>Name: <input id=\"album_artist_attributes_name\" name=\"album[artist_attributes][name]\" type=\"text\" value=\"A\"/></label></fieldset> 2 n1 <input id=\"album_artist_attributes_id\" name=\"album[artist_attributes][id]\" type=\"hidden\" value=\"2\"/> n2 <label>Name2: <input id=\"album_artist_attributes_name2\" name=\"album[artist_attributes][name2]\" type=\"text\" value=\"A2\"/></label> n3 n4 <input id=\"album_artist_attributes_id\" name=\"album[artist_attributes][id]\" type=\"hidden\" value=\"2\"/><fieldset class=\"inputs\"><legend>Bar</legend><label>Name3: <input id=\"album_artist_attributes_name3\" name=\"album[artist_attributes][name3]\" type=\"text\" value=\"A3\"/></label></fieldset> n5 3 </form>4"
|
178
184
|
end
|
179
185
|
|
180
186
|
specify "#form should accept two hashes instead of requiring obj as first argument" do
|
@@ -192,4 +198,8 @@ describe "Forme Rails integration" do
|
|
192
198
|
specify "#form should work without a block" do
|
193
199
|
sin_get('/noblock').should == '<form action="/baz"><fieldset class="inputs"><legend>123</legend><input id="first" name="first" type="text" value="foo"/></fieldset><input type="submit" value="xyz"/></form>'
|
194
200
|
end
|
201
|
+
|
202
|
+
specify "#form should handle Rails SafeBuffers" do
|
203
|
+
sin_get('/safe_buffer').should == '<form action="/baz"><fieldset class="inputs"><legend><b>foo</b></legend><input id="first" name="first" type="text" value="foo"/></fieldset><input type="submit" value="xyz"/></form>'
|
204
|
+
end
|
195
205
|
end
|
data/spec/sequel_plugin_spec.rb
CHANGED
@@ -17,6 +17,13 @@ describe "Forme Sequel::Model forms" do
|
|
17
17
|
@b.form(:class=>:foo, :method=>:get).to_s.should == '<form class="foo forme album" method="get"></form>'
|
18
18
|
end
|
19
19
|
|
20
|
+
specify "should handle invalid methods" do
|
21
|
+
def @ab.db_schema
|
22
|
+
super.merge(:foo=>{:type=>:bar})
|
23
|
+
end
|
24
|
+
@b.input(:foo, :value=>'baz').to_s.should == '<label>Foo: <input id="album_foo" name="album[foo]" type="text" value="baz"/></label>'
|
25
|
+
end
|
26
|
+
|
20
27
|
specify "should allow an array of classes" do
|
21
28
|
@b.form(:class=>[:foo, :bar]).to_s.should == '<form class="foo bar forme album" method="post"></form>'
|
22
29
|
@b.form(:class=>[:foo, [:bar, :baz]]).to_s.should == '<form class="foo bar baz forme album" method="post"></form>'
|
@@ -122,12 +129,16 @@ describe "Forme Sequel::Model forms" do
|
|
122
129
|
@c.input(:artist).to_s.should == '<label>Artist: <select id="album_artist_id" name="album[artist_id]"><option value=""></option><option value="1">a</option><option selected="selected" value="2">d</option></select></label>'
|
123
130
|
end
|
124
131
|
|
132
|
+
specify "should not add a blank option by default if there is a default value and it is required" do
|
133
|
+
@b.input(:artist, :required=>true).to_s.should == '<label>Artist<abbr title="required">*</abbr>: <select id="album_artist_id" name="album[artist_id]" required="required"><option selected="selected" value="1">a</option><option value="2">d</option></select></label>'
|
134
|
+
end
|
135
|
+
|
125
136
|
specify "should allow overriding default input type using a :type option" do
|
126
137
|
@b.input(:artist, :type=>:string, :value=>nil).to_s.should == '<label>Artist: <input id="album_artist" name="album[artist]" type="text"/></label>'
|
127
138
|
end
|
128
139
|
|
129
140
|
specify "should use a required wrapper tag for many_to_one required associations" do
|
130
|
-
@b.input(:artist, :required=>true, :wrapper=>:li).to_s.should == '<li class="many_to_one required"><label>Artist<abbr title="required">*</abbr>: <select id="album_artist_id" name="album[artist_id]" required="required"><option
|
141
|
+
@b.input(:artist, :required=>true, :wrapper=>:li).to_s.should == '<li class="many_to_one required"><label>Artist<abbr title="required">*</abbr>: <select id="album_artist_id" name="album[artist_id]" required="required"><option selected="selected" value="1">a</option><option value="2">d</option></select></label></li>'
|
131
142
|
end
|
132
143
|
|
133
144
|
specify "should use a set of radio buttons for many_to_one associations with :as=>:radio option" do
|
@@ -5,11 +5,14 @@ require 'rubygems'
|
|
5
5
|
require 'sinatra/base'
|
6
6
|
require 'forme/sinatra'
|
7
7
|
require(ENV['ERUBIS'] ? 'erubis' : 'erb')
|
8
|
+
require 'rack/csrf'
|
8
9
|
|
9
10
|
class FormeSinatraTest < Sinatra::Base
|
10
11
|
helpers(Forme::Sinatra::ERB)
|
11
12
|
disable :show_exceptions
|
12
13
|
enable :raise_errors
|
14
|
+
enable :sessions
|
15
|
+
use Rack::Csrf
|
13
16
|
|
14
17
|
get '/' do
|
15
18
|
erb <<END
|
@@ -24,21 +27,17 @@ END
|
|
24
27
|
|
25
28
|
get '/inputs_block' do
|
26
29
|
erb <<END
|
27
|
-
<% form([:foo, :bar], :action=>'/baz') do |f| %>
|
28
|
-
<% f.inputs(:legend=>'FBB') do %>
|
30
|
+
<% form([:foo, :bar], :action=>'/baz') do |f| %><% f.inputs(:legend=>'FBB') do %>
|
29
31
|
<%= f.input(:last) %>
|
30
|
-
<% end %>
|
31
|
-
<% end %>
|
32
|
+
<% end %><% end %>
|
32
33
|
END
|
33
34
|
end
|
34
35
|
|
35
36
|
get '/inputs_block_wrapper' do
|
36
37
|
erb <<END
|
37
|
-
<% form([:foo, :bar], {:action=>'/baz'}, :inputs_wrapper=>:fieldset_ol) do |f| %>
|
38
|
-
<% f.inputs(:legend=>'FBB') do %>
|
38
|
+
<% form([:foo, :bar], {:action=>'/baz'}, :inputs_wrapper=>:fieldset_ol) do |f| %><% f.inputs(:legend=>'FBB') do %>
|
39
39
|
<%= f.input(:last) %>
|
40
|
-
<% end %>
|
41
|
-
<% end %>
|
40
|
+
<% end %><% end %>
|
42
41
|
END
|
43
42
|
end
|
44
43
|
|
@@ -134,11 +133,17 @@ END
|
|
134
133
|
get '/noblock' do
|
135
134
|
erb "<%= form([:foo, :bar], {:action=>'/baz'}, :inputs=>[:first], :button=>'xyz', :legend=>'123') %>"
|
136
135
|
end
|
136
|
+
|
137
|
+
get '/noblock_empty' do
|
138
|
+
erb "<%= form(:action=>'/baz') %>"
|
139
|
+
end
|
137
140
|
end
|
138
141
|
|
139
142
|
describe "Forme Sinatra ERB integration" do
|
140
143
|
def sin_get(path)
|
141
|
-
|
144
|
+
s = ''
|
145
|
+
FormeSinatraTest.new.call(@rack.merge('PATH_INFO'=>path))[2].each{|str| s << str}
|
146
|
+
s.gsub(/\s+/, ' ').strip
|
142
147
|
end
|
143
148
|
before do
|
144
149
|
o = Object.new
|
@@ -167,7 +172,7 @@ describe "Forme Sinatra ERB integration" do
|
|
167
172
|
end
|
168
173
|
|
169
174
|
specify "#form should correctly handle situation Sequel integration with subforms where multiple templates are used with same form object" do
|
170
|
-
sin_get('/nest_seq').should == "0 <form action=\"/baz\" class=\"forme album\" method=\"post\"
|
175
|
+
sin_get('/nest_seq').sub(%r{<input name=\"_csrf\" type=\"hidden\" value=\"([^\"]+)\"/>}, "<input name=\"_csrf\" type=\"hidden\" value=\"csrf\"/>").should == "0 <form action=\"/baz\" class=\"forme album\" method=\"post\"><input name=\"_csrf\" type=\"hidden\" value=\"csrf\"/> 1 <input id=\"album_artist_attributes_id\" name=\"album[artist_attributes][id]\" type=\"hidden\" value=\"2\"/><fieldset class=\"inputs\"><legend>Foo</legend><label>Name: <input id=\"album_artist_attributes_name\" name=\"album[artist_attributes][name]\" type=\"text\" value=\"A\"/></label></fieldset> 2 n1 <input id=\"album_artist_attributes_id\" name=\"album[artist_attributes][id]\" type=\"hidden\" value=\"2\"/> n2 <label>Name2: <input id=\"album_artist_attributes_name2\" name=\"album[artist_attributes][name2]\" type=\"text\" value=\"A2\"/></label> n3 n4 <input id=\"album_artist_attributes_id\" name=\"album[artist_attributes][id]\" type=\"hidden\" value=\"2\"/><fieldset class=\"inputs\"><legend>Bar</legend><label>Name3: <input id=\"album_artist_attributes_name3\" name=\"album[artist_attributes][name3]\" type=\"text\" value=\"A3\"/></label></fieldset> n5 3 </form>4"
|
171
176
|
end
|
172
177
|
|
173
178
|
specify "#form should accept two hashes instead of requiring obj as first argument" do
|
@@ -185,4 +190,8 @@ describe "Forme Sinatra ERB integration" do
|
|
185
190
|
specify "#form should work without a block" do
|
186
191
|
sin_get('/noblock').should == '<form action="/baz"><fieldset class="inputs"><legend>123</legend><input id="first" name="first" type="text" value="foo"/></fieldset><input type="submit" value="xyz"/></form>'
|
187
192
|
end
|
193
|
+
|
194
|
+
specify "#form with an empty form should work" do
|
195
|
+
sin_get('/noblock_empty').should == '<form action="/baz"></form>'
|
196
|
+
end
|
188
197
|
end
|
metadata
CHANGED
@@ -1,28 +1,22 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: forme
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.8.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Jeremy Evans
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2013-10-30 00:00:00.000000000 Z
|
13
12
|
dependencies: []
|
14
|
-
description:
|
15
|
-
|
13
|
+
description: |
|
14
|
+
Forme is a forms library with the following goals:
|
16
15
|
|
17
16
|
1) Have no external dependencies
|
18
|
-
|
19
17
|
2) Have a simple API
|
20
|
-
|
21
18
|
3) Support forms both with and without related objects
|
22
|
-
|
23
19
|
4) Allow compiling down to different types of output
|
24
|
-
|
25
|
-
'
|
26
20
|
email: code@jeremyevans.net
|
27
21
|
executables: []
|
28
22
|
extensions: []
|
@@ -48,33 +42,32 @@ files:
|
|
48
42
|
- lib/sequel/plugins/forme.rb
|
49
43
|
homepage: http://gihub.com/jeremyevans/forme
|
50
44
|
licenses: []
|
45
|
+
metadata: {}
|
51
46
|
post_install_message:
|
52
47
|
rdoc_options:
|
53
48
|
- --quiet
|
54
49
|
- --line-numbers
|
55
50
|
- --inline-source
|
56
51
|
- --title
|
57
|
-
-
|
52
|
+
- 'Forme: HTML forms library'
|
58
53
|
- --main
|
59
54
|
- README.rdoc
|
60
55
|
require_paths:
|
61
56
|
- lib
|
62
57
|
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
-
none: false
|
64
58
|
requirements:
|
65
|
-
- -
|
59
|
+
- - '>='
|
66
60
|
- !ruby/object:Gem::Version
|
67
61
|
version: '0'
|
68
62
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
-
none: false
|
70
63
|
requirements:
|
71
|
-
- -
|
64
|
+
- - '>='
|
72
65
|
- !ruby/object:Gem::Version
|
73
66
|
version: '0'
|
74
67
|
requirements: []
|
75
68
|
rubyforge_project:
|
76
|
-
rubygems_version:
|
69
|
+
rubygems_version: 2.0.3
|
77
70
|
signing_key:
|
78
|
-
specification_version:
|
71
|
+
specification_version: 4
|
79
72
|
summary: HTML forms library
|
80
73
|
test_files: []
|