forme 1.11.0 → 2.1.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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +54 -0
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +235 -209
  5. data/Rakefile +1 -7
  6. data/lib/forme/bs3.rb +18 -4
  7. data/lib/forme/erb.rb +13 -25
  8. data/lib/forme/form.rb +144 -149
  9. data/lib/forme/input.rb +1 -1
  10. data/lib/forme/rails.rb +39 -83
  11. data/lib/forme/raw.rb +2 -2
  12. data/lib/forme/tag.rb +3 -12
  13. data/lib/forme/template.rb +110 -0
  14. data/lib/forme/transformers/formatter.rb +4 -1
  15. data/lib/forme/transformers/helper.rb +0 -1
  16. data/lib/forme/transformers/inputs_wrapper.rb +4 -4
  17. data/lib/forme/version.rb +2 -2
  18. data/lib/forme.rb +15 -2
  19. data/lib/roda/plugins/forme.rb +1 -1
  20. data/lib/roda/plugins/forme_erubi_capture.rb +57 -0
  21. data/lib/roda/plugins/forme_route_csrf.rb +16 -34
  22. data/lib/roda/plugins/forme_set.rb +39 -76
  23. data/lib/sequel/plugins/forme.rb +40 -50
  24. data/lib/sequel/plugins/forme_i18n.rb +3 -1
  25. data/lib/sequel/plugins/forme_set.rb +3 -1
  26. data/spec/all.rb +1 -1
  27. data/spec/bs3_reference_spec.rb +18 -18
  28. data/spec/bs3_sequel_plugin_spec.rb +17 -17
  29. data/spec/bs3_spec.rb +23 -11
  30. data/spec/erb_helper.rb +69 -58
  31. data/spec/erubi_capture_helper.rb +198 -0
  32. data/spec/forme_spec.rb +21 -32
  33. data/spec/rails_integration_spec.rb +39 -25
  34. data/spec/roda_integration_spec.rb +118 -70
  35. data/spec/sequel_helper.rb +0 -1
  36. data/spec/sequel_i18n_helper.rb +1 -1
  37. data/spec/sequel_i18n_plugin_spec.rb +3 -2
  38. data/spec/sequel_plugin_spec.rb +29 -12
  39. data/spec/sequel_set_plugin_spec.rb +9 -2
  40. data/spec/shared_erb_specs.rb +71 -0
  41. data/spec/sinatra_integration_spec.rb +5 -6
  42. data/spec/spec_helper.rb +21 -8
  43. metadata +9 -7
  44. data/lib/forme/erb_form.rb +0 -74
  45. data/lib/forme/sinatra.rb +0 -17
data/spec/bs3_spec.rb CHANGED
@@ -1,5 +1,5 @@
1
- require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
- require 'forme/bs3'
1
+ require_relative 'spec_helper'
2
+ require_relative '../lib/forme/bs3'
3
3
 
4
4
  describe "Forme Bootstrap3 (BS3) forms" do
5
5
  def sel(opts, s)
@@ -99,6 +99,18 @@ describe "Forme Bootstrap3 (BS3) forms" do
99
99
  end
100
100
  end
101
101
 
102
+ it "should consider form's :errors hash based on the :key option" do
103
+ @f.opts[:errors] = { 'foo' => 'must be present' }
104
+ @f.input(:text, :key=>"foo").to_s.must_equal "<div class=\"form-group has-error\"><input aria-describedby=\"foo_error_message\" aria-invalid=\"true\" class=\"form-control\" id=\"foo\" name=\"foo\" type=\"text\"/><span class=\"help-block with-errors\">must be present</span></div>"
105
+ end
106
+
107
+ it "should consider form's :errors hash based on the :key option when using namespaces" do
108
+ @f.opts[:errors] = { 'bar' => { 'foo' => 'must be present' } }
109
+ @f.with_opts(:namespace=>['bar']) do
110
+ @f.input(:text, :key=>"foo").to_s.must_equal "<div class=\"form-group has-error\"><input aria-describedby=\"bar_foo_error_message\" aria-invalid=\"true\" class=\"form-control\" id=\"bar_foo\" name=\"bar[foo]\" type=\"text\"/><span class=\"help-block with-errors\">must be present</span></div>"
111
+ end
112
+ end
113
+
102
114
  it "should support a with_obj method that changes the object and namespace for the given block" do
103
115
  @f.with_obj([:a, :c], 'bar') do
104
116
  @f.input(:first).to_s.must_equal '<div class="form-group"><input class="form-control" id="bar_first" name="bar[first]" type="text" value="a"/></div>'
@@ -481,19 +493,19 @@ describe "Forme Bootstrap3 (BS3) forms" do
481
493
  end
482
494
 
483
495
  it "should automatically note the input has errors if :error option is used" do
484
- @f.input(:text, :error=>'Bad Stuff!', :value=>'foo').to_s.must_equal '<div class="form-group has-error"><input class="form-control" type="text" value="foo"/><span class="help-block with-errors">Bad Stuff!</span></div>'
496
+ @f.input(:text, :error=>'Bad Stuff!', :value=>'foo').to_s.must_equal '<div class="form-group has-error"><input aria-invalid="true" class="form-control" type="text" value="foo"/><span class="help-block with-errors">Bad Stuff!</span></div>'
485
497
  end
486
498
 
487
499
  it "should add an error message after the label" do
488
- @f.input(:text, :error=>'Bad Stuff!', :value=>'foo', :label=>"Foo").to_s.must_equal '<div class="form-group has-error"><label>Foo</label> <input class="form-control" type="text" value="foo"/><span class="help-block with-errors">Bad Stuff!</span></div>'
500
+ @f.input(:text, :error=>'Bad Stuff!', :value=>'foo', :label=>"Foo").to_s.must_equal '<div class="form-group has-error"><label>Foo</label> <input aria-invalid="true" class="form-control" type="text" value="foo"/><span class="help-block with-errors">Bad Stuff!</span></div>'
489
501
  end
490
502
 
491
503
  it "should add to existing :class option if :error option is used" do
492
- @f.input(:text, :error=>'Bad Stuff!', :class=>'bar', :value=>'foo').to_s.must_equal '<div class="form-group has-error"><input class="form-control bar" type="text" value="foo"/><span class="help-block with-errors">Bad Stuff!</span></div>'
504
+ @f.input(:text, :error=>'Bad Stuff!', :class=>'bar', :value=>'foo').to_s.must_equal '<div class="form-group has-error"><input aria-invalid="true" class="form-control bar" type="text" value="foo"/><span class="help-block with-errors">Bad Stuff!</span></div>'
493
505
  end
494
506
 
495
507
  it "should respect :error_attr option for setting the attributes for the error message span" do
496
- @f.input(:text, :error=>'Bad Stuff!', :value=>'foo', :error_attr=>{:class=>'foo'}).to_s.must_equal '<div class="form-group has-error"><input class="form-control" type="text" value="foo"/><span class="foo help-block with-errors">Bad Stuff!</span></div>'
508
+ @f.input(:text, :error=>'Bad Stuff!', :value=>'foo', :error_attr=>{:class=>'foo'}).to_s.must_equal '<div class="form-group has-error"><input aria-invalid="true" class="form-control" type="text" value="foo"/><span class="foo help-block with-errors">Bad Stuff!</span></div>'
497
509
  end
498
510
 
499
511
  it "#open should return an opening tag" do
@@ -527,12 +539,12 @@ describe "Forme Bootstrap3 (BS3) forms" do
527
539
  end
528
540
 
529
541
  it "#tag should accept children as procs" do
530
- @f.tag(:div, {:class=>"foo"}, lambda{|t| t.form.tag(:input, :class=>t.attr[:class])}).to_s.must_equal '<div class="foo"><input class="form-control foo" type="text"/></div>'
542
+ @f.tag(:div, {:class=>"foo"}, lambda{|t| t.tag(:input, :class=>t.attr[:class])}).to_s.must_equal '<div class="foo"><input class="form-control foo" type="text"/></div>'
531
543
  end
532
544
 
533
545
  it "#tag should accept children as methods" do
534
546
  o = Object.new
535
- def o.foo(t) t.form.tag(:input, :class=>t.attr[:class]) end
547
+ def o.foo(t) t.tag(:input, :class=>t.attr[:class]) end
536
548
  @f.tag(:div, {:class=>"foo"}, o.method(:foo)).to_s.must_equal '<div class="foo"><input class="form-control foo" type="text"/></div>'
537
549
  end
538
550
 
@@ -624,7 +636,7 @@ describe "Forme Bootstrap3 (BS3) forms" do
624
636
  end
625
637
 
626
638
  it "inputs should have helper displayed inside wrapper, after error" do
627
- @f.input(:text, :help=>"List type of foo", :error=>'bad', :wrapper=>:li).to_s.must_equal '<li class="has-error"><input class="form-control" type="text"/><span class="help-block with-errors">bad</span><span class="helper">List type of foo</span></li>'
639
+ @f.input(:text, :help=>"List type of foo", :error=>'bad', :wrapper=>:li).to_s.must_equal '<li class="has-error"><input aria-invalid="true" class="form-control" type="text"/><span class="help-block with-errors">bad</span><span class="helper">List type of foo</span></li>'
628
640
  end
629
641
 
630
642
  it "inputs should accept a :formatter option to use a custom formatter" do
@@ -661,7 +673,7 @@ describe "Forme Bootstrap3 (BS3) forms" do
661
673
  end
662
674
 
663
675
  it "inputs should accept a :error_handler option to use a custom error_handler" do
664
- @f.input(:textarea, :error_handler=>proc{|t, i| [t, "!!! #{i.opts[:error]}"]}, :error=>'bar', :id=>:foo).to_s.must_equal '<div class="form-group"><textarea class="form-control" id="foo"></textarea>!!! bar</div>'
676
+ @f.input(:textarea, :error_handler=>proc{|t, i| [t, "!!! #{i.opts[:error]}"]}, :error=>'bar', :id=>:foo).to_s.must_equal '<div class="form-group"><textarea aria-describedby="foo_error_message" aria-invalid="true" class="form-control" id="foo"></textarea>!!! bar</div>'
665
677
  end
666
678
 
667
679
  it "#inputs should accept a :inputs_wrapper option to use a custom inputs_wrapper" do
@@ -679,7 +691,7 @@ describe "Forme Bootstrap3 (BS3) forms" do
679
691
  end
680
692
 
681
693
  it "inputs should accept a :error_handler=>nil option to not use an error_handler" do
682
- @f.input(:textarea, :error_handler=>nil, :error=>'bar', :id=>:foo).to_s.must_equal '<div class="form-group"><textarea class="form-control" id="foo"></textarea></div>'
694
+ @f.input(:textarea, :error_handler=>nil, :error=>'bar', :id=>:foo).to_s.must_equal '<div class="form-group"><textarea aria-invalid="true" class="form-control" id="foo"></textarea></div>'
683
695
  end
684
696
 
685
697
  it "#inputs should accept a :inputs_wrapper=>nil option to not use an inputs_wrapper" do
data/spec/erb_helper.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require_relative 'shared_erb_specs'
2
+
1
3
  ERB_BLOCK = lambda do |r|
2
4
  r.get '' do
3
5
  erb <<END
@@ -65,6 +67,29 @@ END
65
67
  END
66
68
  end
67
69
 
70
+ r.get 'nest_seq_simple' do
71
+ @album = Album.load(:name=>'N', :copies_sold=>2, :id=>1)
72
+ @album.associations[:artist] = Artist.load(:name=>'A', :id=>2)
73
+ @nest = <<END
74
+ n1
75
+ <% f.subform(:artist) do %>
76
+ n2
77
+ <%= f.input(:name2) %>
78
+ n3
79
+ <% end %>
80
+ n4
81
+ END
82
+ erb <<END
83
+ 0
84
+ <% form(@album, :action=>'/baz') do |f| %>
85
+ 1
86
+ <%= erb(@nest, :locals=>{:f=>f}) %>
87
+ 3
88
+ <% end %>
89
+ 4
90
+ END
91
+ end
92
+
68
93
  r.get 'nest_seq' do
69
94
  @album = Album.load(:name=>'N', :copies_sold=>2, :id=>1)
70
95
  @album.associations[:artist] = Artist.load(:name=>'A', :id=>2)
@@ -92,6 +117,50 @@ END
92
117
  END
93
118
  end
94
119
 
120
+ r.get 'grid-block' do
121
+ @album = Album.load(:name=>'N', :copies_sold=>2, :id=>1)
122
+ @album.associations[:artist] = Artist.load(:name=>'A', :id=>2)
123
+ erb <<END
124
+ 0
125
+ <% form(@album, {:action=>'/baz'}, :button=>'Sub') do |f| %>
126
+ 1
127
+ <% f.subform(:artist, :inputs=>[:name], :legend=>'Foo', :grid=>true, :labels=>%w'Name') do %>
128
+ 2
129
+ <% end %>
130
+ 3
131
+ <% end %>
132
+ 4
133
+ END
134
+ end
135
+
136
+ r.get 'grid-noblock' do
137
+ @album = Album.load(:name=>'N', :copies_sold=>2, :id=>1)
138
+ @album.associations[:artist] = Artist.load(:name=>'A', :id=>2)
139
+ erb <<END
140
+ 0
141
+ <% form(@album, {:action=>'/baz'}, :button=>'Sub') do |f| %>
142
+ 1
143
+ <%= f.subform(:artist, :inputs=>[:name], :legend=>'Foo', :grid=>true, :labels=>%w'Name') %>
144
+ 2
145
+ <% end %>
146
+ 3
147
+ END
148
+ end
149
+
150
+ r.get 'grid-noblock-multiple' do
151
+ @artist = Artist.load(:name=>'A', :id=>2)
152
+ @artist.associations[:albums] = [Album.load(:name=>'N', :copies_sold=>2, :id=>1)]
153
+ erb <<END
154
+ 0
155
+ <% form(@artist, {:action=>'/baz'}, :button=>'Sub') do |f| %>
156
+ 1
157
+ <%= f.subform(:albums, :inputs=>[:name, :copies_sold], :legend=>'Foo', :grid=>true, :labels=>%w'Name Copies') %>
158
+ 2
159
+ <% end %>
160
+ 3
161
+ END
162
+ end
163
+
95
164
  r.get 'hash' do
96
165
  erb "<% form({:action=>'/baz'}, :obj=>[:foo]) do |f| %> <%= f.input(:first) %> <% end %>"
97
166
  end
@@ -127,61 +196,3 @@ END
127
196
  erb "<%= form(:action=>'/baz') %>"
128
197
  end
129
198
  end
130
-
131
- module FormeErbSpecs
132
- extend Minitest::Spec::DSL
133
-
134
- before do
135
- o = Object.new
136
- def o.puts(*) end
137
- @rack = {'rack.input'=>'', 'REQUEST_METHOD'=>'GET', 'rack.errors'=>o, 'SCRIPT_NAME'=>''}
138
- end
139
-
140
- it "#form should add start and end tags and yield Forme::Form instance" do
141
- sin_get('/').must_equal '<form action="/baz"> <p>FBB</p> <input id="first" name="first" type="text" value="foo"/> <input id="last" name="last" type="text" value="bar"/> <input type="submit" value="Save"/> </form>'
142
- end
143
-
144
- it "#form should have inputs work with a block" do
145
- sin_get('/inputs_block').must_equal '<form action="/baz"><fieldset class="inputs"><legend>FBB</legend> <input id="last" name="last" type="text" value="bar"/> </fieldset></form>'
146
- end
147
-
148
- it "#form should have inputs with fieldset_ol wrapper work with block" do
149
- sin_get('/inputs_block_wrapper').must_equal '<form action="/baz"><fieldset class="inputs"><legend>FBB</legend><ol> <input id="last" name="last" type="text" value="bar"/> </ol></fieldset></form>'
150
- end
151
-
152
- it "#form should add start and end tags and yield Forme::Form instance" do
153
- sin_get('/nest').must_equal '<form action="/baz"> <p>FBB</p> <div> <input id="first" name="first" type="text" value="foo"/> <input id="last" name="last" type="text" value="bar"/> </div> </form>'
154
- end
155
-
156
- it "#form should correctly handle situation where multiple templates are used with same form object" do
157
- sin_get('/nest_sep').must_equal '0 <form action="/baz"> 1 <p>FBB</p> 2 n1 <div> n2 <input id="first" name="first" type="text" value="foo"/> <input id="last" name="last" type="text" value="bar"/> n3 </div> n4 <fieldset class="inputs"><legend>Foo</legend><input id="first" name="first" type="text" value="foo"/><input id="last" name="last" type="text" value="bar"/></fieldset> n5 3 </form>4'
158
- end
159
-
160
- it "#form should correctly handle situation Sequel integration with subforms where multiple templates are used with same form object" do
161
- sin_get('/nest_seq').sub(%r{<input name="_csrf" type="hidden" value="([^"]+)"/>}, '<input name="_csrf" type="hidden" value="csrf"/>').must_equal '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" maxlength="255" 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"/><fieldset class="inputs"><legend>Artist</legend> n2 <label>Name2: <input id="album_artist_attributes_name2" name="album[artist_attributes][name2]" type="text" value="A2"/></label> n3 </fieldset> 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'
162
- end
163
-
164
- it "#form should accept two hashes instead of requiring obj as first argument" do
165
- sin_get('/hash').must_equal '<form action="/baz"> <input id="first" name="first" type="text" value="foo"/> </form>'
166
- end
167
-
168
- it "#form should deal with emitted code" do
169
- sin_get('/legend').must_equal '<form action="/baz"> <p>FBB</p> <fieldset class="inputs"><legend>Foo</legend><input id="first" name="first" type="text" value="foo"/><input id="last" name="last" type="text" value="bar"/></fieldset> <p>FBB2</p> </form>'
170
- end
171
-
172
- it "#form should work with :inputs, :button, and :legend options" do
173
- sin_get('/combined').must_equal '<form action="/baz"><fieldset class="inputs"><legend>123</legend><input id="first" name="first" type="text" value="foo"/></fieldset> <p>FBB</p> <input id="last" name="last" type="text" value="bar"/> <input type="submit" value="xyz"/></form>'
174
- end
175
-
176
- it "#form should work without a block" do
177
- sin_get('/noblock').must_equal '<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>'
178
- end
179
-
180
- it "#form should work without a block and still have hidden tags emitted" do
181
- sin_get('/noblock_post').sub(%r{<input name=\"_csrf\" type=\"hidden\" value=\"([^\"]+)\"/>}, "<input name=\"_csrf\" type=\"hidden\" value=\"csrf\"/>").must_equal '<form method="post"><input name="_csrf" type="hidden" value="csrf"/><input type="submit" value="xyz"/></form>'
182
- end
183
-
184
- it "#form with an empty form should work" do
185
- sin_get('/noblock_empty').must_equal '<form action="/baz"></form>'
186
- end
187
- end
@@ -0,0 +1,198 @@
1
+ require_relative 'shared_erb_specs'
2
+
3
+ ERUBI_CAPTURE_BLOCK = lambda do |r|
4
+ r.get '' do
5
+ erb <<END
6
+ <%|= form([:foo, :bar], :action=>'/baz') do |f| %>
7
+ <p>FBB</p>
8
+ <%= f.input(:first) %>
9
+ <%= f.input(:last) %>
10
+ <%= f.button('Save') %>
11
+ <%| end %>
12
+ END
13
+ end
14
+
15
+ r.get 'inputs_block' do
16
+ erb <<END
17
+ <%|= form([:foo, :bar], :action=>'/baz') do |f| %><%|= f.inputs(:legend=>'FBB') do %>
18
+ <%= f.input(:last) %>
19
+ <%| end %><%| end %>
20
+ END
21
+ end
22
+
23
+ r.get 'inputs_block_wrapper' do
24
+ erb <<END
25
+ <%|= form([:foo, :bar], {:action=>'/baz'}, :inputs_wrapper=>:fieldset_ol) do |f| %><%|= f.inputs(:legend=>'FBB') do %>
26
+ <%= f.input(:last) %>
27
+ <%| end %><%| end %>
28
+ END
29
+ end
30
+
31
+ r.get 'nest' do
32
+ erb <<END
33
+ <%|= form([:foo, :bar], :action=>'/baz') do |f| %>
34
+ <%= f.tag(:p, {}, 'FBB') %>
35
+ <%|= f.tag(:div) do %>
36
+ <%= f.input(:first) %>
37
+ <%= f.input(:last) %>
38
+ <%| end %>
39
+
40
+ <%| end %>
41
+ END
42
+ end
43
+
44
+ r.get 'nest_sep' do
45
+ @nest = <<END
46
+ n1
47
+ <%|= f.tag(:div) do %>
48
+ n2
49
+ <%= f.input(:first) %>
50
+ <%= f.input(:last) %>
51
+ n3
52
+ <%| end %>
53
+ n4
54
+ <%= f.inputs([:first, :last], :legend=>'Foo') %>
55
+ n5
56
+ END
57
+ erb <<END
58
+ 0
59
+ <%|= form([:foo, :bar], :action=>'/baz') do |f| %>
60
+ 1
61
+ <%= f.tag(:p, {}, 'FBB') %>
62
+ 2
63
+ <%= erb(@nest, :locals=>{:f=>f}) %>
64
+ 3
65
+ <%| end %>
66
+ 4
67
+ END
68
+ end
69
+
70
+ r.get 'nest_seq_simple' do
71
+ @album = Album.load(:name=>'N', :copies_sold=>2, :id=>1)
72
+ @album.associations[:artist] = Artist.load(:name=>'A', :id=>2)
73
+ @nest = <<END
74
+ n1
75
+ <%|= f.subform(:artist) do %>
76
+ n2
77
+ <%= f.input(:name2) %>
78
+ n3
79
+ <%| end %>
80
+ n4
81
+ END
82
+ erb <<END
83
+ 0
84
+ <%|= form(@album, :action=>'/baz') do |f| %>
85
+ 1
86
+ <%= erb(@nest, :locals=>{:f=>f}) %>
87
+ 3
88
+ <%| end %>
89
+ 4
90
+ END
91
+ end
92
+
93
+ r.get 'nest_seq' do
94
+ @album = Album.load(:name=>'N', :copies_sold=>2, :id=>1)
95
+ @album.associations[:artist] = Artist.load(:name=>'A', :id=>2)
96
+ @nest = <<END
97
+ n1
98
+ <%|= f.subform(:artist) do %>
99
+ n2
100
+ <%= f.input(:name2) %>
101
+ n3
102
+ <%| end %>
103
+ n4
104
+ <%= f.subform(:artist, :inputs=>[:name3], :legend=>'Bar') %>
105
+ n5
106
+ END
107
+ erb <<END
108
+ 0
109
+ <%|= form(@album, :action=>'/baz') do |f| %>
110
+ 1
111
+ <%= f.subform(:artist, :inputs=>[:name], :legend=>'Foo') %>
112
+ 2
113
+ <%= erb(@nest, :locals=>{:f=>f}) %>
114
+ 3
115
+ <%| end %>
116
+ 4
117
+ END
118
+ end
119
+
120
+ r.get 'grid-block' do
121
+ @album = Album.load(:name=>'N', :copies_sold=>2, :id=>1)
122
+ @album.associations[:artist] = Artist.load(:name=>'A', :id=>2)
123
+ erb <<END
124
+ 0
125
+ <%|= form(@album, {:action=>'/baz'}, :button=>'Sub') do |f| %>
126
+ 1
127
+ <%|= f.subform(:artist, :inputs=>[:name], :legend=>'Foo', :grid=>true, :labels=>%w'Name') do %>
128
+ 2
129
+ <%| end %>
130
+ 3
131
+ <%| end %>
132
+ 4
133
+ END
134
+ end
135
+
136
+ r.get 'grid-noblock' do
137
+ @album = Album.load(:name=>'N', :copies_sold=>2, :id=>1)
138
+ @album.associations[:artist] = Artist.load(:name=>'A', :id=>2)
139
+ erb <<END
140
+ 0
141
+ <%|= form(@album, {:action=>'/baz'}, :button=>'Sub') do |f| %>
142
+ 1
143
+ <%= f.subform(:artist, :inputs=>[:name], :legend=>'Foo', :grid=>true, :labels=>%w'Name') %>
144
+ 2
145
+ <%| end %>
146
+ 3
147
+ END
148
+ end
149
+
150
+ r.get 'grid-noblock-multiple' do
151
+ @artist = Artist.load(:name=>'A', :id=>2)
152
+ @artist.associations[:albums] = [Album.load(:name=>'N', :copies_sold=>2, :id=>1)]
153
+ erb <<END
154
+ 0
155
+ <%|= form(@artist, {:action=>'/baz'}, :button=>'Sub') do |f| %>
156
+ 1
157
+ <%= f.subform(:albums, :inputs=>[:name, :copies_sold], :legend=>'Foo', :grid=>true, :labels=>%w'Name Copies') %>
158
+ 2
159
+ <%| end %>
160
+ 3
161
+ END
162
+ end
163
+
164
+ r.get 'hash' do
165
+ erb "<%|= form({:action=>'/baz'}, :obj=>[:foo]) do |f| %> <%= f.input(:first) %> <%| end %>"
166
+ end
167
+
168
+ r.get 'legend' do
169
+ erb <<END
170
+ <%|= form([:foo, :bar], :action=>'/baz') do |f| %>
171
+ <p>FBB</p>
172
+ <%= f.inputs([:first, :last], :legend=>'Foo') %>
173
+ <p>FBB2</p>
174
+ <%| end %>
175
+ END
176
+ end
177
+
178
+ r.get 'combined' do
179
+ erb <<END
180
+ <%|= form([:foo, :bar], {:action=>'/baz'}, :inputs=>[:first], :button=>'xyz', :legend=>'123') do |f| %>
181
+ <p>FBB</p>
182
+ <%= f.input(:last) %>
183
+ <%| end %>
184
+ END
185
+ end
186
+
187
+ r.get 'noblock' do
188
+ erb "<%= form([:foo, :bar], {:action=>'/baz'}, :inputs=>[:first], :button=>'xyz', :legend=>'123') %>"
189
+ end
190
+
191
+ r.get 'noblock_post' do
192
+ erb "<%= form({:method=>:post}, :button=>'xyz') %>"
193
+ end
194
+
195
+ r.get 'noblock_empty' do
196
+ erb "<%= form(:action=>'/baz') %>"
197
+ end
198
+ end
data/spec/forme_spec.rb CHANGED
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
1
+ require_relative 'spec_helper'
2
2
 
3
3
  describe "Forme plain forms" do
4
4
  def sel(opts, s)
@@ -317,6 +317,10 @@ describe "Forme plain forms" do
317
317
  @f.input(:date, :name=>"foo", :id=>"bar", :as=>:select, :value=>Date.new(2011, 6, 5), :select_options=>{:year=>1970..2020}).to_s.must_equal %{<select id="bar" name="foo[year]">#{sel(1970..2020, 2011)}</select>-<select id="bar_month" name="foo[month]">#{sel(1..12, 6)}</select>-<select id="bar_day" name="foo[day]">#{sel(1..31, 5)}</select>}
318
318
  end
319
319
 
320
+ it "should support :select_options with both values and text for dates when :as=>:select is given" do
321
+ @f.input(:date, :name=>"foo", :id=>"bar", :as=>:select, :value=>Date.new(2011, 6, 5), :select_options=>{:year=>[[2011, 'A'], [2012, 'B']]}).to_s.must_equal %{<select id="bar" name="foo[year]"><option selected="selected" value="2011">A</option><option value="2012">B</option></select>-<select id="bar_month" name="foo[month]">#{sel(1..12, 6)}</select>-<select id="bar_day" name="foo[day]">#{sel(1..31, 5)}</select>}
322
+ end
323
+
320
324
  it "should have explicit labeler and trtd wrapper work with multiple select boxes for dates" do
321
325
  @f.input(:date, :name=>"foo", :id=>"bar", :as=>:select, :value=>Date.new(2011, 6, 5), :wrapper=>:trtd, :labeler=>:explicit, :label=>'Baz').to_s.must_equal %{<tr><td><label class="label-before" for="bar">Baz</label></td><td><select id="bar" name="foo[year]">#{sel(1900..2050, 2011)}</select>-<select id="bar_month" name="foo[month]">#{sel(1..12, 6)}</select>-<select id="bar_day" name="foo[day]">#{sel(1..31, 5)}</select></td></tr>}
322
326
  end
@@ -627,13 +631,19 @@ describe "Forme plain forms" do
627
631
  @f.tag(:textarea, {:name=>:foo}, :bar).to_s.must_equal '<textarea name="foo">bar</textarea>'
628
632
  end
629
633
 
634
+ it "#tag should accept a block" do
635
+ @f.tag(:div){@f.tag(:textarea)}.to_s.must_equal '<div><textarea></textarea></div>'
636
+ @f.tag(:div, :name=>'a'){@f.tag(:textarea)}.to_s.must_equal '<div name="a"><textarea></textarea></div>'
637
+ @f.tag(:div, {:name=>'a'}, ["text"]){@f.tag(:textarea)}.to_s.must_equal '<div name="a">text<textarea></textarea></div>'
638
+ end
639
+
630
640
  it "#tag should accept children as procs" do
631
- @f.tag(:div, {:class=>"foo"}, lambda{|t| t.form.tag(:input, :class=>t.attr[:class])}).to_s.must_equal '<div class="foo"><input class="foo"/></div>'
641
+ @f.tag(:div, {:class=>"foo"}, lambda{|t| t.tag(:input, :class=>t.attr[:class])}).to_s.must_equal '<div class="foo"><input class="foo"/></div>'
632
642
  end
633
643
 
634
644
  it "#tag should accept children as methods" do
635
645
  o = Object.new
636
- def o.foo(t) t.form.tag(:input, :class=>t.attr[:class]) end
646
+ def o.foo(t) t.tag(:input, :class=>t.attr[:class]) end
637
647
  @f.tag(:div, {:class=>"foo"}, o.method(:foo)).to_s.must_equal '<div class="foo"><input class="foo"/></div>'
638
648
  end
639
649
 
@@ -641,6 +651,10 @@ describe "Forme plain forms" do
641
651
  @f.inputs([:textarea, :text]).to_s.must_equal '<fieldset class="inputs"><textarea></textarea><input type="text"/></fieldset>'
642
652
  end
643
653
 
654
+ it "should have an #inputs method for multiple inputs wrapped in a fieldset when using an empty block" do
655
+ @f.inputs([:textarea, :text]){}.to_s.must_equal '<fieldset class="inputs"><textarea></textarea><input type="text"/></fieldset>'
656
+ end
657
+
644
658
  it "should have default #inputs method accept an :attr option" do
645
659
  @f.inputs([:textarea, :text], :legend=>'Inputs', :attr=>{:class=>'foo', :bar=>'baz'}).to_s.must_equal '<fieldset bar="baz" class="foo inputs"><legend>Inputs</legend><textarea></textarea><input type="text"/></fieldset>'
646
660
  end
@@ -801,41 +815,15 @@ describe "Forme plain forms" do
801
815
  proc{@f.input(:textarea, :wrapper=>Object.new).to_s}.must_raise(Forme::Error)
802
816
  proc{@f.input(:textarea, :formatter=>nil).to_s}.must_raise(Forme::Error)
803
817
  end
804
- end
805
-
806
- describe "Forme::Form :hidden_tags option " do
807
- before do
808
- @f = Forme::Form.new
809
- end
810
-
811
- it "should handle hash" do
812
- Forme.form({}, :hidden_tags=>[{:a=>'b'}]).to_s.must_equal '<form><input name="a" type="hidden" value="b"/></form>'
813
- end
814
-
815
- it "should handle array" do
816
- Forme.form({}, :hidden_tags=>[["a ", "b"]]).to_s.must_equal '<form>a b</form>'
817
- end
818
-
819
- it "should handle string" do
820
- Forme.form({}, :hidden_tags=>["a "]).to_s.must_equal '<form>a </form>'
821
- end
822
-
823
- it "should handle proc return hash" do
824
- Forme.form({}, :hidden_tags=>[lambda{|tag| {:a=>'b'}}]).to_s.must_equal '<form><input name="a" type="hidden" value="b"/></form>'
825
- end
826
-
827
- it "should handle proc return tag" do
828
- Forme.form({:method=>'post'}, :hidden_tags=>[lambda{|tag| tag.form._tag(tag.attr[:method])}]).to_s.must_equal '<form method="post"><post></post></form>'
829
- end
830
818
 
831
- it "should raise error for unhandled object" do
832
- proc{Forme.form({}, :hidden_tags=>[Object.new])}.must_raise Forme::Error
819
+ it "should handle :before and :after hook options" do
820
+ Forme.form({}, :before=>lambda{|f| f.tag(:input, :type=>:hidden, :name=>:a, :value=>'b')}, :after=>lambda{|f| f.tag(:input, :type=>:hidden, :name=>:c, :value=>'d')}){|f| f.tag(:input)}.to_s.must_equal '<form><input name="a" type="hidden" value="b"/><input/><input name="c" type="hidden" value="d"/></form>'
833
821
  end
834
822
  end
835
823
 
836
824
  describe "Forme custom" do
837
825
  it "formatters can be specified as a proc" do
838
- Forme::Form.new(:formatter=>proc{|i| i.form._tag(:textarea, i.opts[:name]=>:name)}).input(:text, :name=>'foo').to_s.must_equal '<textarea foo="name"></textarea>'
826
+ Forme::Form.new(:formatter=>proc{|i| i.tag(:textarea, i.opts[:name]=>:name)}).input(:text, :name=>'foo').to_s.must_equal '<textarea foo="name"></textarea>'
839
827
  end
840
828
 
841
829
  it "serializers can be specified as a proc" do
@@ -1052,6 +1040,7 @@ describe "Forme built-in custom" do
1052
1040
  Forme::Form.new(:serializer=>:text).button().to_s.must_equal ""
1053
1041
  Forme::Form.new(:serializer=>:text).inputs([[:textarea, {:label=>"Foo", :value=>"Bar"}]], :legend=>'Baz').to_s.must_equal "Baz\n---\nFoo: Bar\n\n"
1054
1042
  Forme::Form.new(:serializer=>:text).tag(:p){|f| f.input(:textarea, :label=>"Foo", :value=>"Bar")}.to_s.must_equal "Foo: Bar\n\n"
1043
+ Forme::Form.new(:serializer=>:text).tag(:p, {}, ['a']).to_s.must_equal "a"
1055
1044
  end
1056
1045
  end
1057
1046
 
@@ -1,34 +1,48 @@
1
- require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
- require File.join(File.dirname(File.expand_path(__FILE__)), 'sequel_helper.rb')
1
+ require_relative 'spec_helper'
2
+ require_relative 'sequel_helper'
3
3
 
4
- require 'rubygems'
5
4
  begin
6
- require 'action_controller/railtie'
7
- rescue LoadError
8
- warn "unable to load rails, skipping rails spec"
9
- else
10
- begin
11
- require 'active_pack/gem_version'
12
- rescue LoadError
13
- end
14
- require 'forme/rails'
5
+ require 'action_controller/railtie'
6
+
7
+ begin
8
+ require 'active_pack/gem_version'
9
+ rescue LoadError
10
+ end
11
+ require_relative '../lib/forme/rails'
15
12
 
16
- class FormeRails < Rails::Application
17
- routes.append do
18
- %w'index inputs_block inputs_block_wrapper nest nest_sep nest_inputs nest_seq hash legend combined noblock noblock_post safe_buffer'.each do |action|
19
- get action, :controller=>'forme', :action=>action
13
+ if Rails.respond_to?(:version) && Rails.version.start_with?('4')
14
+ # Work around issue in backported openssl environments where
15
+ # secret is 64 bytes intead of 32 bytes
16
+ require 'active_support/message_encryptor'
17
+ def (ActiveSupport::MessageEncryptor).new(secret, *signature_key_or_options)
18
+ obj = allocate
19
+ obj.send(:initialize, secret[0, 32], *signature_key_or_options)
20
+ obj
20
21
  end
21
22
  end
22
- config.active_support.deprecation = :stderr
23
- config.middleware.delete(ActionDispatch::HostAuthorization) if defined?(ActionDispatch::HostAuthorization)
24
- config.middleware.delete(ActionDispatch::ShowExceptions)
25
- config.middleware.delete(Rack::Lock)
26
- config.secret_key_base = 'foo'*15
27
- config.secret_token = 'secret token'*15 if Rails.respond_to?(:version) && Rails.version < '5.2'
28
- config.eager_load = true
29
- initialize!
30
- end
31
23
 
24
+ class FormeRails < Rails::Application
25
+ routes.append do
26
+ %w'index inputs_block inputs_block_wrapper nest nest_sep nest_inputs nest_seq hash legend combined noblock noblock_post safe_buffer'.each do |action|
27
+ get action, :controller=>'forme', :action=>action
28
+ end
29
+ end
30
+ config.active_support.deprecation = :stderr
31
+ config.middleware.delete(ActionDispatch::HostAuthorization) if defined?(ActionDispatch::HostAuthorization)
32
+ config.middleware.delete(ActionDispatch::ShowExceptions)
33
+ config.middleware.delete(Rack::Lock)
34
+ config.secret_key_base = 'foo'*15
35
+ config.secret_token = 'secret token'*15 if Rails.respond_to?(:version) && Rails.version < '5.2'
36
+ config.eager_load = true
37
+ begin
38
+ initialize!
39
+ rescue NoMethodError
40
+ raise LoadError
41
+ end
42
+ end
43
+ rescue LoadError
44
+ warn "unable to load or setup rails, skipping rails spec"
45
+ else
32
46
  class FormeController < ActionController::Base
33
47
  helper Forme::Rails::ERB
34
48