简体   繁体   中英

Adding rails 3 form helpers to rails 2

I would like to add the number_field form helper that exists in rails 3 to my rails 2.3.15 app, but i'm having trouble extending the module.

These are the methods I need from rails 3

class InstanceTag
    def to_number_field_tag(field_type, options = {})
        options = options.stringify_keys
        if range = options.delete("in") || options.delete("within")
          options.update("min" => range.min, "max" => range.max)
        end
        to_input_field_tag(field_type, options)
      end
end

def number_field(object_name, method, options = {})
        InstanceTag.new(object_name, method, self, options.delete(:object)).to_number_field_tag("number", options)
end

def number_field_tag(name, value = nil, options = {})
        options = options.stringify_keys
        options["type"] ||= "number"
        if range = options.delete("in") || options.delete("within")
          options.update("min" => range.min, "max" => range.max)
        end
        text_field_tag(name, value, options)
end

I'm adding this to a module which i include in my application helper. The to_number_field_tag method is easy because i can just open the class and add the override.

The FormHelper module methods I'm having trouble with because i can't quite figure out the ancestors chain and don't know how to scope my override. I don't know how to make it work basically.

My problem above was that i was not overriding the FormBuilder. Here is a solution for those who might need this in the future.

Rather than just implementing the type="number" input type, i decided to make a generic helper for all new HTML5 inputs. I place this code in an overrides file which i include in application_helper.rb .

# file 'rails_overrides.rb`

ActionView::Helpers::InstanceTag.class_eval do
    def to_custom_field_tag(field_type, options = {})
        options = options.stringify_keys
        to_input_field_tag(field_type, options)
      end
end

ActionView::Helpers::FormBuilder.class_eval do
    def custom_field(method, options = {}, html_options = {})
        @template.custom_field(@object_name, method, objectify_options(options), html_options)
    end
end

# form.custom_field helper to use in views
def custom_field(object_name, method, options = {}, html_options = {})
    ActionView::Helpers::InstanceTag.new(object_name, method, self, options.delete(:object)).to_custom_field_tag(options.delete(:type), options)
end

# form.custom_field_tag helper to use in views
def custom_field_tag(name, value = nil, options = {})
    options = options.stringify_keys
    # potential sanitation. Taken from rails3 code for number_field
    if range = options.delete("in") || options.delete("within")
      options.update("min" => range.min, "max" => range.max)
    end
    text_field_tag(name, value, options)
end

Then to use this in your views:

<% form_for... do |form| %>
    <%= form.custom_field :user_age, :type=>"number", :min=>"0", :max=>"1000" %>
    <%= form.custom_field :email, :type=>"email", :required=>"true" %>
<% end %>

Which will generate an <input type='number', and an <input type='email'

If you have a custom form builder, you will need to expand/override that as well. Namespace may vary, but most standard is like this:

MySpecialFormBuilder.class_eval do
    def custom_field(method, options = {}, html_options = {})
        ...custom form builder implementation
    end
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM