lib/formtastic/helpers/input_helper.rb in formtastic-3.0.0 vs lib/formtastic/helpers/input_helper.rb in formtastic-3.1.0.rc1
- old
+ new
@@ -34,10 +34,13 @@
#
# @see #input
# @see Formtastic::Helpers::InputsHelper#inputs
# @see Formtastic::Helpers::FormHelper#semantic_form_for
module InputHelper
+ INPUT_CLASS_DEPRECATION = 'configure Formtastic::FormBuilder.input_class_finder instead'.freeze
+ private_constant(:INPUT_CLASS_DEPRECATION)
+
include Formtastic::Helpers::Reflection
include Formtastic::Helpers::FileColumnDetection
# Returns a chunk of HTML markup for a given `method` on the form object, wrapped in
# an `<li>` wrapper tag with appropriate `class` and `id` attribute hooks for CSS and JS.
@@ -84,30 +87,30 @@
# defined in a module of the same name. Detailed documentation for each input style and it's
# supported options is available on the `*_input` method in each module (links provided below).
#
# Available input styles:
#
- # * `:boolean` (see {Inputs::BooleanInput})
- # * `:check_boxes` (see {Inputs::CheckBoxesInput})
- # * `:color` (see {Inputs::ColorInput})
- # * `:country` (see {Inputs::CountryInput})
- # * `:datetime_select` (see {Inputs::DatetimeSelectInput})
- # * `:date_select` (see {Inputs::DateSelectInput})
- # * `:email` (see {Inputs::EmailInput})
- # * `:file` (see {Inputs::FileInput})
- # * `:hidden` (see {Inputs::HiddenInput})
- # * `:number` (see {Inputs::NumberInput})
- # * `:password` (see {Inputs::PasswordInput})
- # * `:phone` (see {Inputs::PhoneInput})
- # * `:radio` (see {Inputs::RadioInput})
- # * `:search` (see {Inputs::SearchInput})
- # * `:select` (see {Inputs::SelectInput})
- # * `:string` (see {Inputs::StringInput})
- # * `:text` (see {Inputs::TextInput})
- # * `:time_zone` (see {Inputs::TimeZoneInput})
- # * `:time_select` (see {Inputs::TimeSelectInput})
- # * `:url` (see {Inputs::UrlInput})
+ # * `:boolean` (see {Inputs::BooleanInput})
+ # * `:check_boxes` (see {Inputs::CheckBoxesInput})
+ # * `:color` (see {Inputs::ColorInput})
+ # * `:country` (see {Inputs::CountryInput})
+ # * `:datetime_select` (see {Inputs::DatetimeSelectInput})
+ # * `:date_select` (see {Inputs::DateSelectInput})
+ # * `:email` (see {Inputs::EmailInput})
+ # * `:file` (see {Inputs::FileInput})
+ # * `:hidden` (see {Inputs::HiddenInput})
+ # * `:number` (see {Inputs::NumberInput})
+ # * `:password` (see {Inputs::PasswordInput})
+ # * `:phone` (see {Inputs::PhoneInput})
+ # * `:radio` (see {Inputs::RadioInput})
+ # * `:search` (see {Inputs::SearchInput})
+ # * `:select` (see {Inputs::SelectInput})
+ # * `:string` (see {Inputs::StringInput})
+ # * `:text` (see {Inputs::TextInput})
+ # * `:time_zone` (see {Inputs::TimeZoneInput})
+ # * `:time_select` (see {Inputs::TimeSelectInput})
+ # * `:url` (see {Inputs::UrlInput})
#
# Calling `:as => :string` (for example) will call `#to_html` on a new instance of
# `Formtastic::Inputs::StringInput`. Before this, Formtastic will try to instantiate a top-level
# namespace StringInput, meaning you can subclass and modify `Formtastic::Inputs::StringInput`
# in `app/inputs/`. This also means you can create your own new input types in `app/inputs/`.
@@ -231,11 +234,11 @@
# last_name: "Smith"
#
# @todo Many many more examples. Some of the detail probably needs to be pushed out to the relevant methods too.
# @todo More i18n examples.
def input(method, options = {})
- method = method.to_sym if method.is_a?(String)
+ method = method.to_sym
options = options.dup # Allow options to be shared without being tainted by Formtastic
options[:as] ||= default_input_type(method, options)
klass = input_class(options[:as])
@@ -297,19 +300,25 @@
end
end
# Get a column object for a specified attribute method - if possible.
def column_for(method) #:nodoc:
- @object.column_for_attribute(method) if @object.respond_to?(:column_for_attribute)
+ if @object.respond_to?(:column_for_attribute)
+ # Remove deprecation wrapper & review after Rails 5.0 ships
+ ActiveSupport::Deprecation.silence do
+ @object.column_for_attribute(method)
+ end
+ end
end
- # Takes the `:as` option and attempts to return the corresponding input class. In the case of
- # `:as => :string` it will first attempt to find a top level `StringInput` class (to allow the
- # application to subclass and modify to suit), falling back to `Formtastic::Inputs::StringInput`.
+ # Takes the `:as` option and attempts to return the corresponding input
+ # class. In the case of `:as => :awesome` it will first attempt to find a
+ # top level `AwesomeInput` class (to allow the application to subclass
+ # and modify to suit), falling back to `Formtastic::Inputs::AwesomeInput`.
#
- # This also means that the application can define it's own custom inputs in the top level
- # namespace (eg `DatepickerInput`).
+ # Custom input namespaces to look into can be configured via the
+ # .input_namespaces +FormBuilder+ configuration setting.
#
# @param [Symbol] as A symbol representing the type of input to render
# @raise [Formtastic::UnknownInputError] An appropriate input class could not be found
# @return [Class] An input class constant
#
@@ -317,33 +326,51 @@
# input_class(:string) #=> Formtastic::Inputs::StringInput
# input_class(:date) #=> Formtastic::Inputs::DateInput
#
# @example When a top-level class is found
# input_class(:string) #=> StringInput
- # input_class(:awesome) #=> AwesomeInput
+ # input_class(:awesome) #=> AwesomeInput
+
+ def namespaced_input_class(as)
+ @input_class_finder ||= input_class_finder.new(self)
+ @input_class_finder.find(as)
+ rescue Formtastic::InputClassFinder::NotFoundError
+ raise Formtastic::UnknownInputError, "Unable to find input #{$!.message}"
+ end
+
+ # @api private
+ # @deprecated Use {#namespaced_input_class} instead.
def input_class(as)
+ return namespaced_input_class(as) if input_class_finder
+
+ input_class_deprecation_warning(__method__)
+
@input_classes_cache ||= {}
@input_classes_cache[as] ||= begin
config = Rails.application.config
use_const_defined = config.respond_to?(:eager_load) ? config.eager_load : config.cache_classes
use_const_defined ? input_class_with_const_defined(as) : input_class_by_trying(as)
end
end
-
+
+ # @api private
+ # @deprecated Use {InputClassFinder#find} instead.
# prevent exceptions in production environment for better performance
def input_class_with_const_defined(as)
input_class_name = custom_input_class_name(as)
if ::Object.const_defined?(input_class_name)
input_class_name.constantize
elsif Formtastic::Inputs.const_defined?(input_class_name)
- standard_input_class_name(as).constantize
+ standard_input_class_name(as).constantize
else
raise Formtastic::UnknownInputError, "Unable to find input class #{input_class_name}"
end
end
-
+
+ # @api private
+ # @deprecated Use {InputClassFinder#find} instead.
# use auto-loading in development environment
def input_class_by_trying(as)
begin
custom_input_class_name(as).constantize
rescue NameError
@@ -351,17 +378,30 @@
end
rescue NameError
raise Formtastic::UnknownInputError, "Unable to find input class for #{as}"
end
+ # @api private
+ # @deprecated Use {InputClassFinder#class_name} instead.
# :as => :string # => StringInput
def custom_input_class_name(as)
+ input_class_deprecation_warning(__method__)
"#{as.to_s.camelize}Input"
end
+ # @api private
+ # @deprecated Use {InputClassFinder#class_name} instead.
# :as => :string # => Formtastic::Inputs::StringInput
def standard_input_class_name(as)
+ input_class_deprecation_warning(__method__)
"Formtastic::Inputs::#{as.to_s.camelize}Input"
+ end
+
+ private
+
+ def input_class_deprecation_warning(method)
+ @input_class_deprecation_warned ||=
+ Formtastic.deprecation.deprecation_warning(method, INPUT_CLASS_DEPRECATION, caller(2))
end
end
end
end