formtastic 0.9.1 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +21 -29
- data/Rakefile +2 -12
- data/generators/formtastic/templates/formtastic.rb +4 -0
- data/lib/formtastic.rb +114 -66
- data/spec/buttons_spec.rb +1 -1
- data/spec/commit_button_spec.rb +4 -4
- data/spec/custom_builder_spec.rb +1 -1
- data/spec/custom_macros.rb +461 -0
- data/spec/error_proc_spec.rb +1 -1
- data/spec/errors_spec.rb +8 -1
- data/spec/form_helper_spec.rb +1 -1
- data/spec/include_blank_spec.rb +1 -1
- data/spec/input_spec.rb +3 -1567
- data/spec/inputs/boolean_input_spec.rb +60 -0
- data/spec/inputs/check_boxes_input_spec.rb +106 -0
- data/spec/inputs/country_input_spec.rb +80 -0
- data/spec/inputs/date_input_spec.rb +43 -0
- data/spec/inputs/datetime_input_spec.rb +155 -0
- data/spec/inputs/file_input_spec.rb +33 -0
- data/spec/inputs/hidden_input_spec.rb +41 -0
- data/spec/inputs/numeric_input_spec.rb +44 -0
- data/spec/inputs/password_input_spec.rb +46 -0
- data/spec/inputs/radio_input_spec.rb +113 -0
- data/spec/inputs/select_input_spec.rb +263 -0
- data/spec/inputs/string_input_spec.rb +47 -0
- data/spec/inputs/text_input_spec.rb +33 -0
- data/spec/inputs/time_input_spec.rb +42 -0
- data/spec/inputs/time_zone_input_spec.rb +59 -0
- data/spec/inputs_spec.rb +1 -1
- data/spec/label_spec.rb +1 -1
- data/spec/semantic_fields_for_spec.rb +1 -1
- data/spec/spec.opts +2 -0
- data/spec/{test_helper.rb → spec_helper.rb} +36 -3
- metadata +38 -5
data/README.textile
CHANGED
@@ -311,12 +311,12 @@ Formtastic supports localized *labels*, *hints*, *legends*, *actions* using the
|
|
311
311
|
|
312
312
|
<pre>
|
313
313
|
<% semantic_form_for Post.new do |form| %>
|
314
|
-
<% inputs do %>
|
314
|
+
<% form.inputs do %>
|
315
315
|
<%= form.input :title %> # => :label => "Choose a title...", :hint => "Choose a good title for you post."
|
316
316
|
<%= form.input :body %> # => :label => "Write something...", :hint => "Write something inspiring here."
|
317
317
|
<%= form.input :section %> # => :label => I18n.t('activerecord.attributes.user.section') or 'Section'
|
318
318
|
<% end %>
|
319
|
-
<% buttons do %>
|
319
|
+
<% form.buttons do %>
|
320
320
|
<%= form.commit_button %> # => "Create my {{model}}"
|
321
321
|
<% end %>
|
322
322
|
<% end %>
|
@@ -328,7 +328,7 @@ _Note: Slightly different because Formtastic can't guess how you group fields in
|
|
328
328
|
|
329
329
|
<pre>
|
330
330
|
<% semantic_form_for @post do |form| %>
|
331
|
-
<% inputs :title => :post_details do %> # => :title => "Post details"
|
331
|
+
<% form.inputs :title => :post_details do %> # => :title => "Post details"
|
332
332
|
# ...
|
333
333
|
<% end %>
|
334
334
|
# ...
|
@@ -339,12 +339,12 @@ _Note: Slightly different because Formtastic can't guess how you group fields in
|
|
339
339
|
|
340
340
|
<pre>
|
341
341
|
<% semantic_form_for @post do |form| %>
|
342
|
-
<% inputs do %>
|
342
|
+
<% form.inputs do %>
|
343
343
|
<%= form.input :title %> # => :label => "Choose a title...", :hint => "Choose a good title for you post."
|
344
344
|
<%= form.input :body, :hint => false %> # => :label => "Write something..."
|
345
345
|
<%= form.input :section, :label => 'Some section' %> # => :label => 'Some section'
|
346
346
|
<% end %>
|
347
|
-
<% buttons do %>
|
347
|
+
<% form.buttons do %>
|
348
348
|
<%= form.commit_button :dummie %> # => "Launch!"
|
349
349
|
<% end %>
|
350
350
|
<% end %>
|
@@ -360,12 +360,12 @@ If I18n-lookups is disabled, i.e.:
|
|
360
360
|
|
361
361
|
<pre>
|
362
362
|
<% semantic_form_for @post do |form| %>
|
363
|
-
<% inputs do %>
|
363
|
+
<% form.inputs do %>
|
364
364
|
<%= form.input :title, :label => true %> # => :label => "Choose a title..."
|
365
365
|
<%= form.input :body, :label => true %> # => :label => "Write something..."
|
366
366
|
<%= form.input :section, :label => true %> # => :label => I18n.t('activerecord.attributes.user.section') or 'Section'
|
367
367
|
<% end %>
|
368
|
-
|
368
|
+
<% form.buttons do %>
|
369
369
|
<%= form.commit_button true %> # => "Save changes" (if we are in edit that is...)
|
370
370
|
<% end %>
|
371
371
|
<% end %>
|
@@ -416,6 +416,13 @@ h2. Configuration
|
|
416
416
|
Run @./script/generate formtastic@ to copy a commented out config file into @config/initializers/formtastic.rb@. You can "view the configuration file on GitHub":http://github.com/justinfrench/formtastic/blob/master/generators/formtastic/templates/formtastic.rb
|
417
417
|
|
418
418
|
|
419
|
+
h2. Custom Inputs
|
420
|
+
|
421
|
+
If you want to add your own input types to encapsulate your own logic or interface patterns, you can do so by subclassing SemanticFormBuilder and configuring Formtastic to use your custom builder class.
|
422
|
+
|
423
|
+
@Formtastic::SemanticFormHelper.builder = MyCustomBuilder@
|
424
|
+
|
425
|
+
|
419
426
|
h2. Status
|
420
427
|
|
421
428
|
Formtastic has been in active development for about a year. We've just recently jumped to an 0.9 version number, signaling that we consider this a 1.0 release candidate, and that the API won't change significantly for the 1.x series.
|
@@ -432,7 +439,7 @@ There are none, but...
|
|
432
439
|
|
433
440
|
h2. Compatibility
|
434
441
|
|
435
|
-
I'm only testing Formtastic with the latest Rails 2.
|
442
|
+
I'm only testing Formtastic with the latest Rails 2.4.x stable release, and it should be fine under Rails 2.3.x as well (including nested forms). Patches are welcome to allow backwards compatibility, but I don't have the energy!
|
436
443
|
|
437
444
|
|
438
445
|
h2. Got TextMate?
|
@@ -444,27 +451,12 @@ Well...there's a TextMate-bundle in town, dedicated to make usage of Formtastic
|
|
444
451
|
|
445
452
|
h2. Contributors
|
446
453
|
|
447
|
-
Formtastic is maintained by "Justin French":http://justinfrench.com
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
* "negonicrac":http://github.com/negonicrac
|
454
|
-
* "Xavier Shay":http://rhnh.net
|
455
|
-
* "Pat Allan":http://github.com/freelancing-god
|
456
|
-
* "Gareth Townsend":http://github.com/quamen
|
457
|
-
* "Sascha Hoellger":http://github.com/mitnal
|
458
|
-
* "Andrew Carpenter":http://github.com/andrewcarpenter
|
459
|
-
* "Jack Dempsey":http://github.com/jackdempsey/
|
460
|
-
* "Greg Fitzgerald":http://github.com/gregf/
|
461
|
-
* "Hector E. Gomez Morales":http://github.com/hectoregm
|
462
|
-
* "Ben Hamill":http://blog.benhamill.com/
|
463
|
-
* "Simon Chiu":http://github.com/tolatomeow
|
464
|
-
* "Bin Dong":http://github.com/dongbin
|
465
|
-
|
466
|
-
|
467
|
-
h2. Hey, join the Google group!
|
454
|
+
Formtastic is maintained by "Justin French":http://justinfrench.com, "José Valim":http://github.com/josevalim and "Jonas Grimfelt":http://github.com/grimen, but it wouldn't be as awesome as it is today without help from over 30 contributors.
|
455
|
+
|
456
|
+
@git shortlog -n -s --no-merges@
|
457
|
+
|
458
|
+
|
459
|
+
h2. Google Group
|
468
460
|
|
469
461
|
Please join the "Formtastic Google Group":http://groups.google.com.au/group/formtastic, especially if you'd like to talk about a new feature, or report a bug.
|
470
462
|
|
data/Rakefile
CHANGED
@@ -13,25 +13,15 @@ begin
|
|
13
13
|
HOMEPAGE = "http://github.com/justinfrench/formtastic/tree/master"
|
14
14
|
INSTALL_MESSAGE = %q{
|
15
15
|
========================================================================
|
16
|
-
|
17
16
|
Thanks for installing Formtastic!
|
18
|
-
|
17
|
+
------------------------------------------------------------------------
|
19
18
|
You can now (optionally) run the generater to copy some stylesheets and
|
20
19
|
a config initializer into your application:
|
21
|
-
|
22
20
|
./script/generate formtastic
|
23
|
-
|
24
|
-
The following files will be added:
|
25
|
-
|
26
|
-
RAILS_ROOT/public/stylesheets/formtastic.css
|
27
|
-
RAILS_ROOT/public/stylesheets/formtastic_changes.css
|
28
|
-
RAILS_ROOT/config/initializers/formtastic.rb
|
29
|
-
|
30
|
-
Find out more and get involved:
|
31
21
|
|
22
|
+
Find out more and get involved:
|
32
23
|
http://github.com/justinfrench/formtastic
|
33
24
|
http://groups.google.com.au/group/formtastic
|
34
|
-
|
35
25
|
========================================================================
|
36
26
|
}
|
37
27
|
|
@@ -45,3 +45,7 @@
|
|
45
45
|
# Default value: false. Overridden for specific fields by setting value to true,
|
46
46
|
# i.e. :label => true, or :hint => true (or opposite depending on initialized value)
|
47
47
|
# Formtastic::SemanticFormBuilder.i18n_lookups_by_default = false
|
48
|
+
|
49
|
+
# You can add custom inputs or override parts of Formtastic by subclassing SemanticFormBuilder and
|
50
|
+
# specifying that class here. Defaults to SemanticFormBuilder.
|
51
|
+
# Formtastic::SemanticFormHelper.builder = MyCustomBuilder
|
data/lib/formtastic.rb
CHANGED
@@ -25,17 +25,7 @@ module Formtastic #:nodoc:
|
|
25
25
|
I18N_SCOPES = [ '{{model}}.{{action}}.{{attribute}}',
|
26
26
|
'{{model}}.{{attribute}}',
|
27
27
|
'{{attribute}}']
|
28
|
-
|
29
|
-
# Keeps simple mappings in a hash
|
30
|
-
INPUT_MAPPINGS = {
|
31
|
-
:string => :text_field,
|
32
|
-
:password => :password_field,
|
33
|
-
:numeric => :text_field,
|
34
|
-
:text => :text_area,
|
35
|
-
:file => :file_field
|
36
|
-
}
|
37
|
-
STRING_MAPPINGS = [ :string, :password, :numeric ]
|
38
|
-
|
28
|
+
|
39
29
|
attr_accessor :template
|
40
30
|
|
41
31
|
# Returns a suitable form input for the given +method+, using the database column information
|
@@ -88,7 +78,6 @@ module Formtastic #:nodoc:
|
|
88
78
|
|
89
79
|
html_class = [ options[:as], (options[:required] ? :required : :optional) ]
|
90
80
|
html_class << 'error' if @object && @object.respond_to?(:errors) && !@object.errors[method.to_sym].blank?
|
91
|
-
html_class << method.to_s
|
92
81
|
|
93
82
|
wrapper_html = options.delete(:wrapper_html) || {}
|
94
83
|
wrapper_html[:id] ||= generate_html_id(method)
|
@@ -299,12 +288,6 @@ module Formtastic #:nodoc:
|
|
299
288
|
if @object
|
300
289
|
key = @object.new_record? ? :create : :update
|
301
290
|
object_name = @object.class.human_name
|
302
|
-
|
303
|
-
if key == :update
|
304
|
-
# Note: Fallback on :save-key (deprecated), :update makes more sense in the REST-world.
|
305
|
-
fallback_text = ::I18n.t(:save, :model => object_name, :default => "Save {{model}}", :scope => [:formtastic])
|
306
|
-
::ActiveSupport::Deprecation.warn "Formtastic I18n: Key 'formtastic.save' is now deprecated in favor 'formtastic.update'."
|
307
|
-
end
|
308
291
|
else
|
309
292
|
key = :submit
|
310
293
|
object_name = @object_name.to_s.send(@@label_str_method)
|
@@ -392,8 +375,8 @@ module Formtastic #:nodoc:
|
|
392
375
|
end
|
393
376
|
end
|
394
377
|
|
395
|
-
# Generates error messages for the given method. Errors can be shown as list
|
396
|
-
# or
|
378
|
+
# Generates error messages for the given method. Errors can be shown as list,
|
379
|
+
# as sentence or just the first error can be displayed. If :none is set, no error is shown.
|
397
380
|
#
|
398
381
|
# This method is also aliased as errors_on, so you can call on your custom
|
399
382
|
# inputs as well:
|
@@ -404,7 +387,7 @@ module Formtastic #:nodoc:
|
|
404
387
|
# end
|
405
388
|
#
|
406
389
|
def inline_errors_for(method, options=nil) #:nodoc:
|
407
|
-
return nil unless @object && @object.respond_to?(:errors) && [:sentence, :list].include?(@@inline_errors)
|
390
|
+
return nil unless @object && @object.respond_to?(:errors) && [:sentence, :list, :first].include?(@@inline_errors)
|
408
391
|
|
409
392
|
errors = @object.errors[method.to_sym]
|
410
393
|
send("error_#{@@inline_errors}", Array(errors)) unless errors.blank?
|
@@ -491,24 +474,42 @@ module Formtastic #:nodoc:
|
|
491
474
|
if_condition ? !!condition : !condition
|
492
475
|
end
|
493
476
|
|
494
|
-
|
495
|
-
# :textarea and :numeric). :select, :radio, :boolean and :datetime inputs
|
496
|
-
# are not handled by this method, since they need more detailed approach.
|
497
|
-
#
|
498
|
-
# If input_html is given as option, it's passed down to the input.
|
499
|
-
#
|
500
|
-
def input_simple(type, method, options)
|
477
|
+
def basic_input_helper(form_helper_method, type, method, options)
|
501
478
|
html_options = options.delete(:input_html) || {}
|
502
|
-
html_options = default_string_options(method, type).merge(html_options) if
|
479
|
+
html_options = default_string_options(method, type).merge(html_options) if [:numeric, :string, :password].include?(type)
|
503
480
|
|
504
481
|
self.label(method, options_for_label(options)) +
|
505
|
-
self.send(
|
482
|
+
self.send(form_helper_method, method, html_options)
|
483
|
+
end
|
484
|
+
|
485
|
+
# Outputs a label and standard Rails text field inside the wrapper.
|
486
|
+
def string_input(method, options)
|
487
|
+
basic_input_helper(:text_field, :string, method, options)
|
488
|
+
end
|
489
|
+
|
490
|
+
# Outputs a label and standard Rails password field inside the wrapper.
|
491
|
+
def password_input(method, options)
|
492
|
+
basic_input_helper(:password_field, :password, method, options)
|
493
|
+
end
|
494
|
+
|
495
|
+
# Outputs a label and standard Rails text field inside the wrapper.
|
496
|
+
def numeric_input(method, options)
|
497
|
+
basic_input_helper(:text_field, :numeric, method, options)
|
498
|
+
end
|
499
|
+
|
500
|
+
# Ouputs a label and standard Rails text area inside the wrapper.
|
501
|
+
def text_input(method, options)
|
502
|
+
basic_input_helper(:text_area, :text, method, options)
|
503
|
+
end
|
504
|
+
|
505
|
+
# Outputs a label and a standard Rails file field inside the wrapper.
|
506
|
+
def file_input(method, options)
|
507
|
+
basic_input_helper(:file_field, :file, method, options)
|
506
508
|
end
|
507
509
|
|
508
510
|
# Outputs a hidden field inside the wrapper, which should be hidden with CSS.
|
509
511
|
# Additionals options can be given and will be sent straight to hidden input
|
510
512
|
# element.
|
511
|
-
#
|
512
513
|
def hidden_input(method, options)
|
513
514
|
self.hidden_field(method, set_options(options))
|
514
515
|
end
|
@@ -585,6 +586,13 @@ module Formtastic #:nodoc:
|
|
585
586
|
# f.input :author, :value_method => :login
|
586
587
|
# f.input :author, :value_method => Proc.new { |a| "author_#{a.login}" }
|
587
588
|
#
|
589
|
+
# You can pre-select a specific option value by passing in the :selected option.
|
590
|
+
#
|
591
|
+
# Examples:
|
592
|
+
#
|
593
|
+
# f.input :author, :selected => current_user.id
|
594
|
+
# f.input :author, :value_method => :login, :selected => current_user.login
|
595
|
+
#
|
588
596
|
# You can pass html_options to the select tag using :input_html => {}
|
589
597
|
#
|
590
598
|
# Examples:
|
@@ -594,8 +602,21 @@ module Formtastic #:nodoc:
|
|
594
602
|
# By default, all select inputs will have a blank option at the top of the list. You can add
|
595
603
|
# a prompt with the :prompt option, or disable the blank option with :include_blank => false.
|
596
604
|
#
|
605
|
+
#
|
606
|
+
# You can group the options in optgroup elements by passing the :group_by option
|
607
|
+
# (Note: only tested for belongs_to relations)
|
608
|
+
#
|
609
|
+
# Examples:
|
610
|
+
#
|
611
|
+
# f.input :author, :group_by => :continent
|
612
|
+
#
|
613
|
+
# All the other options should work as expected. If you want to call a custom method on the
|
614
|
+
# group item. You can include the option:group_label_method
|
615
|
+
# Examples:
|
616
|
+
#
|
617
|
+
# f.input :author, :group_by => :continents, :group_label_method => :something_different
|
618
|
+
#
|
597
619
|
def select_input(method, options)
|
598
|
-
collection = find_collection_for_column(method, options)
|
599
620
|
html_options = options.delete(:input_html) || {}
|
600
621
|
options = set_include_blank(options)
|
601
622
|
|
@@ -608,7 +629,25 @@ module Formtastic #:nodoc:
|
|
608
629
|
|
609
630
|
input_name = generate_association_input_name(method)
|
610
631
|
self.label(method, options_for_label(options).merge(:input_name => input_name)) +
|
611
|
-
|
632
|
+
|
633
|
+
if options[:group_by]
|
634
|
+
# The grouped_options_select is a bit counter intuitive and not optimised (mostly due to ActiveRecord).
|
635
|
+
# The formtastic user however shouldn't notice this too much.
|
636
|
+
raw_collection = find_raw_collection_for_column(method, options.reverse_merge(:find_options => { :include => options[:group_by] }))
|
637
|
+
label, value = detect_label_and_value_method!(raw_collection)
|
638
|
+
group_collection = raw_collection.map { |option| option.send(options[:group_by]) }.uniq
|
639
|
+
group_label_method = options[:group_label_method] || detect_label_method(group_collection)
|
640
|
+
group_collection = group_collection.sort_by { |group_item| group_item.send(group_label_method) }
|
641
|
+
|
642
|
+
# Here comes the monster with 8 arguments
|
643
|
+
self.grouped_collection_select(input_name, group_collection,
|
644
|
+
method.to_s.pluralize, group_label_method,
|
645
|
+
value, label,
|
646
|
+
set_options(options), html_options)
|
647
|
+
else
|
648
|
+
collection = find_collection_for_column(method, options)
|
649
|
+
self.select(input_name, collection, set_options(options), html_options)
|
650
|
+
end
|
612
651
|
end
|
613
652
|
alias :boolean_select_input :select_input
|
614
653
|
|
@@ -678,6 +717,11 @@ module Formtastic #:nodoc:
|
|
678
717
|
# f.input :author, :as => :radio, :value_method => :full_name
|
679
718
|
# f.input :author, :as => :radio, :value_method => :login
|
680
719
|
# f.input :author, :as => :radio, :value_method => Proc.new { |a| "author_#{a.login}" }
|
720
|
+
#
|
721
|
+
# You can force a particular radio button in the collection to be checked with the :selected option. Example:
|
722
|
+
#
|
723
|
+
# f.input :subscribe_to_newsletter, :as => :radio, :selected => true
|
724
|
+
# f.input :subscribe_to_newsletter, :as => :radio, :collection => ["Yeah!", "Nope!"], :selected => "Nope!"
|
681
725
|
#
|
682
726
|
# Finally, you can set :value_as_class => true if you want the li wrapper around each radio
|
683
727
|
# button / label combination to contain a class with the value of the radio button (useful for
|
@@ -692,6 +736,7 @@ module Formtastic #:nodoc:
|
|
692
736
|
list_item_content = collection.map do |c|
|
693
737
|
label = c.is_a?(Array) ? c.first : c
|
694
738
|
value = c.is_a?(Array) ? c.last : c
|
739
|
+
html_options[:checked] = options.delete(:selected) unless options[:selected].blank?
|
695
740
|
|
696
741
|
li_content = template.content_tag(:label,
|
697
742
|
"#{self.radio_button(input_name, value, html_options)} #{label}",
|
@@ -945,20 +990,8 @@ module Formtastic #:nodoc:
|
|
945
990
|
end
|
946
991
|
|
947
992
|
# Generates an input for the given method using the type supplied with :as.
|
948
|
-
#
|
949
|
-
# If the input is included in INPUT_MAPPINGS, it uses input_simple
|
950
|
-
# implementation which maps most of the inputs. All others have specific
|
951
|
-
# code and then a proper handler should be called (like radio_input) for
|
952
|
-
# :radio types.
|
953
|
-
#
|
954
993
|
def inline_input_for(method, options)
|
955
|
-
|
956
|
-
|
957
|
-
if INPUT_MAPPINGS.key?(input_type)
|
958
|
-
input_simple(input_type, method, options)
|
959
|
-
else
|
960
|
-
send("#{input_type}_input", method, options)
|
961
|
-
end
|
994
|
+
send("#{options.delete(:as)}_input", method, options)
|
962
995
|
end
|
963
996
|
|
964
997
|
# Generates hints for the given method using the text supplied in :hint.
|
@@ -985,6 +1018,12 @@ module Formtastic #:nodoc:
|
|
985
1018
|
template.content_tag(:ul, list_elements.join("\n"), :class => 'errors')
|
986
1019
|
end
|
987
1020
|
|
1021
|
+
# Creates an error sentence containing only the first error
|
1022
|
+
#
|
1023
|
+
def error_first(errors) #:nodoc:
|
1024
|
+
template.content_tag(:p, errors.first.untaint, :class => 'inline-errors')
|
1025
|
+
end
|
1026
|
+
|
988
1027
|
# Generates the required or optional string. If the value set is a proc,
|
989
1028
|
# it evaluates the proc first.
|
990
1029
|
#
|
@@ -1100,26 +1139,43 @@ module Formtastic #:nodoc:
|
|
1100
1139
|
# appropriate label and value.
|
1101
1140
|
#
|
1102
1141
|
def find_collection_for_column(column, options)
|
1142
|
+
collection = find_raw_collection_for_column(column, options)
|
1143
|
+
|
1144
|
+
# Return if we have an Array of strings, fixnums or arrays
|
1145
|
+
return collection if collection.instance_of?(Array) &&
|
1146
|
+
[Array, Fixnum, String, Symbol].include?(collection.first.class)
|
1147
|
+
|
1148
|
+
label, value = detect_label_and_value_method!(collection, options)
|
1149
|
+
|
1150
|
+
collection.map { |o| [send_or_call(label, o), send_or_call(value, o)] }
|
1151
|
+
end
|
1152
|
+
|
1153
|
+
# As #find_collection_for_column but returns the collection without mapping the label and value
|
1154
|
+
#
|
1155
|
+
def find_raw_collection_for_column(column, options) #:nodoc:
|
1103
1156
|
reflection = find_reflection(column)
|
1104
1157
|
|
1105
1158
|
collection = if options[:collection]
|
1106
1159
|
options.delete(:collection)
|
1107
1160
|
elsif reflection
|
1108
|
-
reflection.klass.find(:all)
|
1161
|
+
reflection.klass.find(:all, options[:find_options] || {})
|
1109
1162
|
else
|
1110
1163
|
create_boolean_collection(options)
|
1111
1164
|
end
|
1112
1165
|
|
1113
1166
|
collection = collection.to_a if collection.is_a?(Hash)
|
1114
1167
|
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1168
|
+
collection
|
1169
|
+
end
|
1170
|
+
|
1171
|
+
# Detects the label and value methods from a collection values set in
|
1172
|
+
# @@collection_label_methods. It will use and delete
|
1173
|
+
# the options :label_method and :value_methods when present
|
1174
|
+
#
|
1175
|
+
def detect_label_and_value_method!(collection_or_instance, options = {}) #:nodoc
|
1176
|
+
label = options.delete(:label_method) || detect_label_method(collection_or_instance)
|
1120
1177
|
value = options.delete(:value_method) || :id
|
1121
|
-
|
1122
|
-
collection.map { |o| [send_or_call(label, o), send_or_call(value, o)] }
|
1178
|
+
[label, value]
|
1123
1179
|
end
|
1124
1180
|
|
1125
1181
|
# Detected the label collection method when none is supplied using the
|
@@ -1318,8 +1374,8 @@ module Formtastic #:nodoc:
|
|
1318
1374
|
# <% end %>
|
1319
1375
|
#
|
1320
1376
|
# The above examples use a resource-oriented style of form_for() helper where only the @post
|
1321
|
-
# object is given as an argument, but the generic style is also supported
|
1322
|
-
#
|
1377
|
+
# object is given as an argument, but the generic style is also supported, as are forms with
|
1378
|
+
# inline objects (Post.new) rather than objects with instance variables (@post):
|
1323
1379
|
#
|
1324
1380
|
# <% semantic_form_for :post, @post, :url => posts_path do |f| %>
|
1325
1381
|
# ...
|
@@ -1328,14 +1384,6 @@ module Formtastic #:nodoc:
|
|
1328
1384
|
# <% semantic_form_for :post, Post.new, :url => posts_path do |f| %>
|
1329
1385
|
# ...
|
1330
1386
|
# <% end %>
|
1331
|
-
#
|
1332
|
-
# The shorter, resource-oriented style is most definitely preferred, and has recieved the most
|
1333
|
-
# testing to date.
|
1334
|
-
#
|
1335
|
-
# Please note: Although it's possible to call Rails' built-in form_for() helper without an
|
1336
|
-
# object, all semantic forms *must* have an object (either Post.new or @post), as Formtastic
|
1337
|
-
# has too many dependencies on an ActiveRecord object being present.
|
1338
|
-
#
|
1339
1387
|
module SemanticFormHelper
|
1340
1388
|
@@builder = Formtastic::SemanticFormBuilder
|
1341
1389
|
mattr_accessor :builder
|
@@ -1350,7 +1398,7 @@ module Formtastic #:nodoc:
|
|
1350
1398
|
html_tag
|
1351
1399
|
end
|
1352
1400
|
|
1353
|
-
def
|
1401
|
+
def with_custom_field_error_proc(&block)
|
1354
1402
|
@@default_field_error_proc = ::ActionView::Base.field_error_proc
|
1355
1403
|
::ActionView::Base.field_error_proc = FIELD_ERROR_PROC
|
1356
1404
|
result = yield
|
@@ -1374,7 +1422,7 @@ module Formtastic #:nodoc:
|
|
1374
1422
|
end
|
1375
1423
|
options[:html][:class] = class_names.join(" ")
|
1376
1424
|
|
1377
|
-
|
1425
|
+
with_custom_field_error_proc do
|
1378
1426
|
#{meth}(record_or_name_or_array, *(args << options), &proc)
|
1379
1427
|
end
|
1380
1428
|
end
|