forme 0.10.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 610c1c28c2ed6fc3c4f36d520c4e67fea4fa9c1f
4
- data.tar.gz: 7bb48306b738007c7c40c0673ad964c94f1e4c0d
3
+ metadata.gz: 9fb6883778ebb616402a910c3f46f7bd6ba3734b
4
+ data.tar.gz: aed74dd741f94bb368e97390d14a4000f4b73f39
5
5
  SHA512:
6
- metadata.gz: a6076239cb78c5f4ad271fb77d5b65947f75899243633e49281ae0d2c350799d134d4deb542aa8129e912f427a0a46ce195bd5f21d34904ab1505e738aab75dd
7
- data.tar.gz: de392606364637b2b8999151ff18854bbc0e0b2ec62d54f123ce563b986814e5311154b7c825687274dc16f4e5b579cc0f6a44f5a37c34d08338ee93214cd939
6
+ metadata.gz: 297661c5e245fcbb2f7c671d59c79f77b4d07d3bcded836ace5c7a6049f237b3d7711923178dcfcfdc3ac704a654b491c217112d114f033bd9d241f2c3f9b2f4
7
+ data.tar.gz: 68d7a1d1adbae977f2c26649a72633ae2c954f8701bca70883153eac44fe86113aedd1a47015ad261f2e91ad119945aab56355d54480dda0782bc11896557b26
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ === 1.0.0 (2014-07-30)
2
+
3
+ * Add roda plugin for forme (jeremyevans)
4
+
5
+ * Move forme/sinatra to forme/erb, since it is ERB and not Sinatra specific (jeremyevans)
6
+
7
+ * Do not extend objects at runtime when using the Sequel support (jeremyevans)
8
+
1
9
  === 0.10.0 (2014-07-01)
2
10
 
3
11
  * Use #[] instead of #send to get input value for object forms if object is a hash (jeremyevans)
data/lib/forme.rb CHANGED
@@ -148,6 +148,16 @@ module Forme
148
148
  # Must respond to +call+ or be a registered symbol.
149
149
  attr_reader :serializer
150
150
 
151
+ # Use appropriate Form subclass for object based on the current class, if the
152
+ # object responds to +forme_form_class+.
153
+ def self.new(obj=nil, opts={})
154
+ if obj && obj.respond_to?(:forme_form_class) && !opts[:_forme_form_class_set]
155
+ obj.forme_form_class(self).new(obj, opts.merge(:_forme_form_class_set=>true))
156
+ else
157
+ super
158
+ end
159
+ end
160
+
151
161
  # Create a +Form+ instance and yield it to the block,
152
162
  # injecting the opening form tag before yielding and
153
163
  # the closing form tag after yielding.
@@ -403,6 +413,13 @@ module Forme
403
413
  end
404
414
  end
405
415
 
416
+ # Marks the string as containing already escaped output. Returns string given
417
+ # by default, but subclasses for specific web frameworks can handle automatic
418
+ # html escaping by overriding this.
419
+ def raw_output(s)
420
+ s
421
+ end
422
+
406
423
  # Temporarily override the given object and namespace for the form. Any given
407
424
  # namespaces are appended to the form's current namespace.
408
425
  def with_obj(obj, namespace=nil)
@@ -471,6 +488,16 @@ module Forme
471
488
  ensure
472
489
  @nesting.pop
473
490
  end
491
+
492
+ # Return a serialized opening tag for the given tag.
493
+ def serialize_open(tag)
494
+ raw_output(serializer.serialize_open(tag)) if serializer.respond_to?(:serialize_open)
495
+ end
496
+
497
+ # Return a serialized closing tag for the given tag.
498
+ def serialize_close(tag)
499
+ raw_output(serializer.serialize_close(tag)) if serializer.respond_to?(:serialize_close)
500
+ end
474
501
  end
475
502
 
476
503
  # High level abstract tag form, transformed by formatters into the lower
@@ -510,7 +537,7 @@ module Forme
510
537
 
511
538
  # Return a string containing the serialized content of the receiver.
512
539
  def to_s
513
- Forme.transform(:serializer, @opts, @form_opts, self)
540
+ form.raw_output(Forme.transform(:serializer, @opts, @form_opts, self))
514
541
  end
515
542
 
516
543
  # Transform the receiver into a lower level +Tag+ form (or an array
@@ -559,7 +586,7 @@ module Forme
559
586
 
560
587
  # Return a string containing the serialized content of the receiver.
561
588
  def to_s
562
- Forme.transform(:serializer, @opts, @form.opts, self)
589
+ form.raw_output(Forme.transform(:serializer, @opts, @form.opts, self))
563
590
  end
564
591
 
565
592
  private
data/lib/forme/erb.rb ADDED
@@ -0,0 +1,104 @@
1
+ require 'forme'
2
+
3
+ module Forme
4
+ module ERB
5
+ HIDDEN_TAGS = []
6
+
7
+ # Add a hidden tag proc that will be used for all forms created via Forme::ERB::Helper#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
+
22
+ # Subclass used when using Forme ERB integration.
23
+ # Handles integrating into the view template so that
24
+ # methods with blocks can inject strings into the output.
25
+ class Form < ::Forme::Form
26
+ # Template output object, where serialized output gets
27
+ # injected.
28
+ attr_reader :output
29
+
30
+ # Set the template output object when initializing.
31
+ def initialize(*)
32
+ super
33
+ @output = @opts[:output] ? @opts[:output] : ''
34
+ end
35
+
36
+ # Serialize the tag and inject it into the output.
37
+ def emit(tag)
38
+ output << tag.to_s
39
+ end
40
+
41
+ # Capture the inside of the inputs, injecting it into the template
42
+ # if a block is given, or returning it as a string if not.
43
+ def inputs(*a, &block)
44
+ if block
45
+ capture(block){super}
46
+ else
47
+ capture{super}
48
+ end
49
+ end
50
+
51
+ # Capture the inside of the form, injecting it into the template if
52
+ # a block is given, or returning it as a string if not.
53
+ def form(*a, &block)
54
+ if block
55
+ capture(block){super}
56
+ else
57
+ super
58
+ end
59
+ end
60
+
61
+ # If a block is given, inject an opening tag into the
62
+ # output, inject any given children into the output, yield to the
63
+ # block, inject a closing tag into the output.
64
+ # If a block is not given, just return the tag created.
65
+ def tag(type, attr={}, children=[], &block)
66
+ tag = _tag(type, attr, children)
67
+ if block
68
+ capture(block) do
69
+ emit(serialize_open(tag))
70
+ Array(tag.children).each{|c| emit(c)}
71
+ yield self
72
+ emit(serialize_close(tag))
73
+ end
74
+ else
75
+ tag
76
+ end
77
+ end
78
+
79
+ def capture(block='') # :nodoc:
80
+ buf_was, @output = @output, block.is_a?(Proc) ? (eval("@_out_buf", block.binding) || @output) : block
81
+ yield
82
+ ret = @output
83
+ @output = buf_was
84
+ ret
85
+ end
86
+ end
87
+
88
+ # This is the module used to add the Forme integration
89
+ # to ERB.
90
+ module Helper
91
+ # Create a +Form+ object tied to the current output buffer,
92
+ # using the standard ERB hidden tags.
93
+ def form(obj=nil, attr={}, opts={}, &block)
94
+ if block
95
+ h = {:output=>@_out_buf, :hidden_tags=>Forme::ERB::HIDDEN_TAGS, :env=>env}
96
+ (obj.is_a?(Hash) ? attr = attr.merge(h) : opts = opts.merge(h))
97
+ Form.form(obj, attr, opts, &block)
98
+ else
99
+ Form.form(obj, attr, opts)
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
data/lib/forme/rails.rb CHANGED
@@ -38,7 +38,7 @@ module Forme
38
38
  # Serialize and mark as already escaped the string version of
39
39
  # the input.
40
40
  def emit(tag)
41
- template.output_buffer << template.raw(tag.to_s)
41
+ template.output_buffer << tag.to_s
42
42
  end
43
43
 
44
44
  # Capture the inputs into a new output buffer, and return
@@ -63,12 +63,17 @@ module Forme
63
63
 
64
64
  # Return a string version of the input that is already marked as safe.
65
65
  def input(*)
66
- template.raw(super.to_s)
66
+ super.to_s
67
67
  end
68
68
 
69
69
  # Return a string version of the button that is already marked as safe.
70
70
  def button(*)
71
- template.raw(super.to_s)
71
+ super.to_s
72
+ end
73
+
74
+ # Use the template's raw method to mark the given string as html safe.
75
+ def raw_output(s)
76
+ template.raw(s)
72
77
  end
73
78
 
74
79
  # If a block is given, create a new output buffer and make sure all the
@@ -79,37 +84,22 @@ module Forme
79
84
  if block_given?
80
85
  template.send(:with_output_buffer){tag_(type, attr, children, &block)}
81
86
  else
82
- tag = _tag(type, attr, children)
83
- template.raw(tag.to_s)
87
+ _tag(type, attr, children).to_s
84
88
  end
85
89
  end
86
90
 
87
91
  def tag_(type, attr={}, children=[]) # :nodoc:
88
92
  tag = _tag(type, attr, children)
89
- emit(serializer.serialize_open(tag)) if serializer.respond_to?(:serialize_open)
93
+ emit(serialize_open(tag))
90
94
  Array(tag.children).each{|c| emit(c)}
91
95
  yield self if block_given?
92
- emit(serializer.serialize_close(tag)) if serializer.respond_to?(:serialize_close)
96
+ emit(serialize_close(tag))
93
97
  end
94
98
  end
95
99
 
96
100
  module ERB
97
- # Create a +Form+ object and yield it to the block,
98
- # injecting the opening form tag before yielding and
99
- # the closing form tag after yielding.
100
- #
101
- # Argument Handling:
102
- # No args :: Creates a +Form+ object with no options and not associated
103
- # to an +obj+, and with no attributes in the opening tag.
104
- # 1 hash arg :: Treated as opening form tag attributes, creating a
105
- # +Form+ object with no options.
106
- # 1 non-hash arg :: Treated as the +Form+'s +obj+, with empty options
107
- # and no attributes in the opening tag.
108
- # 2 hash args :: First hash is opening attributes, second hash is +Form+
109
- # options.
110
- # 1 non-hash arg, 1-2 hash args :: First argument is +Form+'s obj, second is
111
- # opening attributes, third if provided is
112
- # +Form+'s options.
101
+ # Create a +Form+ object tied to the current template, and using the standard
102
+ # Rails hidden tags.
113
103
  def forme(obj=nil, attr={}, opts={}, &block)
114
104
  h = {:template=>self, :hidden_tags=>Forme::Rails::HIDDEN_TAGS}
115
105
  (obj.is_a?(Hash) ? attr = attr.merge(h) : opts = opts.merge(h))
data/lib/forme/sinatra.rb CHANGED
@@ -1,124 +1,15 @@
1
- require 'forme'
1
+ require 'forme/erb'
2
2
 
3
3
  module Forme
4
+ # For backwards compatibility only. New code should
5
+ # require 'forme/erb' and include the Forme::ERB::Helper
6
+ # class:
7
+ #
8
+ # helpers Forme::ERB::Helper
4
9
  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
-
22
- # Subclass used when using Forme/Sinatra ERB integration.
23
- # Handles integrating into the view template so that
24
- # methods with blocks can inject strings into the output.
25
- class Form < ::Forme::Form
26
- # Template output object, where serialized output gets
27
- # injected.
28
- attr_reader :output
29
-
30
- # Set the template output object when initializing.
31
- def initialize(*)
32
- super
33
- @output = @opts[:output] ? @opts[:output] : ''
34
- end
35
-
36
- # Serialize the tag and inject it into the output.
37
- def emit(tag)
38
- output << tag.to_s
39
- end
40
-
41
- # Capture the inside of the inputs, injecting it into the template
42
- # if a block is given, or returning it as a string if not.
43
- def inputs(*a, &block)
44
- if block
45
- capture(block){super}
46
- else
47
- capture{super}
48
- end
49
- end
50
-
51
- # Capture the inside of the form, injecting it into the template if
52
- # a block is given, or returning it as a string if not.
53
- def form(*a, &block)
54
- if block
55
- capture(block){super}
56
- else
57
- super
58
- end
59
- end
60
-
61
- # If a block is given, inject an opening tag into the
62
- # output, inject any given children into the output, yield to the
63
- # block, inject a closing tag into the output.
64
- # If a block is not given, just return the tag created.
65
- def tag(type, attr={}, children=[], &block)
66
- tag = _tag(type, attr, children)
67
- if block
68
- capture(block) do
69
- emit(serializer.serialize_open(tag)) if serializer.respond_to?(:serialize_open)
70
- Array(tag.children).each{|c| emit(c)}
71
- yield self
72
- emit(serializer.serialize_close(tag)) if serializer.respond_to?(:serialize_close)
73
- end
74
- else
75
- tag
76
- end
77
- end
78
-
79
- def capture(block='')
80
- buf_was, @output = @output, block.is_a?(Proc) ? (eval("@_out_buf", block.binding) || @output) : block
81
- yield
82
- ret = @output
83
- @output = buf_was
84
- ret
85
- end
86
- end
87
-
88
- # This is the module used to add the Forme integration
89
- # to Sinatra. It should be enabled in Sinatra with the
90
- # following code in your <tt>Sinatra::Base</tt> subclass:
91
- #
92
- # helpers Forme::Sinatra::ERB
93
- module ERB
94
- # Create a +Form+ object and yield it to the block,
95
- # injecting the opening form tag before yielding and
96
- # the closing form tag after yielding.
97
- #
98
- # Argument Handling:
99
- # No args :: Creates a +Form+ object with no options and not associated
100
- # to an +obj+, and with no attributes in the opening tag.
101
- # 1 hash arg :: Treated as opening form tag attributes, creating a
102
- # +Form+ object with no options.
103
- # 1 non-hash arg :: Treated as the +Form+'s +obj+, with empty options
104
- # and no attributes in the opening tag.
105
- # 2 hash args :: First hash is opening attributes, second hash is +Form+
106
- # options.
107
- # 1 non-hash arg, 1-2 hash args :: First argument is +Form+'s obj, second is
108
- # opening attributes, third if provided is
109
- # +Form+'s options.
110
- def form(obj=nil, attr={}, opts={}, &block)
111
- if block
112
- h = {:output=>@_out_buf, :hidden_tags=>Forme::Sinatra::HIDDEN_TAGS, :env=>env}
113
- (obj.is_a?(Hash) ? attr = attr.merge(h) : opts = opts.merge(h))
114
- Form.form(obj, attr, opts, &block)
115
- else
116
- Form.form(obj, attr, opts)
117
- end
118
- end
119
- end
120
-
121
- # Alias of <tt>Forme::Sinatra::ERB</tt>
10
+ ERB = Forme::ERB::Helper
122
11
  Erubis = ERB
12
+ Form = Forme::ERB::Form
13
+ HIDDEN_TAGS = Forme::ERB::HIDDEN_TAGS
123
14
  end
124
15
  end
data/lib/forme/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Forme
2
2
  # Version constant, use <tt>Forme.version</tt> instead.
3
- VERSION = '0.10.0'.freeze
3
+ VERSION = '1.0.0'.freeze
4
4
 
5
5
  # Returns the version as a frozen string (e.g. '0.1.0')
6
6
  def self.version
@@ -0,0 +1,17 @@
1
+ require 'forme/erb'
2
+
3
+ class Roda
4
+ module RodaPlugins
5
+ module Forme
6
+ # Require the render plugin, since forme template integration
7
+ # only makes sense with it.
8
+ def self.load_dependencies(app)
9
+ app.plugin :render
10
+ end
11
+
12
+ InstanceMethods = ::Forme::ERB::Helper
13
+ end
14
+
15
+ register_plugin(:forme, Forme)
16
+ end
17
+ end
@@ -1,4 +1,5 @@
1
1
  require 'forme'
2
+ require 'thread'
2
3
 
3
4
  module Sequel # :nodoc:
4
5
  module Plugins # :nodoc:
@@ -418,9 +419,9 @@ module Sequel # :nodoc:
418
419
  end
419
420
  end
420
421
 
421
- # Helper module used for Sequel/Sinatra forms. Necessary for
422
+ # Helper module used for Sequel forms using ERB template integration. Necessary for
422
423
  # proper subform handling when using such forms with partials.
423
- module SinatraSequelForm
424
+ module ERBSequelForm
424
425
  # Capture the inside of the inputs, injecting it into the template
425
426
  # if a block is given, or returning it as a string if not.
426
427
  def subform(*, &block)
@@ -431,14 +432,31 @@ module Sequel # :nodoc:
431
432
  end
432
433
  end
433
434
  end
435
+ SinatraSequelForm = ERBSequelForm
436
+
437
+ class Form < ::Forme::Form
438
+ include SequelForm
439
+ end
434
440
 
435
441
  module InstanceMethods
442
+ MUTEX = Mutex.new
443
+ FORM_CLASSES = {::Forme::Form=>Form}
444
+
436
445
  # Configure the +form+ with support for <tt>Sequel::Model</tt>
437
446
  # specific code, such as support for nested attributes.
438
447
  def forme_config(form)
439
- form.extend(SequelForm)
440
448
  form.namespaces << model.send(:underscore, model.name)
441
- form.extend(SinatraSequelForm) if defined?(::Forme::Sinatra::Form) && form.is_a?(::Forme::Sinatra::Form)
449
+ end
450
+
451
+ # Return subclass of base form that includes the necessary Sequel form methods.
452
+ def forme_form_class(base)
453
+ unless klass = MUTEX.synchronize{FORM_CLASSES[base]}
454
+ klass = Class.new(base)
455
+ klass.send(:include, SequelForm)
456
+ klass.send(:include, ERBSequelForm) if defined?(::Forme::ERB::Form) && base == ::Forme::ERB::Form
457
+ MUTEX.synchronize{FORM_CLASSES[base] = klass}
458
+ end
459
+ klass
442
460
  end
443
461
 
444
462
  # Return <tt>Forme::Input</tt> instance based on the given arguments.
@@ -0,0 +1,177 @@
1
+ ERB_BLOCK = lambda do |r|
2
+ r.get '' do
3
+ erb <<END
4
+ <% form([:foo, :bar], :action=>'/baz') do |f| %>
5
+ <p>FBB</p>
6
+ <%= f.input(:first) %>
7
+ <%= f.input(:last) %>
8
+ <%= f.button('Save') %>
9
+ <% end %>
10
+ END
11
+ end
12
+
13
+ r.get 'inputs_block' do
14
+ erb <<END
15
+ <% form([:foo, :bar], :action=>'/baz') do |f| %><% f.inputs(:legend=>'FBB') do %>
16
+ <%= f.input(:last) %>
17
+ <% end %><% end %>
18
+ END
19
+ end
20
+
21
+ r.get 'inputs_block_wrapper' do
22
+ erb <<END
23
+ <% form([:foo, :bar], {:action=>'/baz'}, :inputs_wrapper=>:fieldset_ol) do |f| %><% f.inputs(:legend=>'FBB') do %>
24
+ <%= f.input(:last) %>
25
+ <% end %><% end %>
26
+ END
27
+ end
28
+
29
+ r.get 'nest' do
30
+ erb <<END
31
+ <% form([:foo, :bar], :action=>'/baz') do |f| %>
32
+ <%= f.tag(:p, {}, 'FBB') %>
33
+ <% f.tag(:div) do %>
34
+ <%= f.input(:first) %>
35
+ <%= f.input(:last) %>
36
+ <% end %>
37
+
38
+ <% end %>
39
+ END
40
+ end
41
+
42
+ r.get 'nest_sep' do
43
+ @nest = <<END
44
+ n1
45
+ <% f.tag(:div) do %>
46
+ n2
47
+ <%= f.input(:first) %>
48
+ <%= f.input(:last) %>
49
+ n3
50
+ <% end %>
51
+ n4
52
+ <%= f.inputs([:first, :last], :legend=>'Foo') %>
53
+ n5
54
+ END
55
+ erb <<END
56
+ 0
57
+ <% form([:foo, :bar], :action=>'/baz') do |f| %>
58
+ 1
59
+ <%= f.tag(:p, {}, 'FBB') %>
60
+ 2
61
+ <%= erb(@nest, :locals=>{:f=>f}) %>
62
+ 3
63
+ <% end %>
64
+ 4
65
+ END
66
+ end
67
+
68
+ r.get 'nest_seq' do
69
+ @album = Album.load(:name=>'N', :copies_sold=>2, :id=>1)
70
+ @album.associations[:artist] = Artist.load(:name=>'A', :id=>2)
71
+ @nest = <<END
72
+ n1
73
+ <% f.subform(:artist) do %>
74
+ n2
75
+ <%= f.input(:name2) %>
76
+ n3
77
+ <% end %>
78
+ n4
79
+ <%= f.subform(:artist, :inputs=>[:name3], :legend=>'Bar') %>
80
+ n5
81
+ END
82
+ erb <<END
83
+ 0
84
+ <% form(@album, :action=>'/baz') do |f| %>
85
+ 1
86
+ <%= f.subform(:artist, :inputs=>[:name], :legend=>'Foo') %>
87
+ 2
88
+ <%= erb(@nest, :locals=>{:f=>f}) %>
89
+ 3
90
+ <% end %>
91
+ 4
92
+ END
93
+ end
94
+
95
+ r.get 'hash' do
96
+ erb "<% form({:action=>'/baz'}, :obj=>[:foo]) do |f| %> <%= f.input(:first) %> <% end %>"
97
+ end
98
+
99
+ r.get 'legend' do
100
+ erb <<END
101
+ <% form([:foo, :bar], :action=>'/baz') do |f| %>
102
+ <p>FBB</p>
103
+ <%= f.inputs([:first, :last], :legend=>'Foo') %>
104
+ <p>FBB2</p>
105
+ <% end %>
106
+ END
107
+ end
108
+
109
+ r.get 'combined' do
110
+ erb <<END
111
+ <% form([:foo, :bar], {:action=>'/baz'}, :inputs=>[:first], :button=>'xyz', :legend=>'123') do |f| %>
112
+ <p>FBB</p>
113
+ <%= f.input(:last) %>
114
+ <% end %>
115
+ END
116
+ end
117
+
118
+ r.get 'noblock' do
119
+ erb "<%= form([:foo, :bar], {:action=>'/baz'}, :inputs=>[:first], :button=>'xyz', :legend=>'123') %>"
120
+ end
121
+
122
+ r.get 'noblock_empty' do
123
+ erb "<%= form(:action=>'/baz') %>"
124
+ end
125
+ end
126
+
127
+ shared_examples_for "erb integration" do
128
+ before do
129
+ o = Object.new
130
+ def o.puts(*) end
131
+ @rack = {'rack.input'=>'', 'REQUEST_METHOD'=>'GET', 'rack.errors'=>o, 'SCRIPT_NAME'=>''}
132
+ end
133
+
134
+ specify "#form should add start and end tags and yield Forme::Form instance" do
135
+ sin_get('/').should == '<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>'
136
+ end
137
+
138
+ specify "#form should have inputs work with a block" do
139
+ sin_get('/inputs_block').should == '<form action="/baz"><fieldset class="inputs"><legend>FBB</legend> <input id="last" name="last" type="text" value="bar"/> </fieldset></form>'
140
+ end
141
+
142
+ specify "#form should have inputs with fieldset_ol wrapper work with block" do
143
+ sin_get('/inputs_block_wrapper').should == '<form action="/baz"><fieldset class="inputs"><legend>FBB</legend><ol> <input id="last" name="last" type="text" value="bar"/> </ol></fieldset></form>'
144
+ end
145
+
146
+ specify "#form should add start and end tags and yield Forme::Form instance" do
147
+ sin_get('/nest').should == '<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>'
148
+ end
149
+
150
+ specify "#form should correctly handle situation where multiple templates are used with same form object" do
151
+ sin_get('/nest_sep').should == "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"
152
+ end
153
+
154
+ specify "#form should correctly handle situation Sequel integration with subforms where multiple templates are used with same form object" do
155
+ 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\"/><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"
156
+ end
157
+
158
+ specify "#form should accept two hashes instead of requiring obj as first argument" do
159
+ sin_get('/hash').should == '<form action="/baz"> <input id="first" name="first" type="text" value="foo"/> </form>'
160
+ end
161
+
162
+ specify "#form should deal with emitted code" do
163
+ sin_get('/legend').should == '<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>'
164
+ end
165
+
166
+ specify "#form should work with :inputs, :button, and :legend options" do
167
+ sin_get('/combined').should == '<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>'
168
+ end
169
+
170
+ specify "#form should work without a block" do
171
+ 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>'
172
+ end
173
+
174
+ specify "#form with an empty form should work" do
175
+ sin_get('/noblock_empty').should == '<form action="/baz"></form>'
176
+ end
177
+ end
@@ -2,7 +2,11 @@ require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
2
  require File.join(File.dirname(File.expand_path(__FILE__)), 'sequel_helper.rb')
3
3
 
4
4
  require 'rubygems'
5
+ begin
5
6
  require 'action_controller/railtie'
7
+ rescue LoadError
8
+ warn "unable to load rails, skipping rails spec"
9
+ else
6
10
  require 'forme/rails'
7
11
 
8
12
  class FormeRails < Rails::Application
@@ -233,3 +237,4 @@ describe "Forme Rails integration" do
233
237
  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>'
234
238
  end
235
239
  end
240
+ end
@@ -0,0 +1,36 @@
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')
3
+ require File.join(File.dirname(File.expand_path(__FILE__)), 'erb_helper.rb')
4
+
5
+ require 'rubygems'
6
+ begin
7
+ require 'roda'
8
+ require(ENV['ERUBIS'] ? 'erubis' : 'erb')
9
+ require 'rack/csrf'
10
+ rescue LoadError
11
+ warn "unable to load roda or rack/csrf, skipping roda spec"
12
+ else
13
+ class FormeRodaTest < Roda
14
+ plugin :forme
15
+ use Rack::Session::Cookie, :secret => "__a_very_long_string__"
16
+ use Rack::Csrf
17
+
18
+ def erb(s, opts={})
19
+ render(opts.merge(:inline=>s))
20
+ end
21
+
22
+ route do |r|
23
+ instance_exec(r, &ERB_BLOCK)
24
+ end
25
+ end
26
+
27
+ describe "Forme Roda ERB integration" do
28
+ def sin_get(path)
29
+ s = ''
30
+ FormeRodaTest.app.call(@rack.merge('PATH_INFO'=>path))[2].each{|str| s << str}
31
+ s.gsub(/\s+/, ' ').strip
32
+ end
33
+
34
+ it_should_behave_like "erb integration"
35
+ end
36
+ end
@@ -1,12 +1,16 @@
1
1
  require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
2
  require File.join(File.dirname(File.expand_path(__FILE__)), 'sequel_helper.rb')
3
+ require File.join(File.dirname(File.expand_path(__FILE__)), 'erb_helper.rb')
3
4
 
4
5
  require 'rubygems'
6
+ begin
5
7
  require 'sinatra/base'
6
- require 'forme/sinatra'
7
8
  require(ENV['ERUBIS'] ? 'erubis' : 'erb')
8
9
  require 'rack/csrf'
9
-
10
+ rescue LoadError
11
+ warn "unable to load sinatra or rack/csrf, skipping sinatra spec"
12
+ else
13
+ require 'forme/sinatra'
10
14
  class FormeSinatraTest < Sinatra::Base
11
15
  helpers(Forme::Sinatra::ERB)
12
16
  disable :show_exceptions
@@ -14,129 +18,11 @@ class FormeSinatraTest < Sinatra::Base
14
18
  enable :sessions
15
19
  use Rack::Csrf
16
20
 
17
- get '/' do
18
- erb <<END
19
- <% form([:foo, :bar], :action=>'/baz') do |f| %>
20
- <p>FBB</p>
21
- <%= f.input(:first) %>
22
- <%= f.input(:last) %>
23
- <%= f.button('Save') %>
24
- <% end %>
25
- END
26
- end
27
-
28
- get '/inputs_block' do
29
- erb <<END
30
- <% form([:foo, :bar], :action=>'/baz') do |f| %><% f.inputs(:legend=>'FBB') do %>
31
- <%= f.input(:last) %>
32
- <% end %><% end %>
33
- END
34
- end
35
-
36
- get '/inputs_block_wrapper' do
37
- erb <<END
38
- <% form([:foo, :bar], {:action=>'/baz'}, :inputs_wrapper=>:fieldset_ol) do |f| %><% f.inputs(:legend=>'FBB') do %>
39
- <%= f.input(:last) %>
40
- <% end %><% end %>
41
- END
42
- end
43
-
44
- get '/nest' do
45
- erb <<END
46
- <% form([:foo, :bar], :action=>'/baz') do |f| %>
47
- <%= f.tag(:p, {}, 'FBB') %>
48
- <% f.tag(:div) do %>
49
- <%= f.input(:first) %>
50
- <%= f.input(:last) %>
51
- <% end %>
52
-
53
- <% end %>
54
- END
55
- end
56
-
57
- get '/nest_sep' do
58
- @nest = <<END
59
- n1
60
- <% f.tag(:div) do %>
61
- n2
62
- <%= f.input(:first) %>
63
- <%= f.input(:last) %>
64
- n3
65
- <% end %>
66
- n4
67
- <%= f.inputs([:first, :last], :legend=>'Foo') %>
68
- n5
69
- END
70
- erb <<END
71
- 0
72
- <% form([:foo, :bar], :action=>'/baz') do |f| %>
73
- 1
74
- <%= f.tag(:p, {}, 'FBB') %>
75
- 2
76
- <%= erb(@nest, :locals=>{:f=>f}) %>
77
- 3
78
- <% end %>
79
- 4
80
- END
21
+ def self.get(path, &block)
22
+ super("/#{path}", &block)
81
23
  end
82
24
 
83
- get '/nest_seq' do
84
- @album = Album.load(:name=>'N', :copies_sold=>2, :id=>1)
85
- @album.associations[:artist] = Artist.load(:name=>'A', :id=>2)
86
- @nest = <<END
87
- n1
88
- <% f.subform(:artist) do %>
89
- n2
90
- <%= f.input(:name2) %>
91
- n3
92
- <% end %>
93
- n4
94
- <%= f.subform(:artist, :inputs=>[:name3], :legend=>'Bar') %>
95
- n5
96
- END
97
- erb <<END
98
- 0
99
- <% form(@album, :action=>'/baz') do |f| %>
100
- 1
101
- <%= f.subform(:artist, :inputs=>[:name], :legend=>'Foo') %>
102
- 2
103
- <%= erb(@nest, :locals=>{:f=>f}) %>
104
- 3
105
- <% end %>
106
- 4
107
- END
108
- end
109
-
110
- get '/hash' do
111
- erb "<% form({:action=>'/baz'}, :obj=>[:foo]) do |f| %> <%= f.input(:first) %> <% end %>"
112
- end
113
-
114
- get '/legend' do
115
- erb <<END
116
- <% form([:foo, :bar], :action=>'/baz') do |f| %>
117
- <p>FBB</p>
118
- <%= f.inputs([:first, :last], :legend=>'Foo') %>
119
- <p>FBB2</p>
120
- <% end %>
121
- END
122
- end
123
-
124
- get '/combined' do
125
- erb <<END
126
- <% form([:foo, :bar], {:action=>'/baz'}, :inputs=>[:first], :button=>'xyz', :legend=>'123') do |f| %>
127
- <p>FBB</p>
128
- <%= f.input(:last) %>
129
- <% end %>
130
- END
131
- end
132
-
133
- get '/noblock' do
134
- erb "<%= form([:foo, :bar], {:action=>'/baz'}, :inputs=>[:first], :button=>'xyz', :legend=>'123') %>"
135
- end
136
-
137
- get '/noblock_empty' do
138
- erb "<%= form(:action=>'/baz') %>"
139
- end
25
+ instance_exec(self, &ERB_BLOCK)
140
26
  end
141
27
 
142
28
  describe "Forme Sinatra ERB integration" do
@@ -145,53 +31,7 @@ describe "Forme Sinatra ERB integration" do
145
31
  FormeSinatraTest.new.call(@rack.merge('PATH_INFO'=>path))[2].each{|str| s << str}
146
32
  s.gsub(/\s+/, ' ').strip
147
33
  end
148
- before do
149
- o = Object.new
150
- def o.puts(*) end
151
- @rack = {'rack.input'=>'', 'REQUEST_METHOD'=>'GET', 'rack.errors'=>o}
152
- end
153
-
154
- specify "#form should add start and end tags and yield Forme::Form instance" do
155
- sin_get('/').should == '<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>'
156
- end
157
-
158
- specify "#form should have inputs work with a block" do
159
- sin_get('/inputs_block').should == '<form action="/baz"><fieldset class="inputs"><legend>FBB</legend> <input id="last" name="last" type="text" value="bar"/> </fieldset></form>'
160
- end
161
-
162
- specify "#form should have inputs with fieldset_ol wrapper work with block" do
163
- sin_get('/inputs_block_wrapper').should == '<form action="/baz"><fieldset class="inputs"><legend>FBB</legend><ol> <input id="last" name="last" type="text" value="bar"/> </ol></fieldset></form>'
164
- end
165
-
166
- specify "#form should add start and end tags and yield Forme::Form instance" do
167
- sin_get('/nest').should == '<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>'
168
- end
169
34
 
170
- specify "#form should correctly handle situation where multiple templates are used with same form object" do
171
- sin_get('/nest_sep').should == "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"
172
- end
173
-
174
- specify "#form should correctly handle situation Sequel integration with subforms where multiple templates are used with same form object" do
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\"/><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"
176
- end
177
-
178
- specify "#form should accept two hashes instead of requiring obj as first argument" do
179
- sin_get('/hash').should == '<form action="/baz"> <input id="first" name="first" type="text" value="foo"/> </form>'
180
- end
181
-
182
- specify "#form should deal with emitted code" do
183
- sin_get('/legend').should == '<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>'
184
- end
185
-
186
- specify "#form should work with :inputs, :button, and :legend options" do
187
- sin_get('/combined').should == '<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>'
188
- end
189
-
190
- specify "#form should work without a block" do
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>'
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
35
+ it_should_behave_like "erb integration"
36
+ end
197
37
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forme
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-01 00:00:00.000000000 Z
11
+ date: 2014-07-30 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |
14
14
  Forme is a forms library with the following goals:
@@ -30,13 +30,17 @@ files:
30
30
  - README.rdoc
31
31
  - Rakefile
32
32
  - lib/forme.rb
33
+ - lib/forme/erb.rb
33
34
  - lib/forme/rails.rb
34
35
  - lib/forme/sinatra.rb
35
36
  - lib/forme/version.rb
37
+ - lib/roda/plugins/forme.rb
36
38
  - lib/sequel/plugins/forme.rb
39
+ - spec/erb_helper.rb
37
40
  - spec/forme_coverage.rb
38
41
  - spec/forme_spec.rb
39
42
  - spec/rails_integration_spec.rb
43
+ - spec/roda_integration_spec.rb
40
44
  - spec/sequel_helper.rb
41
45
  - spec/sequel_plugin_spec.rb
42
46
  - spec/sinatra_integration_spec.rb