Permalink
Browse files

Revert "This reverts commit 440bd2d."

This reverts commit e4fc2be.
  • Loading branch information...
justinfrench committed Nov 21, 2009
1 parent e4fc2be commit 17f6668038a323ee04c39f128b1cc2b8d70391cc
View
@@ -148,7 +148,7 @@ If you want to customize the label text, or render some hint text below the fiel
<pre>
<% semantic_form_for @post do |form| %>
- <% form.inputs :name => "Basic", :id => "basic" do %>
+ <% form.inputs "Basic", :id => "basic" do %>
<%= form.input :title %>
<%= form.input :body %>
<% end %>
@@ -324,11 +324,11 @@ Formtastic supports localized *labels*, *hints*, *legends*, *actions* using the
*4. Localized titles (a.k.a. legends):*
-_Note: Slightly different because Formtastic can't guess how you group fields in a form._
+_Note: Slightly different because Formtastic can't guess how you group fields in a form. Legend text can be set with first (as in the sample below) specified value, or :name/:title options - depending on what flavor is preferred._
<pre>
<% semantic_form_for @post do |form| %>
- <% form.inputs :title => :post_details do %> # => :title => "Post details"
+ <% form.inputs :post_details do %> # => :title => "Post details"
# ...
<% end %>
# ...
View
@@ -7,7 +7,7 @@ class SemanticFormBuilder < ActionView::Helpers::FormBuilder
@@default_text_field_size = 50
@@all_fields_required_by_default = true
@@include_blank_for_select_by_default = true
- @@required_string = proc { %{<abbr title="#{I18n.t 'formtastic.required', :default => 'required'}">*</abbr>} }
+ @@required_string = proc { %{<abbr title="#{::I18n.t 'formtastic.required', :default => 'required'}">*</abbr>} }
@@optional_string = ''
@@inline_errors = :sentence
@@label_str_method = :humanize
@@ -22,6 +22,8 @@ class SemanticFormBuilder < ActionView::Helpers::FormBuilder
:required_string, :optional_string, :inline_errors, :label_str_method, :collection_label_methods,
:inline_order, :file_methods, :priority_countries, :i18n_lookups_by_default, :default_commit_button_accesskey
+ RESERVED_COLUMNS = [:created_at, :updated_at, :created_on, :updated_on, :lock_version, :version]
+
I18N_SCOPES = [ '{{model}}.{{action}}.{{attribute}}',
'{{model}}.{{attribute}}',
'{{attribute}}']
@@ -136,11 +138,16 @@ def input(method, options = {})
# <%= form.inputs %>
# <% end %>
#
+ # With a few arguments:
+ # <% semantic_form_for @post do |form| %>
+ # <%= form.inputs "Post details", :title, :body %>
+ # <% end %>
+ #
# === Options
#
- # All options (with the exception of :name) are passed down to the fieldset as HTML
- # attributes (id, class, style, etc). If provided, the :name option is passed into a
- # legend tag inside the fieldset (otherwise a legend is not generated).
+ # All options (with the exception of :name/:title) are passed down to the fieldset as HTML
+ # attributes (id, class, style, etc). If provided, the :name/:title option is passed into a
+ # legend tag inside the fieldset.
#
# # With a block:
# <% semantic_form_for @post do |form| %>
@@ -154,6 +161,11 @@ def input(method, options = {})
# <%= form.inputs :title, :body, :name => "Create a new post", :style => "border:1px;" %>
# <% end %>
#
+ # # ...or the equivalent:
+ # <% semantic_form_for @post do |form| %>
+ # <%= form.inputs "Create a new post", :title, :body, :style => "border:1px;" %>
+ # <% end %>
+ #
# === It's basically a fieldset!
#
# Instead of hard-coding fieldsets & legends into your form to logically group related fields,
@@ -168,6 +180,9 @@ def input(method, options = {})
# <%= f.input :created_at %>
# <%= f.input :user_id, :label => "Author" %>
# <% end %>
+ # <% f.inputs "Extra" do %>
+ # <%= f.input :update_at %>
+ # <% end %>
# <% end %>
#
# # Output:
@@ -185,6 +200,12 @@ def input(method, options = {})
# <li class="select">...</li>
# </ol>
# </fieldset>
+ # <fieldset class="inputs">
+ # <legend><span>Extra</span></legend>
+ # <ol>
+ # <li class="datetime">...</li>
+ # </ol>
+ # </fieldset>
# </form>
#
# === Nested attributes
@@ -232,17 +253,19 @@ def inputs(*args, &block)
if html_options[:for]
inputs_for_nested_attributes(args, html_options, &block)
elsif block_given?
- field_set_and_list_wrapping(html_options, &block)
+ field_set_and_list_wrapping(*(args << html_options), &block)
else
if @object && args.empty?
- args = @object.class.reflections.map { |n,_| n if _.macro == :belongs_to }
- args += @object.class.content_columns.map(&:name)
- args -= %w[created_at updated_at created_on updated_on lock_version version]
+ args = self.association_columns(:belongs_to)
+ args += self.content_columns
+ args -= RESERVED_COLUMNS
args.compact!
end
- contents = args.map { |method| input(method.to_sym) }
-
- field_set_and_list_wrapping(html_options, contents)
+ legend = args.shift if args.first.is_a?(::String)
+ contents = args.collect { |method| input(method.to_sym) }
+ args.unshift(legend) if legend.present?
+
+ field_set_and_list_wrapping(*(args << html_options), contents)
end
end
alias :input_field_set :inputs
@@ -326,7 +349,7 @@ def commit_button(*args)
#
def semantic_fields_for(record_or_name_or_array, *args, &block)
opts = args.extract_options!
- opts.merge!(:builder => Formtastic::SemanticFormHelper.builder)
+ opts.merge!(:builder => ::Formtastic::SemanticFormHelper.builder)
args.push(opts)
fields_for(record_or_name_or_array, *args, &block)
end
@@ -396,6 +419,32 @@ def inline_errors_for(method, options=nil) #:nodoc:
protected
+ # Collects content columns (non-relation columns) for the current form object class.
+ #
+ def content_columns
+ if @object.present?
+ @object.class.name.constantize.content_columns.collect { |c| c.name.to_sym }.compact
+ else
+ @object_name.to_s.classify.constantize.content_columns.collect { |c| c.name.to_sym }.compact rescue []
+ end
+ end
+
+ # Collects association columns (relation columns) for the current form object class.
+ #
+ def association_columns(*by_associations)
+ if @object.present?
+ @object.class.reflections.collect do |name, _|
+ if by_associations.present?
+ name if by_associations.include?(_.macro)
+ else
+ name
+ end
+ end.compact
+ else
+ []
+ end
+ end
+
# Prepare options to be sent to label
#
def options_for_label(options)
@@ -819,7 +868,7 @@ def time_input(method, options)
#
def date_or_datetime_input(method, options)
position = { :year => 1, :month => 2, :day => 3, :hour => 4, :minute => 5, :second => 6 }
- i18n_date_order = I18n.translate(:'date.order').is_a?(Array) ? I18n.translate(:'date.order') : nil
+ i18n_date_order = ::I18n.translate(:'date.order').is_a?(Array) ? ::I18n.translate(:'date.order') : nil
inputs = options.delete(:order) || i18n_date_order || [:year, :month, :day]
time_inputs = [:hour, :minute]
@@ -842,7 +891,7 @@ def date_or_datetime_input(method, options)
hidden_fields_capture << template.hidden_field_tag("#{@object_name}[#{field_name}]", (hidden_value || 1), :id => html_id)
else
opts = set_options(options).merge(:prefix => @object_name, :field_name => field_name)
- item_label_text = I18n.t(input.to_s, :default => input.to_s.humanize, :scope => [:datetime, :prompts])
+ item_label_text = ::I18n.t(input.to_s, :default => input.to_s.humanize, :scope => [:datetime, :prompts])
list_items_capture << template.content_tag(:li,
template.content_tag(:label, item_label_text, :for => html_id) +
@@ -1050,12 +1099,29 @@ def required_or_optional_string(required) #:nodoc:
#
# f.inputs :name => 'Task #%i', :for => :tasks
#
+ # or the shorter equivalent:
+ #
+ # f.inputs 'Task #%i', :for => :tasks
+ #
# And it will generate a fieldset for each task with legend 'Task #1', 'Task #2',
# 'Task #3' and so on.
#
- def field_set_and_list_wrapping(html_options, contents='', &block) #:nodoc:
+ # Note: Special case for the inline inputs (non-block):
+ # f.inputs "My little legend", :title, :body, :author # Explicit legend string => "My little legend"
+ # f.inputs :my_little_legend, :title, :body, :author # Localized (118n) legend with I18n key => I18n.t(:my_little_legend, ...)
+ # f.inputs :title, :body, :author # First argument is a column => (no legend)
+ #
+ def field_set_and_list_wrapping(*args, &block) #:nodoc:
+ contents = args.last.is_a?(::Hash) ? '' : args.pop.flatten
+ html_options = args.extract_options!
+
html_options[:name] ||= html_options.delete(:title)
- html_options[:name] = localized_string(html_options[:name], html_options[:name], :title) if html_options[:name].is_a?(Symbol)
+ if html_options[:name].blank?
+ valid_name_classes = [::String, ::Symbol]
+ valid_name_classes.delete(::Symbol) if !block_given? && (args.first.is_a?(::Symbol) && self.content_columns.include?(args.first))
+ html_options[:name] = args.shift if valid_name_classes.any? { |valid_name_class| args.first.is_a?(valid_name_class) }
+ end
+ html_options[:name] = localized_string(html_options[:name], html_options[:name], :title) if html_options[:name].is_a?(::Symbol)
legend = html_options.delete(:name).to_s
legend %= parent_child_index(html_options[:parent]) if html_options[:parent]
@@ -1142,7 +1208,7 @@ def find_collection_for_column(column, options)
collection = find_raw_collection_for_column(column, options)
# Return if we have an Array of strings, fixnums or arrays
- return collection if collection.instance_of?(Array) &&
+ return collection if (collection.instance_of?(Array) || collection.instance_of?(Range)) &&
[Array, Fixnum, String, Symbol].include?(collection.first.class)
label, value = detect_label_and_value_method!(collection, options)
@@ -1189,8 +1255,8 @@ def detect_label_method(collection) #:nodoc:
# is provided.
#
def create_boolean_collection(options)
- options[:true] ||= I18n.t('yes', :default => 'Yes', :scope => [:formtastic])
- options[:false] ||= I18n.t('no', :default => 'No', :scope => [:formtastic])
+ options[:true] ||= ::I18n.t(:yes, :default => 'Yes', :scope => [:formtastic])
+ options[:false] ||= ::I18n.t(:no, :default => 'No', :scope => [:formtastic])
options[:value_as_class] = true unless options.key?(:value_as_class)
[ [ options.delete(:true), true], [ options.delete(:false), false ] ]
@@ -1341,14 +1407,12 @@ def send_or_call(duck, object)
end
end
- private
-
- def set_include_blank(options)
- unless options.key?(:include_blank) || options.key?(:prompt)
- options[:include_blank] = @@include_blank_for_select_by_default
- end
- options
+ def set_include_blank(options)
+ unless options.key?(:include_blank) || options.key?(:prompt)
+ options[:include_blank] = @@include_blank_for_select_by_default
end
+ options
+ end
end
@@ -1385,7 +1449,7 @@ def set_include_blank(options)
# ...
# <% end %>
module SemanticFormHelper
- @@builder = Formtastic::SemanticFormBuilder
+ @@builder = ::Formtastic::SemanticFormBuilder
mattr_accessor :builder
@@default_field_error_proc = nil
View
@@ -1,7 +1,7 @@
en:
formtastic:
- "yes": 'Yes'
- "no": 'No'
+ :yes: 'Yes'
+ :no: 'No'
create: 'Create'
save: 'Save'
submit: 'Submit'
View
@@ -46,12 +46,12 @@
describe "its accesskey" do
it 'should allow nil default' do
- Formtastic::SemanticFormBuilder.default_commit_button_accesskey.should == nil
+ ::Formtastic::SemanticFormBuilder.default_commit_button_accesskey.should == nil
output_buffer.should_not have_tag('li.commit input[@accesskey]')
end
it 'should use the default if set' do
- Formtastic::SemanticFormBuilder.default_commit_button_accesskey = 's'
+ ::Formtastic::SemanticFormBuilder.default_commit_button_accesskey = 's'
@new_post.stub!(:new_record?).and_return(false)
semantic_form_for(@new_post) do |builder|
concat(builder.commit_button('text', :button_html => {}))
@@ -60,7 +60,7 @@
end
it 'should use the value set in options over the default' do
- Formtastic::SemanticFormBuilder.default_commit_button_accesskey = 's'
+ ::Formtastic::SemanticFormBuilder.default_commit_button_accesskey = 's'
@new_post.stub!(:new_record?).and_return(false)
semantic_form_for(@new_post) do |builder|
concat(builder.commit_button('text', :accesskey => 'o'))
@@ -70,7 +70,7 @@
end
it 'should use the value set in button_html over options' do
- Formtastic::SemanticFormBuilder.default_commit_button_accesskey = 's'
+ ::Formtastic::SemanticFormBuilder.default_commit_button_accesskey = 's'
@new_post.stub!(:new_record?).and_return(false)
semantic_form_for(@new_post) do |builder|
concat(builder.commit_button('text', :accesskey => 'o', :button_html => {:accesskey => 't'}))
@@ -81,7 +81,7 @@
end
after do
- Formtastic::SemanticFormBuilder.default_commit_button_accesskey = nil
+ ::Formtastic::SemanticFormBuilder.default_commit_button_accesskey = nil
end
end
@@ -5,7 +5,7 @@
include FormtasticSpecHelper
- class MyCustomFormBuilder < Formtastic::SemanticFormBuilder
+ class MyCustomFormBuilder < ::Formtastic::SemanticFormBuilder
def awesome_input(method, options)
self.text_field(method)
end
@@ -17,28 +17,28 @@ def awesome_input(method, options)
end
it 'is the Formtastic::SemanticFormBuilder by default' do
- Formtastic::SemanticFormHelper.builder.should == Formtastic::SemanticFormBuilder
+ ::Formtastic::SemanticFormHelper.builder.should == ::Formtastic::SemanticFormBuilder
end
it 'can be configured to use your own custom form builder' do
# Set it to a custom builder class
- Formtastic::SemanticFormHelper.builder = MyCustomFormBuilder
- Formtastic::SemanticFormHelper.builder.should == MyCustomFormBuilder
+ ::Formtastic::SemanticFormHelper.builder = MyCustomFormBuilder
+ ::Formtastic::SemanticFormHelper.builder.should == MyCustomFormBuilder
# Reset it to the default
- Formtastic::SemanticFormHelper.builder = Formtastic::SemanticFormBuilder
- Formtastic::SemanticFormHelper.builder.should == Formtastic::SemanticFormBuilder
+ ::Formtastic::SemanticFormHelper.builder = ::Formtastic::SemanticFormBuilder
+ ::Formtastic::SemanticFormHelper.builder.should == ::Formtastic::SemanticFormBuilder
end
describe "when using a custom builder" do
before do
@new_post.stub!(:title)
- Formtastic::SemanticFormHelper.builder = MyCustomFormBuilder
+ ::Formtastic::SemanticFormHelper.builder = MyCustomFormBuilder
end
after do
- Formtastic::SemanticFormHelper.builder = Formtastic::SemanticFormBuilder
+ ::Formtastic::SemanticFormHelper.builder = ::Formtastic::SemanticFormBuilder
end
describe "semantic_form_for" do
View
@@ -157,15 +157,15 @@ def it_should_apply_error_logic_for_input_type(type)
end
it 'should render a paragraph for the errors' do
- Formtastic::SemanticFormBuilder.inline_errors = :sentence
+ ::Formtastic::SemanticFormBuilder.inline_errors = :sentence
semantic_form_for(@new_post) do |builder|
concat(builder.input(:title, :as => type))
end
output_buffer.should have_tag('form li.error p.inline-errors')
end
it 'should not display an error list' do
- Formtastic::SemanticFormBuilder.inline_errors = :list
+ ::Formtastic::SemanticFormBuilder.inline_errors = :list
semantic_form_for(@new_post) do |builder|
concat(builder.input(:title, :as => type))
end
@@ -399,7 +399,7 @@ def it_should_use_the_collection_when_provided(as, countable)
end
describe 'when the :label_method option is not provided' do
- Formtastic::SemanticFormBuilder.collection_label_methods.each do |label_method|
+ ::Formtastic::SemanticFormBuilder.collection_label_methods.each do |label_method|
describe "when the collection objects respond to #{label_method}" do
before do
Oops, something went wrong.

0 comments on commit 17f6668

Please sign in to comment.