原创作者: hideto
阅读:1960次
评论:0条
更新时间:2011-05-26
ActionView还带有许多helpers,让我们开发起来更快速更顺手,让我们来看看form中常用的一些helper方法
form_helper.rb:
form_for方式引入,form_tag可以丢弃了,因为form_for是对form_tag更简洁更高级的封装
而text_field/password_field/hidden_field/file_field/text_area/check_box/radio_button以及form_options_helpers里的select这八项
form里的基本元素都有方便的helper方法定义,实际上是通过InstanceTag的to_input_field_tag/to_text_area_tag等方法来生成html标签
而InstanceTag的to_input_field_tag/to_text_area_tag等方法又是通过tag_helper.rb里定义的content_tag方法来生成html标签,都很简单
我们可以定制自己的FormBuilder来满足form样式一样等要求,详见每天一剂Rails良药之Creating a Custom Form Builder
form_helper.rb:
module ActionView module Helpers module FormHelper def form_for(object_name, *args, &proc) raise ArgumentError, "Missing block" unless block_given? options = args.last.is_a?(Hash) ? args.pop : {} concat(form_tag(options.delete(:url) || {}, options.delete(:html) || {}), proc.binding) fields_for(object_name, *(args << options), &proc) concat('</form>', proc.binding) end def fields_for(object_name, *args, &block) raise ArgumentError, "Missing block" unless block_given? options = args.last.is_a?(Hash) ? args.pop : {} object = args.first builder = options[:builder] || ActionView::Base.default_form_builder yield builder.new(object_name, object, self, options, block) end def text_field(object_name, method, options = {}) InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("text", options) end def password_field(object_name, method, options = {}) InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("password", options) end def hidden_field(object_name, method, options = {}) InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("hidden", options) end def file_field(object_name, method, options = {}) InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("file", options) end def text_area(object_name, method, options = {}) InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_text_area_tag(options) end def check_box(object_name, method, options = {}, checked_value = "1", unchecked_value = "0") InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_check_box_tag(options, checked_value, unchecked_value) end def radio_button(object_name, method, tag_value, options = {}) InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_radio_button_tag(tag_value, options) end end class InstanceTag def to_input_field_tag(field_type, options = {}) options = options.stringify_keys options["size"] ||= options["maxlength"] || DEFAULT_FIELD_OPTIONS["size"] options = DEFAULT_FIELD_OPTIONS.merge(options) if field_type == "hidden" options.delete("size") end options["type"] = field_type options["value"] ||= value_before_type_cast(object) unless field_type == "file" add_default_name_and_id(options) tag("input", options) end def to_radio_button_tag(tag_value, options = {}) options = DEFAULT_RADIO_OPTIONS.merge(options.stringify_keys) options["type"] = "radio" options["value"] = tag_value if options.has_key?("checked") cv = options.delete "checked" checked = cv == true || cv == "checked" else checked = self.class.radio_button_checked?(value(object), tag_value) end options["checked"] = "checked" if checked pretty_tag_value = tag_value.to_s.gsub(/\s/, "_").gsub(/\W/, "").downcase options["id"] ||= defined?(@auto_index) ? "#{@object_name}_#{@auto_index}_#{@method_name}_#{pretty_tag_value}" : "#{@object_name}_#{@method_name}_#{pretty_tag_value}" add_default_name_and_id(options) tag("input", options) end def to_text_area_tag(options = {}) options = DEFAULT_TEXT_AREA_OPTIONS.merge(options.stringify_keys) add_default_name_and_id(options) if size = options.delete("size") options["cols"], options["rows"] = size.split("x") end content_tag("textarea", html_escape(options.delete('value') || value_before_type_cast(object)), options) end def to_check_box_tag(options = {}, checked_value = "1", unchecked_value = "0") options = options.stringify_keys options["type"] = "checkbox" options["value"] = checked_value if options.has_key?("checked") cv = options.delete "checked" checked = cv == true || cv == "checked" else checked = self.class.check_box_checked?(value(object), checked_value) end options["checked"] = "checked" if checked add_default_name_and_id(options) tag("input", options) << tag("input", "name" => options["name"], "type" => "hidden", "value" => unchecked_value) end end class FormBuilder class_inheritable_accessor :field_helpers self.field_helpers = (FormHelper.instance_methods - ['form_for']) attr_accessor :object_name, :object, :options def initialize(object_name, object, template, options, proc) @object_name, @object, @template, @options, @proc = object_name, object, template, options, proc end (field_helpers - %w(check_box radio_button)).each do |selector| src = <<-end_src def #{selector}(method, options = {}) @template.send(#{selector.inspect}, @object_name, method, options.merge(:object => @object)) end end_src class_eval src, __FILE__, __LINE__ end def check_box(method, options = {}, checked_value = "1", unchecked_value = "0") @template.check_box(@object_name, method, options.merge(:object => @object), checked_value, unchecked_value) end def radio_button(method, tag_value, options = {}) @template.radio_button(@object_name, method, tag_value, options.merge(:object => @object)) end end end class Base cattr_accessor :default_form_builder self.default_form_builder = ::ActionView::Helpers::FormBuilder end end
form_for方式引入,form_tag可以丢弃了,因为form_for是对form_tag更简洁更高级的封装
<% form_for :person, @person, :url => { :action => "update" } do |f| %> First name: <%= f.text_field :first_name %> Last name : <%= f.text_field :last_name %> Biography : <%= f.text_area :biography %> Admin? : <%= f.check_box :admin %> <% end %>
而text_field/password_field/hidden_field/file_field/text_area/check_box/radio_button以及form_options_helpers里的select这八项
form里的基本元素都有方便的helper方法定义,实际上是通过InstanceTag的to_input_field_tag/to_text_area_tag等方法来生成html标签
而InstanceTag的to_input_field_tag/to_text_area_tag等方法又是通过tag_helper.rb里定义的content_tag方法来生成html标签,都很简单
我们可以定制自己的FormBuilder来满足form样式一样等要求,详见每天一剂Rails良药之Creating a Custom Form Builder
评论 共 0 条 请登录后发表评论