Add SimpleForm.custom_inputs_namespaces config to allow namespacing custom input classes

This commit is contained in:
vala 2014-06-05 12:46:12 +02:00
parent e8660478f9
commit 5ae526ed3c
6 changed files with 84 additions and 1 deletions

View File

@ -581,6 +581,28 @@ class CollectionSelectInput < SimpleForm::Inputs::CollectionSelectInput
end
```
If needed, you can namespace your custom inputs in a module and tell **SimpleForm** to look for
their definition in this module. This can avoid conflicts with other form libraries (like Formtastic) that look up
the global context to find inputs definition too.
```ruby
# app/inputs/custom_inputs/numeric_input
module CustomInputs
class NumericInput < SimpleForm::Inputs::NumericInput
def input_html_classes
super.push('no-spinner')
end
end
end
```
And in the **SimpleForm** initializer :
```ruby
# config/simple_form.rb
config.custom_inputs_namespaces << "CustomInputs"
```
## Custom form builder
You can create a custom form builder that uses **Simple Form**.

View File

@ -131,6 +131,10 @@ SimpleForm.setup do |config|
# type as key and the wrapper that will be used for all inputs with specified type.
# config.wrapper_mappings = { string: :prepend }
# Namespaces where SimpleForm should look for custom input classes that
# override default inputs.
# config.custom_inputs_namespaces << "CustomInputs"
# Default priority for time_zone inputs.
# config.time_zone_priority = nil

View File

@ -130,6 +130,14 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
mattr_accessor :wrapper_mappings
@@wrapper_mappings = nil
# Namespaces where SimpleForm should look for custom input classes that override
# default inputs. Namespaces are given as string to allow lazy loading inputs
# e.g. config.custom_inputs_namespaces << "CustomInputs"
# will try to find CustomInputs::NumericInput when an :integer
# field is called
mattr_accessor :custom_inputs_namespaces
@@custom_inputs_namespaces = []
# Default priority for time_zone inputs.
mattr_accessor :time_zone_priority
@@time_zone_priority = nil

View File

@ -567,6 +567,7 @@ module SimpleForm
else
camelized = "#{input_type.to_s.camelize}Input"
attempt_mapping(camelized, Object) || attempt_mapping(camelized, self.class) ||
attempt_mapping_with_custom_namespace(camelized) ||
raise("No input found for #{input_type}")
end
end
@ -604,7 +605,9 @@ module SimpleForm
def mapping_override(klass)
name = klass.name
if name =~ /^SimpleForm::Inputs/
attempt_mapping name.split("::").last, Object
input_name = name.split("::").last
attempt_mapping(input_name, Object) ||
attempt_mapping_with_custom_namespace(input_name)
end
end
@ -617,5 +620,17 @@ module SimpleForm
raise if e.message !~ /#{mapping}$/
end
end
def attempt_mapping_with_custom_namespace(input_name)
SimpleForm.custom_inputs_namespaces.each do |namespace|
camelized = [namespace, input_name].join("::")
if (mapping = attempt_mapping(camelized, Object))
return mapping
end
end
nil
end
end
end

View File

@ -14,6 +14,8 @@ class DiscoveryTest < ActionView::TestCase
Object.send :remove_const, :CustomizedInput
Object.send :remove_const, :DeprecatedInput
Object.send :remove_const, :CollectionSelectInput
CustomInputs.send :remove_const, :PasswordInput
CustomInputs.send :remove_const, :NumericInput
end
end
end
@ -61,6 +63,24 @@ class DiscoveryTest < ActionView::TestCase
end
end
test 'builder discovers new inputs from configured namespaces if not cached' do
discovery do
swap SimpleForm, custom_inputs_namespaces: ['CustomInputs'] do
with_form_for @user, :password, as: :password
assert_select 'form input#user_password.password-custom-input'
end
end
end
test 'builder discovers new inputs from top level namespace before the ones from configured namespaces' do
discovery do
swap SimpleForm, custom_inputs_namespaces: ['CustomInputs'] do
with_form_for @user, :age
assert_no_select 'form input#user_age.numeric-custom-input'
end
end
end
test 'new inputs can override the input_html_options' do
discovery do
with_form_for @user, :active, as: :select

View File

@ -35,3 +35,17 @@ class CollectionSelectInput < SimpleForm::Inputs::CollectionSelectInput
super.push('chosen')
end
end
module CustomInputs
class PasswordInput < SimpleForm::Inputs::PasswordInput
def input_html_classes
super.push('password-custom-input')
end
end
class NumericInput < SimpleForm::Inputs::PasswordInput
def input_html_classes
super.push('numeric-custom-input')
end
end
end