justinfrench-formtastic 0.1.1 → 0.1.2
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.
- data/README.textile +21 -3
- data/lib/formtastic.rb +63 -4
- data/spec/formtastic_spec.rb +44 -5
- metadata +2 -2
data/README.textile
CHANGED
|
@@ -14,7 +14,7 @@ One day, I finally had enough, so I opened up my text editor, and wrote a DSL fo
|
|
|
14
14
|
<%= form.input :body %>
|
|
15
15
|
<%= form.input :section %>
|
|
16
16
|
<%= form.input :publication_state, :as => :radio %>
|
|
17
|
-
<%= form.input :
|
|
17
|
+
<%= form.input :category %>
|
|
18
18
|
<%= form.input :allow_comments, :label => "Allow commenting on this article" %>
|
|
19
19
|
<% end %>
|
|
20
20
|
|
|
@@ -25,6 +25,11 @@ One day, I finally had enough, so I opened up my text editor, and wrote a DSL fo
|
|
|
25
25
|
<%= form.input :url_title, :required => false %>
|
|
26
26
|
<% end %>
|
|
27
27
|
|
|
28
|
+
<% form.inputs :for => :author do |author_form| %>
|
|
29
|
+
<%= form.input :first_name %>
|
|
30
|
+
<%= form.input :last_name %>
|
|
31
|
+
<% end %>
|
|
32
|
+
|
|
28
33
|
<% form.buttons do %>
|
|
29
34
|
<%= form.commit_button %>
|
|
30
35
|
<% end %>
|
|
@@ -151,13 +156,26 @@ If you want to customize the label text, or render some hint text below the fiel
|
|
|
151
156
|
<% end %>
|
|
152
157
|
</pre>
|
|
153
158
|
|
|
154
|
-
Nested forms (Rails 2.3) are also supported:
|
|
159
|
+
Nested forms (Rails 2.3) are also supported. You can do it in the Rails way:
|
|
155
160
|
|
|
156
161
|
<pre>
|
|
157
162
|
<% semantic_form_for @post do |post| %>
|
|
163
|
+
<%= post.inputs %>
|
|
164
|
+
|
|
158
165
|
<%= post.semantic_fields_for :author do |author| %>
|
|
159
|
-
<%= author.inputs %>
|
|
166
|
+
<%= author.inputs :first_name, :last_name %>
|
|
160
167
|
<%= end %>
|
|
168
|
+
|
|
169
|
+
<%= post.buttons %>
|
|
170
|
+
<% end %>
|
|
171
|
+
</pre>
|
|
172
|
+
|
|
173
|
+
Or in the formtastic way:
|
|
174
|
+
|
|
175
|
+
<pre>
|
|
176
|
+
<% semantic_form_for @post do |post| %>
|
|
177
|
+
<%= post.inputs %>
|
|
178
|
+
<%= post.inputs :first_name, :last_name, :for => :author %>
|
|
161
179
|
<%= post.buttons %>
|
|
162
180
|
<% end %>
|
|
163
181
|
</pre>
|
data/lib/formtastic.rb
CHANGED
|
@@ -177,18 +177,60 @@ module Formtastic #:nodoc:
|
|
|
177
177
|
# </ol>
|
|
178
178
|
# </fieldset>
|
|
179
179
|
# </form>
|
|
180
|
+
#
|
|
181
|
+
# === Nested attributes
|
|
182
|
+
#
|
|
183
|
+
# As in Rails, you can use semantic_fields_for to nest attributes:
|
|
184
|
+
#
|
|
185
|
+
# <% semantic_form_for @post do |form| %>
|
|
186
|
+
# <%= form.inputs :title, :body %>
|
|
187
|
+
#
|
|
188
|
+
# <% form.semantic_fields_for :author, @bob do |author_form| %>
|
|
189
|
+
# <% author_form.inputs do %>
|
|
190
|
+
# <%= author_form.input :first_name, :required => false %>
|
|
191
|
+
# <%= author_form.input :last_name %>
|
|
192
|
+
# <% end %>
|
|
193
|
+
# <% end %>
|
|
194
|
+
# <% end %>
|
|
195
|
+
#
|
|
196
|
+
# But this does not look formtastic! This is equivalent:
|
|
197
|
+
#
|
|
198
|
+
# <% semantic_form_for @post do |form| %>
|
|
199
|
+
# <%= form.inputs :title, :body %>
|
|
200
|
+
# <% form.inputs :for => [ :author, @bob ] do |author_form| %>
|
|
201
|
+
# <%= author_form.input :first_name, :required => false %>
|
|
202
|
+
# <%= author_form.input :last_name %>
|
|
203
|
+
# <% end %>
|
|
204
|
+
# <% end %>
|
|
205
|
+
#
|
|
206
|
+
# And if you don't need to give options to your input call, you could do it
|
|
207
|
+
# in just one line:
|
|
208
|
+
#
|
|
209
|
+
# <% semantic_form_for @post do |form| %>
|
|
210
|
+
# <%= form.inputs :title, :body %>
|
|
211
|
+
# <%= form.inputs :first_name, :last_name, :for => @bob %>
|
|
212
|
+
# <% end %>
|
|
213
|
+
#
|
|
214
|
+
# Just remember that calling inputs generates a new fieldset to wrap your
|
|
215
|
+
# inputs. If you have two separate models, but, semantically, on the page
|
|
216
|
+
# they are part of the same fieldset, you should use semantic_fields_for
|
|
217
|
+
# instead (just as you would do with Rails' form builder).
|
|
218
|
+
#
|
|
180
219
|
def inputs(*args, &block)
|
|
181
220
|
html_options = args.extract_options!
|
|
182
221
|
html_options[:class] ||= "inputs"
|
|
183
222
|
|
|
184
|
-
if
|
|
223
|
+
if fields_for_object = html_options.delete(:for)
|
|
224
|
+
inputs_for_nested_attributes(fields_for_object, args << html_options, &block)
|
|
225
|
+
elsif block_given?
|
|
185
226
|
field_set_and_list_wrapping(html_options, &block)
|
|
186
227
|
else
|
|
187
228
|
if args.empty?
|
|
188
|
-
args
|
|
229
|
+
args = @object.class.reflections.map { |n,_| n }
|
|
189
230
|
args += @object.class.content_columns.map(&:name)
|
|
190
231
|
end
|
|
191
232
|
contents = args.map { |method| input(method.to_sym) }
|
|
233
|
+
|
|
192
234
|
field_set_and_list_wrapping(html_options, contents)
|
|
193
235
|
end
|
|
194
236
|
end
|
|
@@ -253,6 +295,22 @@ module Formtastic #:nodoc:
|
|
|
253
295
|
|
|
254
296
|
protected
|
|
255
297
|
|
|
298
|
+
# Deals with :for option when it's supplied to inputs methods.
|
|
299
|
+
# It should raise an error if a block with arity zero is given.
|
|
300
|
+
#
|
|
301
|
+
def inputs_for_nested_attributes(fields_for_object, inputs_args, &block)
|
|
302
|
+
fields_for_block = if block_given?
|
|
303
|
+
raise ArgumentError, 'You gave :for option with a block to inputs method, ' <<
|
|
304
|
+
'but the block does not accept any argument.' if block.arity <= 0
|
|
305
|
+
|
|
306
|
+
proc { |f| f.inputs(*inputs_args){ block.call(f) } }
|
|
307
|
+
else
|
|
308
|
+
proc { |f| f.inputs(*inputs_args) }
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
semantic_fields_for(*Array(fields_for_object), &fields_for_block)
|
|
312
|
+
end
|
|
313
|
+
|
|
256
314
|
# Ensure :object => @object is set before sending the options down to the Rails layer.
|
|
257
315
|
# Also remove any Formtastic-specific options
|
|
258
316
|
def set_options(options)
|
|
@@ -650,12 +708,12 @@ module Formtastic #:nodoc:
|
|
|
650
708
|
# <li class="boolean_radio required" id="post_public_input">
|
|
651
709
|
# <fieldset><legend><span>make this sucker public?<abbr title="required">*</abbr></span></legend>
|
|
652
710
|
# <ol>
|
|
653
|
-
# <li>
|
|
711
|
+
# <li class="true">
|
|
654
712
|
# <label for="post_public_true">
|
|
655
713
|
# <input id="post_public_true" name="post[public]" type="radio" value="true" /> Yeah!
|
|
656
714
|
# </label>
|
|
657
715
|
# </li>
|
|
658
|
-
# <li>
|
|
716
|
+
# <li class="false">
|
|
659
717
|
# <label for="post_public_false">
|
|
660
718
|
# <input id="post_public_false" name="post[public]" type="radio" checked="checked" /> Nah!
|
|
661
719
|
# </label>
|
|
@@ -663,6 +721,7 @@ module Formtastic #:nodoc:
|
|
|
663
721
|
# </ol>
|
|
664
722
|
# </fieldset>
|
|
665
723
|
# </li>
|
|
724
|
+
#
|
|
666
725
|
def boolean_radio_input(method, options)
|
|
667
726
|
options[:true] ||= I18n.t('yes', :default => 'Yes', :scope => [:formtastic]).send(@@label_str_method)
|
|
668
727
|
options[:false] ||= I18n.t('no', :default => 'No', :scope => [:formtastic]).send(@@label_str_method)
|
data/spec/formtastic_spec.rb
CHANGED
|
@@ -2180,20 +2180,50 @@ describe 'Formtastic' do
|
|
|
2180
2180
|
end
|
|
2181
2181
|
end
|
|
2182
2182
|
end
|
|
2183
|
+
|
|
2183
2184
|
it 'should render a fieldset inside the form, with a class of "inputs"' do
|
|
2184
2185
|
output_buffer.should have_tag("form fieldset.inputs")
|
|
2185
2186
|
end
|
|
2187
|
+
|
|
2186
2188
|
it 'should render an ol inside the fieldset' do
|
|
2187
2189
|
output_buffer.should have_tag("form fieldset.inputs ol")
|
|
2188
2190
|
end
|
|
2191
|
+
|
|
2189
2192
|
it 'should render the contents of the block inside the ol' do
|
|
2190
2193
|
output_buffer.should have_tag("form fieldset.inputs ol", /hello/)
|
|
2191
2194
|
end
|
|
2195
|
+
|
|
2192
2196
|
it 'should not render a legend inside the fieldset' do
|
|
2193
2197
|
output_buffer.should_not have_tag("form fieldset.inputs legend")
|
|
2194
2198
|
end
|
|
2195
2199
|
end
|
|
2196
2200
|
|
|
2201
|
+
describe 'when a :for option is provided' do
|
|
2202
|
+
it 'should render nested inputs' do
|
|
2203
|
+
@bob.stub!(:column_for_attribute).and_return(mock('column', :type => :string, :limit => 255))
|
|
2204
|
+
|
|
2205
|
+
semantic_form_for(@new_post) do |builder|
|
|
2206
|
+
builder.inputs :for => [:author, @bob] do |bob_builder|
|
|
2207
|
+
concat(bob_builder.input :login)
|
|
2208
|
+
end
|
|
2209
|
+
end
|
|
2210
|
+
|
|
2211
|
+
output_buffer.should have_tag("form fieldset.inputs #post_author_login")
|
|
2212
|
+
output_buffer.should_not have_tag("form fieldset.inputs #author_login")
|
|
2213
|
+
end
|
|
2214
|
+
|
|
2215
|
+
it 'should raise an error if :for and block with no argument is given' do
|
|
2216
|
+
semantic_form_for(@new_post) do |builder|
|
|
2217
|
+
proc {
|
|
2218
|
+
builder.inputs(:for => [:author, @bob]) do
|
|
2219
|
+
#
|
|
2220
|
+
end
|
|
2221
|
+
}.should raise_error(ArgumentError, 'You gave :for option with a block to inputs method, ' <<
|
|
2222
|
+
'but the block does not accept any argument.')
|
|
2223
|
+
end
|
|
2224
|
+
end
|
|
2225
|
+
end
|
|
2226
|
+
|
|
2197
2227
|
describe 'when a :name option is provided' do
|
|
2198
2228
|
before do
|
|
2199
2229
|
@legend_text = "Advanced options"
|
|
@@ -2203,6 +2233,7 @@ describe 'Formtastic' do
|
|
|
2203
2233
|
end
|
|
2204
2234
|
end
|
|
2205
2235
|
end
|
|
2236
|
+
|
|
2206
2237
|
it 'should render a fieldset inside the form' do
|
|
2207
2238
|
output_buffer.should have_tag("form fieldset legend", /#{@legend_text}/)
|
|
2208
2239
|
end
|
|
@@ -2218,6 +2249,7 @@ describe 'Formtastic' do
|
|
|
2218
2249
|
end
|
|
2219
2250
|
end
|
|
2220
2251
|
end
|
|
2252
|
+
|
|
2221
2253
|
it 'should pass the options into the fieldset tag as attributes' do
|
|
2222
2254
|
output_buffer.should have_tag("form fieldset##{@id_option}")
|
|
2223
2255
|
output_buffer.should have_tag("form fieldset.#{@class_option}")
|
|
@@ -2243,7 +2275,6 @@ describe 'Formtastic' do
|
|
|
2243
2275
|
end
|
|
2244
2276
|
|
|
2245
2277
|
describe 'with no args' do
|
|
2246
|
-
|
|
2247
2278
|
before do
|
|
2248
2279
|
semantic_form_for(@new_post) do |builder|
|
|
2249
2280
|
concat(builder.inputs)
|
|
@@ -2281,11 +2312,9 @@ describe 'Formtastic' do
|
|
|
2281
2312
|
it 'should render a select list item for author_id' do
|
|
2282
2313
|
output_buffer.should have_tag('form > fieldset.inputs > ol > li.select')
|
|
2283
2314
|
end
|
|
2284
|
-
|
|
2285
2315
|
end
|
|
2286
2316
|
|
|
2287
2317
|
describe 'with column names as args' do
|
|
2288
|
-
|
|
2289
2318
|
before do
|
|
2290
2319
|
semantic_form_for(@new_post) do |builder|
|
|
2291
2320
|
concat(builder.inputs(:title, :body))
|
|
@@ -2297,11 +2326,22 @@ describe 'Formtastic' do
|
|
|
2297
2326
|
output_buffer.should have_tag('form > fieldset.inputs > ol > li.string')
|
|
2298
2327
|
output_buffer.should have_tag('form > fieldset.inputs > ol > li.text')
|
|
2299
2328
|
end
|
|
2329
|
+
end
|
|
2300
2330
|
|
|
2331
|
+
describe 'when a :for option is provided' do
|
|
2332
|
+
it 'should render nested inputs' do
|
|
2333
|
+
@bob.stub!(:column_for_attribute).and_return(mock('column', :type => :string, :limit => 255))
|
|
2334
|
+
|
|
2335
|
+
semantic_form_for(@new_post) do |builder|
|
|
2336
|
+
concat(builder.inputs :login, :for => @bob)
|
|
2337
|
+
end
|
|
2338
|
+
|
|
2339
|
+
output_buffer.should have_tag("form fieldset.inputs #post_author_login")
|
|
2340
|
+
output_buffer.should_not have_tag("form fieldset.inputs #author_login")
|
|
2341
|
+
end
|
|
2301
2342
|
end
|
|
2302
2343
|
|
|
2303
2344
|
describe 'with column names and an options hash as args' do
|
|
2304
|
-
|
|
2305
2345
|
before do
|
|
2306
2346
|
semantic_form_for(@new_post) do |builder|
|
|
2307
2347
|
concat(builder.inputs(:title, :body, :name => "Legendary Legend Text", :id => "my-id"))
|
|
@@ -2319,7 +2359,6 @@ describe 'Formtastic' do
|
|
|
2319
2359
|
it 'should use the special :name option as a text for the legend tag' do
|
|
2320
2360
|
output_buffer.should have_tag('form > fieldset#my-id.inputs > legend', /Legendary Legend Text/)
|
|
2321
2361
|
end
|
|
2322
|
-
|
|
2323
2362
|
end
|
|
2324
2363
|
|
|
2325
2364
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: justinfrench-formtastic
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Justin French
|
|
@@ -9,7 +9,7 @@ autorequire: formtastic
|
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
|
|
12
|
-
date: 2009-03-
|
|
12
|
+
date: 2009-03-17 00:00:00 -07:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies: []
|
|
15
15
|
|