From 9577ca6a19d3e4811d46fbd8b64143e4d55c63be Mon Sep 17 00:00:00 2001 From: Carlos Antonio da Silva Date: Thu, 25 Nov 2010 22:35:38 -0200 Subject: [PATCH] Tidy up custom input mappings --- CHANGELOG.rdoc | 1 + .../simple_form/templates/simple_form.rb | 5 ++++ lib/simple_form.rb | 6 +++++ lib/simple_form/form_builder.rb | 20 ++++------------ test/form_builder_test.rb | 23 +++++++++++++------ 5 files changed, 32 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc index 41b0a6d5..d4753ed6 100644 --- a/CHANGELOG.rdoc +++ b/CHANGELOG.rdoc @@ -11,6 +11,7 @@ * Add SimpleForm.translate as an easy way to turn off SimpleForm internal translations * Add :disabled option for all inputs (by github.com/fabiob) * Add collection wrapper tag and item wrapper tag to wrap elements in collection helpers - radio / check boxes + * Add SimpleForm.input_mappings to allow configuring custom mappings for inputs (by github.com/TMaYaD) * bug fix * Search for validations on both association and attribute diff --git a/lib/generators/simple_form/templates/simple_form.rb b/lib/generators/simple_form/templates/simple_form.rb index 307bb660..01d4eb3a 100644 --- a/lib/generators/simple_form/templates/simple_form.rb +++ b/lib/generators/simple_form/templates/simple_form.rb @@ -55,6 +55,11 @@ SimpleForm.setup do |config| # Whether attributes are required by default (or not). Default is true. # config.required_by_default = true + # Custom mappings for input types. This should be a hash containing a regexp + # to match as key, and the input type that will be used when the field name + # matches the regexp as value. + # config.input_mappings = { /count/ => :integer } + # Collection of methods to detect if a file type was given. # config.file_methods = [ :file?, :public_filename ] diff --git a/lib/simple_form.rb b/lib/simple_form.rb index 682e9e6d..978d69e1 100644 --- a/lib/simple_form.rb +++ b/lib/simple_form.rb @@ -87,6 +87,12 @@ module SimpleForm mattr_accessor :file_methods @@file_methods = [ :mounted_as, :file?, :public_filename ] + # Custom mappings for input types. This should be a hash containing a regexp + # to match as key, and the input type that will be used when the field name + # matches the regexp as value, such as { /count/ => :integer }. + mattr_accessor :input_mappings + @@input_mappings = nil + # Default priority for time_zone inputs. mattr_accessor :time_zone_priority @@time_zone_priority = nil diff --git a/lib/simple_form/form_builder.rb b/lib/simple_form/form_builder.rb index 5ee388b8..579122b8 100644 --- a/lib/simple_form/form_builder.rb +++ b/lib/simple_form/form_builder.rb @@ -13,8 +13,6 @@ module SimpleForm map_type :country, :time_zone, :to => SimpleForm::Inputs::PriorityInput map_type :boolean, :to => SimpleForm::Inputs::BooleanInput - @@custom_matchers = Hash.new - # Basic input helper, combines all components in the stack to generate # input html based on options the user define and some guesses through # database column information. By default a call to input will generate @@ -244,16 +242,6 @@ module SimpleForm SimpleForm::ErrorNotification.new(self, options).render end - # Add custom matchers for selecting default input type - # - # == Examples - # - # SimpleForm::FormBuilder.add_matcher( /regexp/ => :input_type ) - # - def self.add_matcher(*args) - @@custom_matchers.reverse_merge!(*args) - end - private # Attempt to guess the better input type given the defined options. By @@ -261,7 +249,7 @@ module SimpleForm # collection is given. def default_input_type(attribute_name, column, options) #:nodoc: return options[:as].to_sym if options[:as] - return :select if options[:collection] + return :select if options[:collection] input_type = column.try(:type) @@ -277,9 +265,9 @@ module SimpleForm when /phone/ then :tel when /url/ then :url else - @@custom_matchers.reduce(nil) { |memo, a| - a[0].match(attribute_name.to_s) ? a[1] : memo - } + SimpleForm.input_mappings.find { |match, type| + attribute_name.to_s =~ match + }.try(:last) if SimpleForm.input_mappings end match || input_type || file_method?(attribute_name) || :string diff --git a/test/form_builder_test.rb b/test/form_builder_test.rb index 9d1bdeeb..867c250e 100644 --- a/test/form_builder_test.rb +++ b/test/form_builder_test.rb @@ -62,6 +62,22 @@ class FormBuilderTest < ActionView::TestCase assert_select 'input#cool' end + test 'builder should allow adding custom input mappings for default input types' do + swap SimpleForm, :input_mappings => { /count$/ => :integer } do + with_form_for @user, :post_count + assert_no_select 'form input#user_post_count.string' + assert_select 'form input#user_post_count.numeric.integer' + end + end + + test 'builder uses the first matching custom input map when more than one match' do + swap SimpleForm, :input_mappings => { /count$/ => :integer, /^post_/ => :password } do + with_form_for @user, :post_count + assert_no_select 'form input#user_post_count.password' + assert_select 'form input#user_post_count.numeric.integer' + end + end + # INPUT TYPES test 'builder should generate text fields for string columns' do with_form_for @user, :name @@ -167,13 +183,6 @@ class FormBuilderTest < ActionView::TestCase assert_select 'form input#user_born_at.string' end - test 'builder should allow adding custom matchers for default input types' do - SimpleForm::FormBuilder.add_matcher( /count/ => :integer ) - with_form_for @user, :post_count - assert_no_select 'form input#user_post_count.string' - assert_select 'form input#user_post_count.numeric.integer' - end - # COMMON OPTIONS test 'builder should allow passing options to input' do with_form_for @user, :name, :input_html => { :class => 'my_input', :id => 'my_input' }