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
@@ -1,7 +1,7 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  require 'rack/utils'
4
- require 'forme/erb_form'
4
+ require_relative '../../forme/template'
5
5
 
6
6
  class Roda
7
7
  module RodaPlugins
@@ -34,74 +34,6 @@ class Roda
34
34
  :missing_namespace=>"no content in expected namespace"
35
35
  }.freeze
36
36
 
37
- # Forme::Form subclass that adds hidden fields with metadata that can be used
38
- # to automatically process form submissions.
39
- class Form < ::Forme::ERB::Form
40
- def initialize(obj, opts=nil)
41
- super
42
- @forme_namespaces = @opts[:namespace]
43
- end
44
-
45
- # Try adding hidden fields to all forms
46
- def form(*)
47
- if block_given?
48
- super do |f|
49
- yield f
50
- hmac_hidden_fields
51
- end
52
- else
53
- t = super
54
- if tags = hmac_hidden_fields
55
- tags.each{|tag| t << tag}
56
- end
57
- t
58
- end
59
- end
60
-
61
- private
62
-
63
- # Add hidden fields with metadata, if the form has an object associated that
64
- # supports the forme_inputs method, and it includes inputs.
65
- def hmac_hidden_fields
66
- if (obj = @opts[:obj]) && obj.respond_to?(:forme_inputs) && (forme_inputs = obj.forme_inputs)
67
- columns = []
68
- valid_values = {}
69
-
70
- forme_inputs.each do |field, input|
71
- next unless col = obj.send(:forme_column_for_input, input)
72
- col = col.to_s
73
- columns << col
74
-
75
- next unless validation = obj.send(:forme_validation_for_input, field, input)
76
- validation[0] = validation[0].to_s
77
- has_nil = false
78
- validation[1] = validation[1].map do |v|
79
- has_nil ||= v.nil?
80
- v.to_s
81
- end
82
- validation[1] << nil if has_nil
83
- valid_values[col] = validation
84
- end
85
-
86
- return if columns.empty?
87
-
88
- data = {}
89
- data['columns'] = columns
90
- data['namespaces'] = @forme_namespaces
91
- data['csrf'] = @opts[:csrf]
92
- data['valid_values'] = valid_values unless valid_values.empty?
93
- data['form_version'] = @opts[:form_version] if @opts[:form_version]
94
-
95
- data = data.to_json
96
- tags = []
97
- tags << tag(:input, :type=>:hidden, :name=>:_forme_set_data, :value=>data)
98
- tags << tag(:input, :type=>:hidden, :name=>:_forme_set_data_hmac, :value=>OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA512.new, @opts[:roda].class.opts[:forme_set_hmac_secret], data))
99
- tags.each{|tag| emit(tag)}
100
- tags
101
- end
102
- end
103
- end
104
-
105
37
  module InstanceMethods
106
38
  # Return hash based on submitted parameters, with :values key
107
39
  # being submitted values for the object, and :validations key
@@ -151,15 +83,46 @@ class Roda
151
83
  raise Error, ERROR_MESSAGES[type]
152
84
  end
153
85
 
154
- # Use form class that adds hidden fields for metadata.
155
- def _forme_form_class
156
- Form
157
- end
158
-
159
86
  # Include a reference to the current scope to the form. This reference is needed
160
87
  # to correctly construct the HMAC.
161
- def _forme_form_options(options)
162
- options.merge!(:roda=>self)
88
+ def _forme_form_options(obj, attr, opts)
89
+ super
90
+
91
+ opts[:_after] = lambda do |form|
92
+ if (obj = form.opts[:obj]) && obj.respond_to?(:forme_inputs) && (forme_inputs = obj.forme_inputs)
93
+ columns = []
94
+ valid_values = {}
95
+
96
+ forme_inputs.each do |field, input|
97
+ next unless col = obj.send(:forme_column_for_input, input)
98
+ col = col.to_s
99
+ columns << col
100
+
101
+ next unless validation = obj.send(:forme_validation_for_input, field, input)
102
+ validation[0] = validation[0].to_s
103
+ has_nil = false
104
+ validation[1] = validation[1].map do |v|
105
+ has_nil ||= v.nil?
106
+ v.to_s
107
+ end
108
+ validation[1] << nil if has_nil
109
+ valid_values[col] = validation
110
+ end
111
+
112
+ return if columns.empty?
113
+
114
+ data = {}
115
+ data['columns'] = columns
116
+ data['namespaces'] = form.opts[:namespace]
117
+ data['csrf'] = form.opts[:csrf]
118
+ data['valid_values'] = valid_values unless valid_values.empty?
119
+ data['form_version'] = form.opts[:form_version] if form.opts[:form_version]
120
+
121
+ data = data.to_json
122
+ form.tag(:input, :type=>:hidden, :name=>:_forme_set_data, :value=>data)
123
+ form.tag(:input, :type=>:hidden, :name=>:_forme_set_data_hmac, :value=>OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA512.new, self.class.opts[:forme_set_hmac_secret], data))
124
+ end
125
+ end
163
126
  end
164
127
 
165
128
  # Internals of forme_parse_hmac and forme_set_hmac.
@@ -1,7 +1,6 @@
1
1
  # frozen-string-literal: true
2
2
 
3
- require 'forme'
4
- require 'thread'
3
+ require_relative '../../forme'
5
4
 
6
5
  module Sequel # :nodoc:
7
6
  module Plugins # :nodoc:
@@ -37,7 +36,8 @@ module Sequel # :nodoc:
37
36
  # of the association for the form's +obj+. Inside the block, calls to
38
37
  # the +input+ and +inputs+ methods for the receiver treat the associated
39
38
  # object as the recevier's +obj+, using name and id attributes that work
40
- # with the Sequel +nested_attributes+ plugin.
39
+ # with the Sequel +nested_attributes+ plugin. Returns the HTML generated by
40
+ # the subform.
41
41
  #
42
42
  # The following options are currently supported:
43
43
  # :inputs :: Automatically call +inputs+ with the given values. Using
@@ -59,45 +59,50 @@ module Sequel # :nodoc:
59
59
  # :skip_primary_key :: Skip adding a hidden primary key field for existing
60
60
  # objects.
61
61
  def subform(association, opts={}, &block)
62
- nested_obj = opts.has_key?(:obj) ? opts[:obj] : obj.send(association)
63
- ref = obj.class.association_reflection(association)
64
- multiple = ref.returns_array?
65
- grid = opts[:grid]
66
- ns = "#{association}_attributes"
62
+ content_added do
63
+ nested_obj = opts.has_key?(:obj) ? opts[:obj] : obj.send(association)
64
+ ref = obj.class.association_reflection(association)
65
+ multiple = ref.returns_array?
66
+ grid = opts[:grid]
67
+ ns = "#{association}_attributes"
67
68
 
68
- contents = proc do
69
69
  send(multiple ? :each_obj : :with_obj, nested_obj, ns) do |no, i|
70
- emit(input(ref.associated_class.primary_key, :type=>:hidden, :label=>nil, :wrapper=>nil)) unless no.new? || opts[:skip_primary_key]
71
- options = opts.dup
72
- if grid
73
- options.delete(:legend)
74
- else
75
- if options.has_key?(:legend)
76
- if options[:legend].respond_to?(:call)
77
- options[:legend] = multiple ? options[:legend].call(no, i) : options[:legend].call(no)
78
- end
70
+ input(ref.associated_class.primary_key, :type=>:hidden, :label=>nil, :wrapper=>nil) unless no.new? || opts[:skip_primary_key]
71
+ end
72
+
73
+ contents = proc do
74
+ send(multiple ? :each_obj : :with_obj, nested_obj, ns) do |no, i|
75
+ options = opts.dup
76
+ if grid
77
+ options.delete(:legend)
79
78
  else
80
- if multiple
81
- options[:legend] = humanize("#{obj.model.send(:singularize, association)} ##{i+1}")
79
+ if options.has_key?(:legend)
80
+ if options[:legend].respond_to?(:call)
81
+ options[:legend] = multiple ? options[:legend].call(no, i) : options[:legend].call(no)
82
+ end
82
83
  else
83
- options[:legend] = humanize(association)
84
+ if multiple
85
+ options[:legend] = humanize("#{obj.model.send(:singularize, association)} ##{i+1}")
86
+ else
87
+ options[:legend] = humanize(association)
88
+ end
84
89
  end
85
90
  end
91
+ options[:subform] = true
92
+
93
+ inputs(options[:inputs]||[], options, &block)
86
94
  end
87
- options[:subform] = true
88
- _inputs(options[:inputs]||[], options, &block)
95
+ end
96
+
97
+ if grid
98
+ labels = opts.fetch(:labels){opts[:inputs].map{|l, *| humanize(l)} if opts[:inputs]}
99
+ legend = opts.fetch(:legend){humanize(association)}
100
+ inputs_opts = opts[:inputs_opts] || {}
101
+ inputs(inputs_opts.merge(:inputs_wrapper=>:table, :nested_inputs_wrapper=>:tr, :wrapper=>:td, :labeler=>nil, :labels=>labels, :legend=>legend), &contents)
102
+ else
103
+ contents.call
89
104
  end
90
105
  end
91
-
92
- if grid
93
- labels = opts.fetch(:labels){opts[:inputs].map{|l, *| humanize(l)} if opts[:inputs]}
94
- legend = opts.fetch(:legend){humanize(association)}
95
- inputs_opts = opts[:inputs_opts] || {}
96
- inputs(inputs_opts.merge(:inputs_wrapper=>:table, :nested_inputs_wrapper=>:tr, :wrapper=>:td, :labeler=>nil, :labels=>labels, :legend=>legend), &contents)
97
- else
98
- contents.call
99
- end
100
- nil
101
106
  end
102
107
  end
103
108
 
@@ -192,6 +197,7 @@ module Sequel # :nodoc:
192
197
 
193
198
  # Set the error option correctly if the field contains errors
194
199
  def handle_errors(f)
200
+ return if opts.has_key?(:error)
195
201
  if e = obj.errors.on(f)
196
202
  opts[:error] = e.join(', ')
197
203
  end
@@ -346,7 +352,7 @@ module Sequel # :nodoc:
346
352
 
347
353
  # Delegate to the +form+.
348
354
  def humanize(s)
349
- form.humanize(s)
355
+ form.respond_to?(:humanize) ? form.humanize(s) : s.to_s.gsub(/_id$/, "").gsub(/_/, " ").capitalize
350
356
  end
351
357
 
352
358
  # If the column allows +NULL+ values, use a three-valued select
@@ -451,21 +457,6 @@ module Sequel # :nodoc:
451
457
  end
452
458
  end
453
459
 
454
- # Helper module used for Sequel forms using ERB template integration. Necessary for
455
- # proper subform handling when using such forms with partials.
456
- module ERBSequelForm
457
- # Capture the inside of the inputs, injecting it into the template
458
- # if a block is given, or returning it as a string if not.
459
- def subform(*, &block)
460
- if block
461
- capture(block){super}
462
- else
463
- capture{super}
464
- end
465
- end
466
- end
467
- SinatraSequelForm = ERBSequelForm
468
-
469
460
  class Form < ::Forme::Form
470
461
  include SequelForm
471
462
  end
@@ -485,7 +476,6 @@ module Sequel # :nodoc:
485
476
  unless klass = MUTEX.synchronize{FORM_CLASSES[base]}
486
477
  klass = Class.new(base)
487
478
  klass.send(:include, SequelForm)
488
- klass.send(:include, ERBSequelForm) if defined?(::Forme::ERB::Form) && base == ::Forme::ERB::Form
489
479
  MUTEX.synchronize{FORM_CLASSES[base] = klass}
490
480
  end
491
481
  klass
@@ -1,5 +1,7 @@
1
+ # frozen-string-literal: true
2
+
1
3
  require 'i18n'
2
- require 'sequel/plugins/forme'
4
+ require_relative 'forme'
3
5
 
4
6
  module Sequel # :nodoc:
5
7
  module Plugins # :nodoc:
@@ -18,6 +18,7 @@ module Sequel # :nodoc:
18
18
  module InstanceMethods
19
19
  # Hash with column name symbol keys and Forme::SequelInput values
20
20
  def forme_inputs
21
+ return (@forme_inputs || {}) if frozen?
21
22
  @forme_inputs ||= {}
22
23
  end
23
24
 
@@ -25,12 +26,13 @@ module Sequel # :nodoc:
25
26
  # is a boolean flag, if true, the uploaded values should be a subset of the allowed values,
26
27
  # otherwise, there should be a single uploaded value that is a member of the allowed values.
27
28
  def forme_validations
29
+ return (@forme_validations || {}) if frozen?
28
30
  @forme_validations ||= {}
29
31
  end
30
32
 
31
33
  # Keep track of the inputs used.
32
34
  def forme_input(_form, field, _opts)
33
- forme_inputs[field] = super
35
+ frozen? ? super : (forme_inputs[field] = super)
34
36
  end
35
37
 
36
38
  # Given the hash of submitted parameters, return a hash containing information on how to
data/spec/all.rb CHANGED
@@ -1,2 +1,2 @@
1
1
  $: << 'lib'
2
- Dir['./spec/*_spec.rb'].each{|f| require f}
2
+ Dir.new(File.dirname(__FILE__)).each{|f| require_relative f if f.end_with?('_spec.rb')}
@@ -1,6 +1,6 @@
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 'forme/bs3'
1
+ require_relative 'spec_helper'
2
+ require_relative 'sequel_helper'
3
+ require_relative '../lib/forme/bs3'
4
4
 
5
5
  describe "Forme Bootstrap3 (BS3) forms" do
6
6
  def sel(opts, s)
@@ -33,7 +33,7 @@ describe "Forme Bootstrap3 (BS3) forms" do
33
33
  end
34
34
 
35
35
  it "should create an input[:text] tag with a label when ':id => bar' with an error" do
36
- @f.input(:text, :label=>"Name", :id=>'bar', :class=>'foo', :error=>'input-text-error').to_s.must_equal '<div class="form-group has-error"><label for="bar">Name</label> <input class="form-control foo" id="bar" type="text"/><span class="help-block with-errors">input-text-error</span></div>'
36
+ @f.input(:text, :label=>"Name", :id=>'bar', :class=>'foo', :error=>'input-text-error').to_s.must_equal '<div class="form-group has-error"><label for="bar">Name</label> <input aria-describedby="bar_error_message" aria-invalid="true" class="form-control foo" id="bar" type="text"/><span class="help-block with-errors">input-text-error</span></div>'
37
37
  end
38
38
 
39
39
  describe 'from a Sequel model' do
@@ -43,7 +43,7 @@ describe "Forme Bootstrap3 (BS3) forms" do
43
43
 
44
44
  it "should correctly handle an input[:text] tag from Sequel model with error" do
45
45
  @ac.errors.add(:name, 'name not valid')
46
- @c.input(:name).to_s.must_equal '<div class="form-group has-error string"><label for="album_name">Name</label> <input class="form-control" id="album_name" maxlength="255" name="album[name]" type="text" value="c"/><span class="help-block with-errors">name not valid</span></div>'
46
+ @c.input(:name).to_s.must_equal '<div class="form-group has-error string"><label for="album_name">Name</label> <input aria-describedby="album_name_error_message" aria-invalid="true" class="form-control" id="album_name" maxlength="255" name="album[name]" type="text" value="c"/><span class="help-block with-errors">name not valid</span></div>'
47
47
  end
48
48
  end
49
49
  end
@@ -66,7 +66,7 @@ describe "Forme Bootstrap3 (BS3) forms" do
66
66
  end
67
67
 
68
68
  it "should create an input[:password] tag with a label when ':id => bar' with an error" do
69
- @f.input(:password, :label=>"Name", :id=>'bar', :class=>'foo', :error=>'input-password-error').to_s.must_equal '<div class="form-group has-error"><label for="bar">Name</label> <input class="form-control foo" id="bar" type="password"/><span class="help-block with-errors">input-password-error</span></div>'
69
+ @f.input(:password, :label=>"Name", :id=>'bar', :class=>'foo', :error=>'input-password-error').to_s.must_equal '<div class="form-group has-error"><label for="bar">Name</label> <input aria-describedby="bar_error_message" aria-invalid="true" class="form-control foo" id="bar" type="password"/><span class="help-block with-errors">input-password-error</span></div>'
70
70
  end
71
71
  end
72
72
 
@@ -88,7 +88,7 @@ describe "Forme Bootstrap3 (BS3) forms" do
88
88
  end
89
89
 
90
90
  it "should create an input[:email] tag with a label when ':id => bar' with an error" do
91
- @f.input(:email, :label=>"Name", :id=>'bar', :class=>'foo', :error=>'input-email-error').to_s.must_equal '<div class="form-group has-error"><label for="bar">Name</label> <input class="form-control foo" id="bar" type="email"/><span class="help-block with-errors">input-email-error</span></div>'
91
+ @f.input(:email, :label=>"Name", :id=>'bar', :class=>'foo', :error=>'input-email-error').to_s.must_equal '<div class="form-group has-error"><label for="bar">Name</label> <input aria-describedby="bar_error_message" aria-invalid="true" class="form-control foo" id="bar" type="email"/><span class="help-block with-errors">input-email-error</span></div>'
92
92
  end
93
93
  end
94
94
 
@@ -110,7 +110,7 @@ describe "Forme Bootstrap3 (BS3) forms" do
110
110
  end
111
111
 
112
112
  it "should create an input[:file] tag with a label when ':id => bar' with an error" do
113
- @f.input(:file, :label=>"Name", :id=>'bar', :class=>'foo', :error=>'input-file-error').to_s.must_equal '<div class="form-group has-error"><label for="bar">Name</label> <input class="foo" id="bar" type="file"/><span class="help-block with-errors">input-file-error</span></div>'
113
+ @f.input(:file, :label=>"Name", :id=>'bar', :class=>'foo', :error=>'input-file-error').to_s.must_equal '<div class="form-group has-error"><label for="bar">Name</label> <input aria-describedby="bar_error_message" aria-invalid="true" class="foo" id="bar" type="file"/><span class="help-block with-errors">input-file-error</span></div>'
114
114
  end
115
115
  end
116
116
 
@@ -132,7 +132,7 @@ describe "Forme Bootstrap3 (BS3) forms" do
132
132
  end
133
133
 
134
134
  it "should create an input[:submit] tag without error message " do
135
- @f.input(:submit, :value=>'Save', :id=>'foo', :error=>'error-message').to_s.must_equal '<input class="btn btn-default" id="foo" type="submit" value="Save"/>'
135
+ @f.input(:submit, :value=>'Save', :id=>'foo', :error=>'error-message').to_s.must_equal '<input aria-describedby="foo_error_message" aria-invalid="true" class="btn btn-default" id="foo" type="submit" value="Save"/>'
136
136
  end
137
137
  end
138
138
 
@@ -154,7 +154,7 @@ describe "Forme Bootstrap3 (BS3) forms" do
154
154
  end
155
155
 
156
156
  it "should create an input[:reset] tag without error message " do
157
- @f.input(:reset, :value=>'Save', :id=>'foo', :error=>'error-message').to_s.must_equal '<input class="btn btn-default" id="foo" type="reset" value="Save"/>'
157
+ @f.input(:reset, :value=>'Save', :id=>'foo', :error=>'error-message').to_s.must_equal '<input aria-describedby="foo_error_message" aria-invalid="true" class="btn btn-default" id="foo" type="reset" value="Save"/>'
158
158
  end
159
159
  end
160
160
 
@@ -180,7 +180,7 @@ describe "Forme Bootstrap3 (BS3) forms" do
180
180
  end
181
181
 
182
182
  it "should create a textarea tag with .has-error and error message when ':error => is-a-string'" do
183
- @f.input(:textarea, :error=>'input-textarea-error').to_s.must_equal '<div class="form-group has-error"><textarea class="form-control"></textarea><span class="help-block with-errors">input-textarea-error</span></div>'
183
+ @f.input(:textarea, :error=>'input-textarea-error').to_s.must_equal '<div class="form-group has-error"><textarea aria-invalid="true" class="form-control"></textarea><span class="help-block with-errors">input-textarea-error</span></div>'
184
184
  end
185
185
 
186
186
  describe 'from a Sequel model' do
@@ -190,7 +190,7 @@ describe "Forme Bootstrap3 (BS3) forms" do
190
190
 
191
191
  it "should correctly handle an input[:text] tag from Sequel model with error" do
192
192
  @ac.errors.add(:name, 'name not valid')
193
- @c.input(:name, :as=>:textarea).to_s.must_equal '<div class="form-group has-error string"><label for="album_name">Name</label> <textarea class="form-control" id="album_name" maxlength="255" name="album[name]">c</textarea><span class="help-block with-errors">name not valid</span></div>'
193
+ @c.input(:name, :as=>:textarea).to_s.must_equal '<div class="form-group has-error string"><label for="album_name">Name</label> <textarea aria-describedby="album_name_error_message" aria-invalid="true" class="form-control" id="album_name" maxlength="255" name="album[name]">c</textarea><span class="help-block with-errors">name not valid</span></div>'
194
194
  end
195
195
  end
196
196
  end
@@ -225,7 +225,7 @@ describe "Forme Bootstrap3 (BS3) forms" do
225
225
  end
226
226
 
227
227
  it "should create a select tag with .has-error and error message when ':error => is-a-string'" do
228
- @f.input(:select, :error=>'input-select-error').to_s.must_equal '<div class="form-group has-error"><select class="form-control"></select><span class="help-block with-errors">input-select-error</span></div>'
228
+ @f.input(:select, :error=>'input-select-error').to_s.must_equal '<div class="form-group has-error"><select aria-invalid="true" class="form-control"></select><span class="help-block with-errors">input-select-error</span></div>'
229
229
  end
230
230
 
231
231
  it "should correctly handle a Sequel model output :as => :select" do
@@ -234,7 +234,7 @@ describe "Forme Bootstrap3 (BS3) forms" do
234
234
 
235
235
  it "should correctly handle a Sequel model output :as => :select with error" do
236
236
  @ac.errors.add(:artist, 'error message')
237
- @c.input(:artist, :as=>:select).to_s.must_equal '<div class="form-group has-error many_to_one"><label for="album_artist_id">Artist</label> <select class="form-control" id="album_artist_id" name="album[artist_id]"><option value=""></option><option value="1">a</option><option selected="selected" value="2">d</option></select><span class="help-block with-errors">error message</span></div>'
237
+ @c.input(:artist, :as=>:select).to_s.must_equal '<div class="form-group has-error many_to_one"><label for="album_artist_id">Artist</label> <select aria-describedby="album_artist_id_error_message" aria-invalid="true" class="form-control" id="album_artist_id" name="album[artist_id]"><option value=""></option><option value="1">a</option><option selected="selected" value="2">d</option></select><span class="help-block with-errors">error message</span></div>'
238
238
  end
239
239
 
240
240
  describe 'from a Sequel model' do
@@ -244,7 +244,7 @@ describe "Forme Bootstrap3 (BS3) forms" do
244
244
 
245
245
  it "should correctly handle a boolean attribute from a Sequel model with an error" do
246
246
  @ac.errors.add(:gold, 'error message')
247
- @c.input(:gold).to_s.must_equal '<div class="boolean form-group has-error"><label for="album_gold">Gold</label> <select class="form-control" id="album_gold" name="album[gold]"><option value=""></option><option selected="selected" value="t">True</option><option value="f">False</option></select><span class="help-block with-errors">error message</span></div>'
247
+ @c.input(:gold).to_s.must_equal '<div class="boolean form-group has-error"><label for="album_gold">Gold</label> <select aria-describedby="album_gold_error_message" aria-invalid="true" class="form-control" id="album_gold" name="album[gold]"><option value=""></option><option selected="selected" value="t">True</option><option value="f">False</option></select><span class="help-block with-errors">error message</span></div>'
248
248
  end
249
249
  end
250
250
  end
@@ -267,7 +267,7 @@ describe "Forme Bootstrap3 (BS3) forms" do
267
267
  end
268
268
 
269
269
  it "should create an input[:checkbox] tag with a label when ':id => bar' with an error" do
270
- @f.input(:checkbox, :label=>"Gold", :id=>'bar', :class=>'foo', :error=>'input-checkbox-error').to_s.must_equal '<div class="has-error"><div class="checkbox"><label for="bar"><input class="foo" id="bar" type="checkbox"/> Gold</label></div><span class="help-block with-errors">input-checkbox-error</span></div>'
270
+ @f.input(:checkbox, :label=>"Gold", :id=>'bar', :class=>'foo', :error=>'input-checkbox-error').to_s.must_equal '<div class="has-error"><div class="checkbox"><label for="bar"><input aria-describedby="bar_error_message" aria-invalid="true" class="foo" id="bar" type="checkbox"/> Gold</label></div><span class="help-block with-errors">input-checkbox-error</span></div>'
271
271
  end
272
272
 
273
273
  describe 'from a Sequel model' do
@@ -277,7 +277,7 @@ describe "Forme Bootstrap3 (BS3) forms" do
277
277
 
278
278
  it "should correctly handle a boolean attribute ':as=>:checkbox' with an error" do
279
279
  @ac.errors.add(:gold, 'error message')
280
- @c.input(:gold, :as=>:checkbox).to_s.must_equal '<div class="boolean has-error"><div class="checkbox"><label for="album_gold"><input id="album_gold_hidden" name="album[gold]" type="hidden" value="f"/><input checked="checked" id="album_gold" name="album[gold]" type="checkbox" value="t"/> Gold</label></div><span class="help-block with-errors">error message</span></div>'
280
+ @c.input(:gold, :as=>:checkbox).to_s.must_equal '<div class="boolean has-error"><div class="checkbox"><label for="album_gold"><input id="album_gold_hidden" name="album[gold]" type="hidden" value="f"/><input aria-describedby="album_gold_error_message" aria-invalid="true" checked="checked" id="album_gold" name="album[gold]" type="checkbox" value="t"/> Gold</label></div><span class="help-block with-errors">error message</span></div>'
281
281
  end
282
282
  end
283
283
  end
@@ -301,7 +301,7 @@ describe "Forme Bootstrap3 (BS3) forms" do
301
301
  end
302
302
 
303
303
  it "should create an input[:radio] tag with a label when ':id => bar' with an error" do
304
- @f.input(:radio, :label=>"Gold", :id=>'bar', :class=>'foo', :error=>'input-radio-error').to_s.must_equal '<div class="has-error"><div class="radio"><label for="bar"><input class="foo" id="bar" type="radio"/> Gold</label></div><span class="help-block with-errors">input-radio-error</span></div>'
304
+ @f.input(:radio, :label=>"Gold", :id=>'bar', :class=>'foo', :error=>'input-radio-error').to_s.must_equal '<div class="has-error"><div class="radio"><label for="bar"><input aria-describedby="bar_error_message" aria-invalid="true" class="foo" id="bar" type="radio"/> Gold</label></div><span class="help-block with-errors">input-radio-error</span></div>'
305
305
  end
306
306
 
307
307
  describe 'from a Sequel model' do
@@ -1,6 +1,6 @@
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 'forme/bs3'
1
+ require_relative 'spec_helper'
2
+ require_relative 'sequel_helper'
3
+ require_relative '../lib/forme/bs3'
4
4
 
5
5
  describe "Forme Sequel::Model BS3 forms" do
6
6
  before do
@@ -263,7 +263,7 @@ describe "Forme Sequel::Model BS3 forms" do
263
263
 
264
264
  it "should handle an error message on the underlying column for pg_array_to_many associations" do
265
265
  @ab.errors.add(:atag_ids, 'tis not valid')
266
- @b.input(:atags).to_s.must_equal '<div class="form-group has-error pg_array_to_many"><label for="album_atag_ids">Atags</label> <select class="form-control" id="album_atag_ids" multiple="multiple" name="album[atag_ids][]"><option selected="selected" value="1">s</option><option selected="selected" value="2">t</option><option value="3">u</option></select><span class="help-block with-errors">tis not valid</span></div>'
266
+ @b.input(:atags).to_s.must_equal '<div class="form-group has-error pg_array_to_many"><label for="album_atag_ids">Atags</label> <select aria-describedby="album_atag_ids_error_message" aria-invalid="true" class="form-control" id="album_atag_ids" multiple="multiple" name="album[atag_ids][]"><option selected="selected" value="1">s</option><option selected="selected" value="2">t</option><option value="3">u</option></select><span class="help-block with-errors">tis not valid</span></div>'
267
267
  @b.input(:atags, :as=>:checkbox).to_s.must_equal '<div class="pg_array_to_many checkboxset has-error"><label>Atags</label><div class="checkbox"><label class="option" for="album_atag_ids_1"><input checked="checked" id="album_atag_ids_1" name="album[atag_ids][]" type="checkbox" value="1"/> s</label></div><div class="checkbox"><label class="option" for="album_atag_ids_2"><input checked="checked" id="album_atag_ids_2" name="album[atag_ids][]" type="checkbox" value="2"/> t</label></div><div class="checkbox"><label class="option" for="album_atag_ids_3"><input id="album_atag_ids_3" name="album[atag_ids][]" type="checkbox" value="3"/> u</label></div><span class="help-block with-errors">tis not valid</span></div>'
268
268
  @b.input(:atags, :as=>:checkbox,:wrapper=>:li).to_s.must_equal '<li class="pg_array_to_many checkboxset has-error"><label>Atags</label><div class="checkbox"><label class="option" for="album_atag_ids_1"><input checked="checked" id="album_atag_ids_1" name="album[atag_ids][]" type="checkbox" value="1"/> s</label></div><div class="checkbox"><label class="option" for="album_atag_ids_2"><input checked="checked" id="album_atag_ids_2" name="album[atag_ids][]" type="checkbox" value="2"/> t</label></div><div class="checkbox"><label class="option" for="album_atag_ids_3"><input id="album_atag_ids_3" name="album[atag_ids][]" type="checkbox" value="3"/> u</label></div><span class="help-block with-errors">tis not valid</span></li>'
269
269
  end
@@ -308,7 +308,7 @@ describe "Forme Sequel::Model BS3 forms" do
308
308
 
309
309
  it "should handle errors on methods not backed by columns" do
310
310
  @ab.errors.add(:artist_name, 'foo')
311
- @b.input(:artist_name).to_s.must_equal '<div class="form-group has-error"><label for="album_artist_name">Artist name</label> <input class="form-control" id="album_artist_name" name="album[artist_name]" type="text" value="a"/><span class="help-block with-errors">foo</span></div>'
311
+ @b.input(:artist_name).to_s.must_equal '<div class="form-group has-error"><label for="album_artist_name">Artist name</label> <input aria-describedby="album_artist_name_error_message" aria-invalid="true" class="form-control" id="album_artist_name" name="album[artist_name]" type="text" value="a"/><span class="help-block with-errors">foo</span></div>'
312
312
  end
313
313
 
314
314
  it "should respect a :type option with a schema type as the input type for methods not backed by columns" do
@@ -323,12 +323,12 @@ describe "Forme Sequel::Model BS3 forms" do
323
323
 
324
324
  it "should correctly show an error message if there is one" do
325
325
  @ab.errors.add(:name, 'tis not valid')
326
- @b.input(:name).to_s.must_equal '<div class="form-group has-error string"><label for="album_name">Name</label> <input class="form-control" id="album_name" maxlength="255" name="album[name]" type="text" value="b"/><span class="help-block with-errors">tis not valid</span></div>'
326
+ @b.input(:name).to_s.must_equal '<div class="form-group has-error string"><label for="album_name">Name</label> <input aria-describedby="album_name_error_message" aria-invalid="true" class="form-control" id="album_name" maxlength="255" name="album[name]" type="text" value="b"/><span class="help-block with-errors">tis not valid</span></div>'
327
327
  end
328
328
 
329
329
  it "should correctly show an error message for many_to_one associations if there is one" do
330
330
  @ab.errors.add(:artist_id, 'tis not valid')
331
- @b.input(:artist).to_s.must_equal '<div class="form-group has-error many_to_one"><label for="album_artist_id">Artist</label> <select class="form-control" id="album_artist_id" name="album[artist_id]"><option value=""></option><option selected="selected" value="1">a</option><option value="2">d</option></select><span class="help-block with-errors">tis not valid</span></div>'
331
+ @b.input(:artist).to_s.must_equal '<div class="form-group has-error many_to_one"><label for="album_artist_id">Artist</label> <select aria-describedby="album_artist_id_error_message" aria-invalid="true" class="form-control" id="album_artist_id" name="album[artist_id]"><option value=""></option><option selected="selected" value="1">a</option><option value="2">d</option></select><span class="help-block with-errors">tis not valid</span></div>'
332
332
  end
333
333
 
334
334
  it "should raise an error for unhandled associations" do
@@ -390,19 +390,19 @@ describe "Forme Sequel::Model BS3 forms" do
390
390
  end
391
391
 
392
392
  it "should use allow nested forms with one_to_many associations" do
393
- Forme.form(@ab, {},{:config=>:bs3}){|f| f.subform(:tracks){f.input(:name)}}.to_s.must_equal '<form class="forme album" method="post"><input id="album_tracks_attributes_0_id" name="album[tracks_attributes][0][id]" type="hidden" value="1"/><fieldset class="inputs"><legend>Track #1</legend><div class="form-group string"><label for="album_tracks_attributes_0_name">Name</label> <input class="form-control" id="album_tracks_attributes_0_name" maxlength="255" name="album[tracks_attributes][0][name]" type="text" value="m"/></div></fieldset><input id="album_tracks_attributes_1_id" name="album[tracks_attributes][1][id]" type="hidden" value="2"/><fieldset class="inputs"><legend>Track #2</legend><div class="form-group string"><label for="album_tracks_attributes_1_name">Name</label> <input class="form-control" id="album_tracks_attributes_1_name" maxlength="255" name="album[tracks_attributes][1][name]" type="text" value="n"/></div></fieldset></form>'
393
+ Forme.form(@ab, {},{:config=>:bs3}){|f| f.subform(:tracks){f.input(:name)}}.to_s.must_equal '<form class="forme album" method="post"><input id="album_tracks_attributes_0_id" name="album[tracks_attributes][0][id]" type="hidden" value="1"/><input id="album_tracks_attributes_1_id" name="album[tracks_attributes][1][id]" type="hidden" value="2"/><fieldset class="inputs"><legend>Track #1</legend><div class="form-group string"><label for="album_tracks_attributes_0_name">Name</label> <input class="form-control" id="album_tracks_attributes_0_name" maxlength="255" name="album[tracks_attributes][0][name]" type="text" value="m"/></div></fieldset><fieldset class="inputs"><legend>Track #2</legend><div class="form-group string"><label for="album_tracks_attributes_1_name">Name</label> <input class="form-control" id="album_tracks_attributes_1_name" maxlength="255" name="album[tracks_attributes][1][name]" type="text" value="n"/></div></fieldset></form>'
394
394
  end
395
395
 
396
396
  it "should support :obj option for *_to_many associations" do
397
- Forme.form(@ab, {},{:config=>:bs3}){|f| f.subform(:tracks, :obj=>[Track.new(:name=>'x'), Track.load(:id=>5, :name=>'y')]){f.input(:name)}}.to_s.must_equal '<form class="forme album" method="post"><fieldset class="inputs"><legend>Track #1</legend><div class="form-group string"><label for="album_tracks_attributes_0_name">Name</label> <input class="form-control" id="album_tracks_attributes_0_name" maxlength="255" name="album[tracks_attributes][0][name]" type="text" value="x"/></div></fieldset><input id="album_tracks_attributes_1_id" name="album[tracks_attributes][1][id]" type="hidden" value="5"/><fieldset class="inputs"><legend>Track #2</legend><div class="form-group string"><label for="album_tracks_attributes_1_name">Name</label> <input class="form-control" id="album_tracks_attributes_1_name" maxlength="255" name="album[tracks_attributes][1][name]" type="text" value="y"/></div></fieldset></form>'
397
+ Forme.form(@ab, {},{:config=>:bs3}){|f| f.subform(:tracks, :obj=>[Track.new(:name=>'x'), Track.load(:id=>5, :name=>'y')]){f.input(:name)}}.to_s.must_equal '<form class="forme album" method="post"><input id="album_tracks_attributes_1_id" name="album[tracks_attributes][1][id]" type="hidden" value="5"/><fieldset class="inputs"><legend>Track #1</legend><div class="form-group string"><label for="album_tracks_attributes_0_name">Name</label> <input class="form-control" id="album_tracks_attributes_0_name" maxlength="255" name="album[tracks_attributes][0][name]" type="text" value="x"/></div></fieldset><fieldset class="inputs"><legend>Track #2</legend><div class="form-group string"><label for="album_tracks_attributes_1_name">Name</label> <input class="form-control" id="album_tracks_attributes_1_name" maxlength="255" name="album[tracks_attributes][1][name]" type="text" value="y"/></div></fieldset></form>'
398
398
  end
399
399
 
400
400
  it "should auto number legends when using subform with inputs for *_to_many associations" do
401
- Forme.form(@ab, {},{:config=>:bs3}){|f| f.subform(:tracks, :inputs=>[:name])}.to_s.must_equal '<form class="forme album" method="post"><input id="album_tracks_attributes_0_id" name="album[tracks_attributes][0][id]" type="hidden" value="1"/><fieldset class="inputs"><legend>Track #1</legend><div class="form-group string"><label for="album_tracks_attributes_0_name">Name</label> <input class="form-control" id="album_tracks_attributes_0_name" maxlength="255" name="album[tracks_attributes][0][name]" type="text" value="m"/></div></fieldset><input id="album_tracks_attributes_1_id" name="album[tracks_attributes][1][id]" type="hidden" value="2"/><fieldset class="inputs"><legend>Track #2</legend><div class="form-group string"><label for="album_tracks_attributes_1_name">Name</label> <input class="form-control" id="album_tracks_attributes_1_name" maxlength="255" name="album[tracks_attributes][1][name]" type="text" value="n"/></div></fieldset></form>'
401
+ Forme.form(@ab, {},{:config=>:bs3}){|f| f.subform(:tracks, :inputs=>[:name])}.to_s.must_equal '<form class="forme album" method="post"><input id="album_tracks_attributes_0_id" name="album[tracks_attributes][0][id]" type="hidden" value="1"/><input id="album_tracks_attributes_1_id" name="album[tracks_attributes][1][id]" type="hidden" value="2"/><fieldset class="inputs"><legend>Track #1</legend><div class="form-group string"><label for="album_tracks_attributes_0_name">Name</label> <input class="form-control" id="album_tracks_attributes_0_name" maxlength="255" name="album[tracks_attributes][0][name]" type="text" value="m"/></div></fieldset><fieldset class="inputs"><legend>Track #2</legend><div class="form-group string"><label for="album_tracks_attributes_1_name">Name</label> <input class="form-control" id="album_tracks_attributes_1_name" maxlength="255" name="album[tracks_attributes][1][name]" type="text" value="n"/></div></fieldset></form>'
402
402
  end
403
403
 
404
404
  it "should support callable :legend option when using subform with inputs for *_to_many associations" do
405
- Forme.form(@ab, {},{:config=>:bs3}){|f| f.subform(:tracks, :inputs=>[:name], :legend=>proc{|o, i| "Track #{i} (#{o.name})"})}.to_s.must_equal '<form class="forme album" method="post"><input id="album_tracks_attributes_0_id" name="album[tracks_attributes][0][id]" type="hidden" value="1"/><fieldset class="inputs"><legend>Track 0 (m)</legend><div class="form-group string"><label for="album_tracks_attributes_0_name">Name</label> <input class="form-control" id="album_tracks_attributes_0_name" maxlength="255" name="album[tracks_attributes][0][name]" type="text" value="m"/></div></fieldset><input id="album_tracks_attributes_1_id" name="album[tracks_attributes][1][id]" type="hidden" value="2"/><fieldset class="inputs"><legend>Track 1 (n)</legend><div class="form-group string"><label for="album_tracks_attributes_1_name">Name</label> <input class="form-control" id="album_tracks_attributes_1_name" maxlength="255" name="album[tracks_attributes][1][name]" type="text" value="n"/></div></fieldset></form>'
405
+ Forme.form(@ab, {},{:config=>:bs3}){|f| f.subform(:tracks, :inputs=>[:name], :legend=>proc{|o, i| "Track #{i} (#{o.name})"})}.to_s.must_equal '<form class="forme album" method="post"><input id="album_tracks_attributes_0_id" name="album[tracks_attributes][0][id]" type="hidden" value="1"/><input id="album_tracks_attributes_1_id" name="album[tracks_attributes][1][id]" type="hidden" value="2"/><fieldset class="inputs"><legend>Track 0 (m)</legend><div class="form-group string"><label for="album_tracks_attributes_0_name">Name</label> <input class="form-control" id="album_tracks_attributes_0_name" maxlength="255" name="album[tracks_attributes][0][name]" type="text" value="m"/></div></fieldset><fieldset class="inputs"><legend>Track 1 (n)</legend><div class="form-group string"><label for="album_tracks_attributes_1_name">Name</label> <input class="form-control" id="album_tracks_attributes_1_name" maxlength="255" name="album[tracks_attributes][1][name]" type="text" value="n"/></div></fieldset></form>'
406
406
  end
407
407
 
408
408
  it "should not add hidden primary key field for nested forms with one_to_many associations with new objects" do
@@ -411,7 +411,7 @@ describe "Forme Sequel::Model BS3 forms" do
411
411
  end
412
412
 
413
413
  it "should use allow nested forms with many_to_many associations" do
414
- Forme.form(@ab, {},{:config=>:bs3}){|f| f.subform(:tags){f.input(:name)}}.to_s.must_equal '<form class="forme album" method="post"><input id="album_tags_attributes_0_id" name="album[tags_attributes][0][id]" type="hidden" value="1"/><fieldset class="inputs"><legend>Tag #1</legend><div class="form-group string"><label for="album_tags_attributes_0_name">Name</label> <input class="form-control" id="album_tags_attributes_0_name" maxlength="255" name="album[tags_attributes][0][name]" type="text" value="s"/></div></fieldset><input id="album_tags_attributes_1_id" name="album[tags_attributes][1][id]" type="hidden" value="2"/><fieldset class="inputs"><legend>Tag #2</legend><div class="form-group string"><label for="album_tags_attributes_1_name">Name</label> <input class="form-control" id="album_tags_attributes_1_name" maxlength="255" name="album[tags_attributes][1][name]" type="text" value="t"/></div></fieldset></form>'
414
+ Forme.form(@ab, {},{:config=>:bs3}){|f| f.subform(:tags){f.input(:name)}}.to_s.must_equal '<form class="forme album" method="post"><input id="album_tags_attributes_0_id" name="album[tags_attributes][0][id]" type="hidden" value="1"/><input id="album_tags_attributes_1_id" name="album[tags_attributes][1][id]" type="hidden" value="2"/><fieldset class="inputs"><legend>Tag #1</legend><div class="form-group string"><label for="album_tags_attributes_0_name">Name</label> <input class="form-control" id="album_tags_attributes_0_name" maxlength="255" name="album[tags_attributes][0][name]" type="text" value="s"/></div></fieldset><fieldset class="inputs"><legend>Tag #2</legend><div class="form-group string"><label for="album_tags_attributes_1_name">Name</label> <input class="form-control" id="album_tags_attributes_1_name" maxlength="255" name="album[tags_attributes][1][name]" type="text" value="t"/></div></fieldset></form>'
415
415
  end
416
416
 
417
417
  it "should not add hidden primary key field for nested forms with many_to_many associations with new objects" do
@@ -420,23 +420,23 @@ describe "Forme Sequel::Model BS3 forms" do
420
420
  end
421
421
 
422
422
  it "should handle multiple nested levels" do
423
- Forme.form(Artist[1], {},{:config=>:bs3}){|f| f.subform(:albums){f.input(:name); f.subform(:tracks){f.input(:name)}}}.to_s.to_s.must_equal '<form class="forme artist" method="post"><input id="artist_albums_attributes_0_id" name="artist[albums_attributes][0][id]" type="hidden" value="1"/><fieldset class="inputs"><legend>Album #1</legend><div class="form-group string"><label for="artist_albums_attributes_0_name">Name</label> <input class="form-control" id="artist_albums_attributes_0_name" maxlength="255" name="artist[albums_attributes][0][name]" type="text" value="b"/></div><input id="artist_albums_attributes_0_tracks_attributes_0_id" name="artist[albums_attributes][0][tracks_attributes][0][id]" type="hidden" value="1"/><fieldset class="inputs"><legend>Track #1</legend><div class="form-group string"><label for="artist_albums_attributes_0_tracks_attributes_0_name">Name</label> <input class="form-control" id="artist_albums_attributes_0_tracks_attributes_0_name" maxlength="255" name="artist[albums_attributes][0][tracks_attributes][0][name]" type="text" value="m"/></div></fieldset><input id="artist_albums_attributes_0_tracks_attributes_1_id" name="artist[albums_attributes][0][tracks_attributes][1][id]" type="hidden" value="2"/><fieldset class="inputs"><legend>Track #2</legend><div class="form-group string"><label for="artist_albums_attributes_0_tracks_attributes_1_name">Name</label> <input class="form-control" id="artist_albums_attributes_0_tracks_attributes_1_name" maxlength="255" name="artist[albums_attributes][0][tracks_attributes][1][name]" type="text" value="n"/></div></fieldset></fieldset></form>'
423
+ Forme.form(Artist[1], {},{:config=>:bs3}){|f| f.subform(:albums){f.input(:name); f.subform(:tracks){f.input(:name)}}}.to_s.to_s.must_equal '<form class="forme artist" method="post"><input id="artist_albums_attributes_0_id" name="artist[albums_attributes][0][id]" type="hidden" value="1"/><fieldset class="inputs"><legend>Album #1</legend><div class="form-group string"><label for="artist_albums_attributes_0_name">Name</label> <input class="form-control" id="artist_albums_attributes_0_name" maxlength="255" name="artist[albums_attributes][0][name]" type="text" value="b"/></div><input id="artist_albums_attributes_0_tracks_attributes_0_id" name="artist[albums_attributes][0][tracks_attributes][0][id]" type="hidden" value="1"/><input id="artist_albums_attributes_0_tracks_attributes_1_id" name="artist[albums_attributes][0][tracks_attributes][1][id]" type="hidden" value="2"/><fieldset class="inputs"><legend>Track #1</legend><div class="form-group string"><label for="artist_albums_attributes_0_tracks_attributes_0_name">Name</label> <input class="form-control" id="artist_albums_attributes_0_tracks_attributes_0_name" maxlength="255" name="artist[albums_attributes][0][tracks_attributes][0][name]" type="text" value="m"/></div></fieldset><fieldset class="inputs"><legend>Track #2</legend><div class="form-group string"><label for="artist_albums_attributes_0_tracks_attributes_1_name">Name</label> <input class="form-control" id="artist_albums_attributes_0_tracks_attributes_1_name" maxlength="255" name="artist[albums_attributes][0][tracks_attributes][1][name]" type="text" value="n"/></div></fieldset></fieldset></form>'
424
424
  end
425
425
 
426
426
  it "should have #subform :grid option create a grid" do
427
- Forme.form(@ab, {},{:config=>:bs3}){|f| f.subform(:artist, :inputs=>[:name], :grid=>true)}.to_s.must_equal '<form class="forme album" method="post"><table><caption>Artist</caption><thead><tr><th>Name</th></tr></thead><tbody><input id="album_artist_attributes_id" name="album[artist_attributes][id]" type="hidden" value="1"/><tr><td class="string"><input class="form-control" id="album_artist_attributes_name" maxlength="255" name="album[artist_attributes][name]" type="text" value="a"/></td></tr></tbody></table></form>'
427
+ Forme.form(@ab, {},{:config=>:bs3}){|f| f.subform(:artist, :inputs=>[:name], :grid=>true)}.to_s.must_equal '<form class="forme album" method="post"><input id="album_artist_attributes_id" name="album[artist_attributes][id]" type="hidden" value="1"/><table><caption>Artist</caption><thead><tr><th>Name</th></tr></thead><tbody><tr><td class="string"><input class="form-control" id="album_artist_attributes_name" maxlength="255" name="album[artist_attributes][name]" type="text" value="a"/></td></tr></tbody></table></form>'
428
428
  end
429
429
 
430
430
  it "should have #subform :grid option respect :inputs_opts option to pass options to inputs" do
431
- Forme.form(@ab, {},{:config=>:bs3}){|f| f.subform(:artist, :inputs=>[:name], :grid=>true, :inputs_opts=>{:attr=>{:class=>'foo'}})}.to_s.must_equal '<form class="forme album" method="post"><table class="foo"><caption>Artist</caption><thead><tr><th>Name</th></tr></thead><tbody><input id="album_artist_attributes_id" name="album[artist_attributes][id]" type="hidden" value="1"/><tr><td class="string"><input class="form-control" id="album_artist_attributes_name" maxlength="255" name="album[artist_attributes][name]" type="text" value="a"/></td></tr></tbody></table></form>'
431
+ Forme.form(@ab, {},{:config=>:bs3}){|f| f.subform(:artist, :inputs=>[:name], :grid=>true, :inputs_opts=>{:attr=>{:class=>'foo'}})}.to_s.must_equal '<form class="forme album" method="post"><input id="album_artist_attributes_id" name="album[artist_attributes][id]" type="hidden" value="1"/><table class="foo"><caption>Artist</caption><thead><tr><th>Name</th></tr></thead><tbody><tr><td class="string"><input class="form-control" id="album_artist_attributes_name" maxlength="255" name="album[artist_attributes][name]" type="text" value="a"/></td></tr></tbody></table></form>'
432
432
  end
433
433
 
434
434
  it "should have #subform :grid option handle :legend and :labels options" do
435
- Forme.form(@ab, {},{:config=>:bs3}){|f| f.subform(:artist, :inputs=>[:name], :grid=>true, :legend=>'Foo', :labels=>%w'Bar')}.to_s.must_equal '<form class="forme album" method="post"><table><caption>Foo</caption><thead><tr><th>Bar</th></tr></thead><tbody><input id="album_artist_attributes_id" name="album[artist_attributes][id]" type="hidden" value="1"/><tr><td class="string"><input class="form-control" id="album_artist_attributes_name" maxlength="255" name="album[artist_attributes][name]" type="text" value="a"/></td></tr></tbody></table></form>'
435
+ Forme.form(@ab, {},{:config=>:bs3}){|f| f.subform(:artist, :inputs=>[:name], :grid=>true, :legend=>'Foo', :labels=>%w'Bar')}.to_s.must_equal '<form class="forme album" method="post"><input id="album_artist_attributes_id" name="album[artist_attributes][id]" type="hidden" value="1"/><table><caption>Foo</caption><thead><tr><th>Bar</th></tr></thead><tbody><tr><td class="string"><input class="form-control" id="album_artist_attributes_name" maxlength="255" name="album[artist_attributes][name]" type="text" value="a"/></td></tr></tbody></table></form>'
436
436
  end
437
437
 
438
438
  it "should have #subform :grid option handle :legend and :labels nil values" do
439
- Forme.form(@ab, {},{:config=>:bs3}){|f| f.subform(:artist, :inputs=>[:name], :grid=>true, :legend=>nil, :labels=>nil)}.to_s.must_equal '<form class="forme album" method="post"><table><tbody><input id="album_artist_attributes_id" name="album[artist_attributes][id]" type="hidden" value="1"/><tr><td class="string"><input class="form-control" id="album_artist_attributes_name" maxlength="255" name="album[artist_attributes][name]" type="text" value="a"/></td></tr></tbody></table></form>'
439
+ Forme.form(@ab, {},{:config=>:bs3}){|f| f.subform(:artist, :inputs=>[:name], :grid=>true, :legend=>nil, :labels=>nil)}.to_s.must_equal '<form class="forme album" method="post"><input id="album_artist_attributes_id" name="album[artist_attributes][id]" type="hidden" value="1"/><table><tbody><tr><td class="string"><input class="form-control" id="album_artist_attributes_name" maxlength="255" name="album[artist_attributes][name]" type="text" value="a"/></td></tr></tbody></table></form>'
440
440
  end
441
441
 
442
442
  it "should have #subform :grid option handle :skip_primary_key option" do